This is DocView.m in view mode; [Download] [Up]
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
* CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
* AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
* ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
* OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
* WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
* WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
* DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* DocView.m
*
* This class handles the scaling of the drawing view. It repositions
* The drawing view within itself if the drawing view is smaller than the
* size of the clip view. The size of the doc view is:
* MAX(clip view frame, drawing view frame).
*
* Version: 2.0
* Author: Ken Fromm
* History:
* 03-07-91 Added this comment.
*/
#import "DocView.h"
#import "DrawingView.h"
#import "rotateprocs.h"
#import <appkit/NXCursor.h>
#import <appkit/NXImage.h>
#import <appkit/Matrix.h>
#import <appkit/ScrollView.h>
#import <dpsclient/wraps.h>
#import <appkit/nextstd.h>
@implementation DocView
/*
* Since there is only one subview its easier to keep track of it as an
* instance variable rather than in the subview list. Returns any the
* previous drawing view.
*/
- addDrawView:subView
{
id oldView;
oldView = drawView;
[oldView removeFromSuperview];
[self addSubview:subView];
drawView = subView;
return oldView;
}
- setZoomControl:anObject
{
zoomControl = anObject;
return self;
}
- zoomControl
{
return zoomControl;
}
- setScale:(float)value
{
scale = value;
return self;
}
- (float) scale
{
return scale;
}
- (BOOL) isZooming
{
return zooming;
}
/*
* This method is overridden from the View class. When the
* user is zooming the cursor rect for the zoom cursor is set
* the the frame of the drawing view.
*/
- resetCursorRects
{
id imageId;
NXPoint hotspot;
NXRect cursorRect, visRect;
if (zooming)
{
if (!zoomCursor)
{
hotspot.x = hotspot.y = 8.0;
imageId = [NXImage newFromSection:"zoom.tiff"];
zoomCursor = [NXCursor newFromImage:imageId];
[zoomCursor setHotSpot:&hotspot];
}
[self getVisibleRect:&visRect];
[drawView getFrame:&cursorRect];
NXIntersectionRect(&visRect, &cursorRect);
[self addCursorRect:&cursorRect cursor:zoomCursor];
}
return self;
}
/*
* Messaged from the zoom matrix. Starts the zoom loop. At the next
* mouse down in the drawing view, the scaleDrawView:toPoint: method
* will be called.
*/
- zoom:sender
{
if (scale != ([sender selectedTag] * 0.01))
{
zooming = YES;
[self setZoomControl:sender];
[self resetCursorRects];
[window makeKeyAndOrderFront:self];
}
return self;
}
- rotateDrawView
{
NXPoint viewPt, windowPt;
NXRect tempRect;
if (drawView)
{
[drawView getVisibleRect:&tempRect];
viewPt.x = tempRect.origin.x + tempRect.size.width/2.0;
viewPt.y = tempRect.origin.y + tempRect.size.height/2.0;
[self getVisibleRect:&tempRect];
windowPt.x = tempRect.origin.x + tempRect.size.width/2.0;
windowPt.y = tempRect.origin.y + tempRect.size.height/2.0;
[self convertPoint:&windowPt toView:nil];
[window disableDisplay];
[self placeDrawView];
[self scrollPoint:&viewPt to:&windowPt];
[window reenableDisplay];
[[window contentView] display];
}
return self;
}
/*
* Sizes the drawing view from the old scale to the newscale.
* The frame of the view is used instead of the bounds because
* the bound will always be the same whereas the frame will
* provide the size in default coordinates.
*/
- sizeDrawViewWithScale:(float) newscale
{
float scalefactor;
NXRect viewFrame;
[drawView getFrame:&viewFrame];
scalefactor = newscale/scale;
[drawView sizeTo:rint(viewFrame.size.width*scalefactor)
:rint(viewFrame.size.height*scalefactor)];
return self;
}
/*
* Scales the drawing view from the old scale to the new scale.
* The scale method is relative so we use the ratio
* of the old scale to the new scale to obtain the scaling factor.
*/
- scaleDrawViewWithScale:(float) newscale
{
float scalefactor;
scalefactor = newscale/scale;
[drawView scale:scalefactor :scalefactor];
return self;
}
/*
* Place the drawing view in the center of the doc view
* if it is smaller than the size of the ClipView.
*/
- placeDrawView
{
int margin;
float rads;
NXSize contSize, newSize, insetSize, delta;
NXRect tempRect, viewFrame;
if (drawView)
{
margin = (int) 4 * OFFSET * scale;
rads = [drawView rotation] / 180.0 * M_PI;
[drawView getFrame:&tempRect];
RotateRectBounds(&viewFrame, &tempRect, &tempRect.origin, rads);
[[superview superview] getContentSize:&contSize];
newSize.width = MAX(viewFrame.size.width, contSize.width);
newSize.height = MAX(viewFrame.size.height, contSize.height);
delta.width = newSize.width - viewFrame.size.width;
delta.height = newSize.height - viewFrame.size.height;
if (delta.width != 0.0 || delta.height != 0.0)
{
if (delta.width < margin)
newSize.width += margin - delta.width;
if (delta.height < margin)
newSize.height += margin - delta.height;
}
[self sizeTo:newSize.width :newSize.height];
insetSize.width = floor((newSize.width - viewFrame.size.width)/2 +
tempRect.origin.x - viewFrame.origin.x);
insetSize.height = floor((newSize.height - viewFrame.size.height)/2 +
tempRect.origin.y - viewFrame.origin.y);
[drawView moveTo:insetSize.width :insetSize.height];
if (insetSize.width != 0 || insetSize.height != 0)
[drawView setClipping:YES];
else
[drawView setClipping:NO];
}
return self;
}
/*
* Scales the drawing view to the tag of the selected matrix cell and
* then scrolls to the point. The point is in window coordinates so
* it must be converted to the drawing view coordinates in order
* to position it in the same relative place in the view.
*/
- scaleDrawViewToPoint:(NXPoint *) p;
{
float newscale;
NXPoint viewPt;
[window invalidateCursorRectsForView:self];
newscale = [zoomControl selectedTag] * 0.01;
if (drawView && newscale != scale)
{
viewPt = *p;
[drawView convertPoint:&viewPt fromView:nil];
[window disableDisplay];
/* Size and then scale the drawing view. The frame of the */
/* drawing view must reflect the changed size. Scaling */
/* alone will not change the frame. */
[self sizeDrawViewWithScale:newscale];
[self scaleDrawViewWithScale:newscale];
[self setScale:newscale];
[self placeDrawView];
[self scrollPoint:&viewPt to:p];
[window reenableDisplay];
[[window contentView] display];
}
zooming = NO;
return self;
}
/*
* Use the point location relative to the window versus the point relative
* to the drawing view (before the scale) to determine where to scroll
* the drawing view. We want the same location in the drawing view to
* appear where the mouse downed occurred.
*/
- scrollPoint:(const NXPoint *) aPt to:(const NXPoint *) windowPt
{
NXPoint viewPt, scrollPt;
NXRect clipFrame, visRect;
[superview getFrame:&clipFrame];
if (frame.size.width > clipFrame.size.width || frame.size.height > clipFrame.size.height)
{
viewPt = *aPt;
[drawView convertPointToSuperview:&viewPt];
scrollPt = *windowPt;
[self convertPoint:&scrollPt fromView:nil];
[self getVisibleRect:&visRect];
viewPt.x -= (scrollPt.x - visRect.origin.x);
viewPt.y -= (scrollPt.y - visRect.origin.y);
[self scrollPoint:&viewPt];
}
return self;
}
/*
* This drawSelf method draws a border around the drawing view as well as a
* drop shadow. This is only done if it will be visible however. We tell if it is visible
* if the rectangle passed in is not contained entirely within drawingView frame.
*/
- drawSelf:(NXRect *)r :(int) count
{
int rotation;
float rads;
NXRect drawRect, viewFrame;
PSsetgray(NX_LTGRAY);
NXRectFill(r);
if (drawView)
{
rotation = [drawView rotation];
rads = rotation / 180.0 * M_PI;
[drawView getFrame:&drawRect];
RotateRectBounds(&viewFrame, &drawRect, &drawRect.origin, rads);
if (!NXContainsRect(&viewFrame, r) || IntersectsRotatedRect(r, &drawRect, rads))
{
PSgsave();
PSrectclip(r->origin.x, r->origin.y, r->size.width, r->size.height);
PStranslate(drawRect.origin.x, drawRect.origin.y);
PSrotate(rotation);
PSsetgray(NX_BLACK);
PSsetlinewidth(LINEWIDTH * scale);
PSrectfill(rint(OFFSET * scale), rint(-OFFSET * scale),
drawRect.size.width, drawRect.size.height);
PSrectstroke(0.0, 0.0, drawRect.size.width, drawRect.size.height);
PSgrestore();
}
}
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.