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.