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). * * This class is used in several of the other Display PostScript programs. * Some of the methods may be different as the class became more and * more refined but the general operation remains the same. * * Version: 2.0 * Author: Ken Fromm */ #import "DocView.h" #import "ImportApp.h" #import <appkit/Cursor.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. */ - setDrawView:newView { id oldView; oldView = drawviewId; [oldView removeFromSuperview]; [self addSubview:newView]; drawviewId = newView; return oldView; } - drawView { return drawviewId; } - setScale:(float)value { scale = value; return self; } - (float) scale { return scale; } /* * Check whether the frame of the drawingview is in the rectangle passed in. * If drop is true, then include the linewidth and the drop shadow as part of the * drawingview frame. */ - getDrawViewInRect:(const NXRect *) aRect withDrop:(BOOL) drop { id aView = NULL; NXRect viewRect, dropRect; [drawviewId getFrame:&viewRect]; if (drop) { dropRect = viewRect; NXOffsetRect(&dropRect, rint(OFFSET * scale), rint(-OFFSET * scale)); NXOffsetRect(&viewRect, rint(LINEWIDTH/2 * scale), rint(LINEWIDTH/2 * scale)); NXUnionRect(&dropRect, &viewRect); } if (NXIntersectsRect(aRect, &viewRect)) aView = drawviewId; return aView; } /* * 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. */ - sizeView:viewId withScale:(float) newscale { float scalefactor, sizewidth, sizeheight; NXRect viewFrame; [viewId getFrame:&viewFrame]; scalefactor = newscale/scale; sizewidth = viewFrame.size.width*scalefactor; sizeheight = viewFrame.size.height*scalefactor; [viewId sizeTo:rint(sizewidth) :rint(sizeheight)]; 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. */ - scaleView:viewId withScale:(float) newscale { float scalefactor; scalefactor = newscale/scale; [viewId scale:scalefactor :scalefactor]; return self; } /* * Place the view passed in in the center of the doc view * if it is smaller than the size of the ClipView. Two passes are made * through the loop because adding or removing a horizontal or * vertical scrollbar will affect the size of the remaining dimension . */ - placeView:viewId { BOOL vert = NO, horiz = NO, done = NO; int passes = 0, border_type; float margin; NXSize contSize, newSize, insetSize, delta; NXRect viewFrame, scrollFrame; margin = 4 * OFFSET * scale; [viewId getFrame:&viewFrame]; [[superview superview] getFrame:&scrollFrame]; border_type = [[superview superview] borderType]; while (!done && ++passes <= 2) { [ScrollView getContentSize:&contSize forFrameSize:&scrollFrame.size horizScroller:horiz vertScroller:vert borderType:border_type]; 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; } horiz = (newSize.width != contSize.width); vert = (newSize.height != contSize.height); if ((horiz && vert) || (!horiz && !vert)) done = YES; else done = NO; } [self sizeTo:newSize.width :newSize.height]; insetSize.width = floor((newSize.width - viewFrame.size.width)/2); insetSize.height = floor((newSize.height - viewFrame.size.height)/2); [viewId moveTo:insetSize.width :insetSize.height]; if (insetSize.width != 0 || insetSize.height != 0) [viewId setClipping:YES]; else [viewId setClipping:NO]; if (horiz) [[superview superview] setHorizScrollerRequired:YES]; else [[superview superview] setHorizScrollerRequired:NO]; if (vert) [[superview superview] setVertScrollerRequired:YES]; else [[superview superview] setVertScrollerRequired:NO]; return self; } /* * Scales the 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. */ - scaleDrawView:hitView withEvent:(NXEvent *) event; { float newscale; NXPoint viewPt; [window invalidateCursorRectsForView:self]; if ((event->flags & NX_ALTERNATEMASK) == NX_ALTERNATEMASK) newscale = scale / INCSCALE; else newscale = scale * INCSCALE; if (hitView && newscale >= MINSCALE && newscale <= MAXSCALE) { viewPt = event->location; [self convertPoint:&viewPt fromView:nil]; [self convertPoint:&viewPt toView:hitView]; [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 sizeView:hitView withScale:newscale]; [self scaleView:hitView withScale:newscale]; [self setScale:newscale]; [self placeView:hitView]; [self scrollPoint:&viewPt inView:hitView to:&event->location]; [window reenableDisplay]; [[window contentView] display]; } else [NXApp clearOperation]; 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. The window coordinates * are used and then adjusted by the position of the scrolling frame * because the presence or absence of scrollbars throws the use * of the doc views coordinates awry. */ - scrollPoint:(const NXPoint *) aPt inView:hitView to:(const NXPoint *) windowPt { NXPoint viewPt; NXSize contSize; NXRect viewFrame, visRect, scrollFrame; [[superview superview] getContentSize:&contSize]; [hitView getFrame:&viewFrame]; if (viewFrame.size.width > contSize.width || viewFrame.size.height > contSize.height) { viewPt = *aPt; [self convertPoint:&viewPt fromView:hitView]; [self getVisibleRect:&visRect]; [[superview superview] getFrame:&scrollFrame]; if (viewFrame.size.width > contSize.width) viewPt.x -= windowPt->x - (scrollFrame.origin.x +scrollFrame.size.width - visRect.size.width); if (viewFrame.size.height > contSize.height) viewPt.y -= windowPt->y - (scrollFrame.origin.y + scrollFrame.size.height - visRect.size.height); [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 { id visView; NXRect drawRect, dropRect, bRect, xRect, yRect; visView = [self getDrawViewInRect:r withDrop:YES]; if (visView) { /* Calculate the rectangle of the draw view plus its drop shadow. */ [visView getFrame:&drawRect]; dropRect = bRect = drawRect; NXOffsetRect(&bRect, -rint(LINEWIDTH/2 * scale), -rint(LINEWIDTH/2 * scale)); NXOffsetRect(&dropRect, rint(OFFSET * scale), rint(-OFFSET * scale)); NXUnionRect(&dropRect, &bRect); if (!NXContainsRect(&bRect, r)) { bRect = xRect = yRect = dropRect; NXIntersectionRect(&drawRect, &bRect); NXDivideRect(&xRect, &dropRect, bRect.size.width, 0); NXDivideRect(&yRect, &dropRect, bRect.size.height, 3); PSgsave(); PSsetgray(NX_BLACK); PSrectclip(r->origin.x, r->origin.y, r->size.width, r->size.height); PSrectfill(xRect.origin.x, xRect.origin.y, xRect.size.width, xRect.size.height); PSrectfill(yRect.origin.x, yRect.origin.y, yRect.size.width, yRect.size.height); PSsetlinewidth(LINEWIDTH * scale); PSrectstroke(drawRect.origin.x, drawRect.origin.y, 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.