home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_Text / DocView.m < prev    next >
Encoding:
Text File  |  1992-12-19  |  9.3 KB  |  382 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    DocView.m
  35.  *
  36.  *    This class handles the scaling of the drawing view. It repositions
  37.  *    The drawing view within itself if the drawing view is smaller than the
  38.  *    size of the clip view. The size of the doc view is:
  39.  *    MAX(clip view frame, drawing view frame).
  40.  *
  41.  *    Version:    2.0
  42.  *    Author:    Ken Fromm
  43.  *    History:
  44.  *            03-07-91        Added this comment.
  45.  */
  46.  
  47. #import "DocView.h"
  48. #import "DrawingView.h"
  49. #import "rotateprocs.h"
  50.  
  51. #import <appkit/NXCursor.h>
  52. #import <appkit/NXImage.h>
  53.  
  54. #import <appkit/Matrix.h>
  55. #import <appkit/ScrollView.h>
  56.  
  57. #import <dpsclient/wraps.h>
  58. #import <appkit/nextstd.h>
  59.  
  60. @implementation DocView
  61.  
  62. /*
  63. *    Since there is only one subview its easier to keep track of it as an
  64. *    instance variable rather than in the subview list.  Returns any the
  65. *    previous drawing view.
  66. */
  67. - addDrawView:subView
  68. {
  69.     id        oldView;
  70.  
  71.     oldView = drawView;
  72.     [oldView  removeFromSuperview];
  73.  
  74.     [self  addSubview:subView];
  75.     drawView = subView;
  76.     
  77.     return oldView;
  78. }
  79.  
  80. - setZoomControl:anObject
  81. {
  82.     zoomControl = anObject;
  83.     
  84.     return self;
  85. }
  86.  
  87. - zoomControl
  88. {
  89.     return zoomControl;
  90. }
  91.  
  92. - setScale:(float)value
  93. {
  94.     scale = value;
  95.     
  96.     return self;
  97. }
  98.  
  99. - (float) scale
  100. {
  101.     return  scale;
  102. }
  103.  
  104. - (BOOL) isZooming
  105. {
  106.     return zooming;
  107. }
  108.  
  109. /*
  110. *    This method is overridden from the View class. When the
  111. *    user is zooming the cursor rect for the zoom cursor is set
  112. *    the the frame of the drawing view.
  113. */
  114. - resetCursorRects
  115. {
  116.     id            imageId;
  117.  
  118.     NXPoint        hotspot;
  119.  
  120.     NXRect        cursorRect, visRect;
  121.  
  122.     if (zooming)
  123.     {
  124.         if (!zoomCursor)
  125.         {
  126.             hotspot.x = hotspot.y = 8.0;
  127.             imageId = [NXImage  newFromSection:"zoom.tiff"];
  128.             zoomCursor = [NXCursor  newFromImage:imageId];
  129.             [zoomCursor setHotSpot:&hotspot];
  130.         }
  131.  
  132.         [self getVisibleRect:&visRect];
  133.         [drawView getFrame:&cursorRect];
  134.         NXIntersectionRect(&visRect, &cursorRect);
  135.         [self addCursorRect:&cursorRect  cursor:zoomCursor];
  136.     }
  137.  
  138.     return self;
  139. }
  140.  
  141. /*
  142. *    Messaged from the zoom matrix. Starts the zoom loop. At the next
  143. *    mouse down in the drawing view, the scaleDrawView:toPoint: method
  144. *    will be called.
  145. */
  146. - zoom:sender
  147. {
  148.     if (scale != ([sender  selectedTag] * 0.01))
  149.     {
  150.         zooming = YES;
  151.         [self  setZoomControl:sender];
  152.         [self  resetCursorRects];
  153.  
  154.         [window makeKeyAndOrderFront:self];
  155.     }
  156.  
  157.     return self;
  158. }
  159.  
  160. - rotateDrawView
  161. {
  162.     NXPoint        viewPt, windowPt;
  163.  
  164.     NXRect        tempRect;
  165.  
  166.     if (drawView)
  167.     {
  168.         [drawView  getVisibleRect:&tempRect];
  169.         viewPt.x = tempRect.origin.x + tempRect.size.width/2.0;
  170.         viewPt.y = tempRect.origin.y + tempRect.size.height/2.0;
  171.  
  172.         [self getVisibleRect:&tempRect];
  173.         windowPt.x = tempRect.origin.x + tempRect.size.width/2.0;
  174.         windowPt.y = tempRect.origin.y + tempRect.size.height/2.0;
  175.         [self  convertPoint:&windowPt  toView:nil];
  176.  
  177.         [window disableDisplay];
  178.             [self  placeDrawView];
  179.             [self  scrollPoint:&viewPt  to:&windowPt];
  180.         [window reenableDisplay];
  181.         [[window  contentView]  display];
  182.     }
  183.  
  184.     return self;
  185. }
  186.  
  187. /*
  188. *    Sizes the drawing view from the old scale to the newscale.
  189. *    The frame of the view is used instead of the bounds because
  190. *    the bound will always be the same whereas the frame will
  191. *    provide the size in default coordinates.
  192. */
  193. - sizeDrawViewWithScale:(float) newscale
  194. {
  195.     float            scalefactor;
  196.  
  197.     NXRect        viewFrame;
  198.     
  199.     [drawView  getFrame:&viewFrame];
  200.     scalefactor = newscale/scale;
  201.     [drawView sizeTo:rint(viewFrame.size.width*scalefactor)
  202.                 :rint(viewFrame.size.height*scalefactor)];
  203.  
  204.     return self;
  205. }
  206.  
  207. /* 
  208. *    Scales the drawing view from the old scale to the new scale.
  209. *    The scale method is relative so we use the ratio
  210. *    of the old scale to the new scale to obtain the scaling factor.
  211. */
  212. - scaleDrawViewWithScale:(float) newscale
  213. {
  214.     float     scalefactor;
  215.  
  216.     scalefactor = newscale/scale;
  217.     [drawView scale:scalefactor  :scalefactor];
  218.  
  219.     return self;
  220. }
  221.  
  222. /*
  223. *    Place the drawing view in the center of the doc view
  224. *    if it is smaller than the size of the ClipView.
  225. */
  226. - placeDrawView
  227. {
  228.     int            margin;
  229.  
  230.     float            rads;
  231.     
  232.     NXSize        contSize, newSize, insetSize, delta;
  233.  
  234.     NXRect         tempRect, viewFrame;
  235.  
  236.     if (drawView)
  237.     {
  238.         margin = (int) 4 * OFFSET * scale;
  239.  
  240.         rads = [drawView  rotation] / 180.0 * M_PI;
  241.         [drawView  getFrame:&tempRect];
  242.         RotateRectBounds(&viewFrame, &tempRect, &tempRect.origin, rads);
  243.         [[superview  superview]  getContentSize:&contSize];
  244.  
  245.         newSize.width = MAX(viewFrame.size.width, contSize.width);
  246.         newSize.height = MAX(viewFrame.size.height, contSize.height);
  247.  
  248.         delta.width = newSize.width - viewFrame.size.width;
  249.         delta.height = newSize.height - viewFrame.size.height;
  250.         if (delta.width != 0.0 || delta.height != 0.0)
  251.         {
  252.             if (delta.width < margin)
  253.                 newSize.width += margin - delta.width;
  254.             if (delta.height < margin)
  255.                 newSize.height += margin - delta.height;
  256.         }
  257.     
  258.         [self  sizeTo:newSize.width  :newSize.height];
  259.  
  260.         insetSize.width = floor((newSize.width - viewFrame.size.width)/2 +
  261.                 tempRect.origin.x - viewFrame.origin.x);
  262.         insetSize.height =  floor((newSize.height - viewFrame.size.height)/2 +
  263.                 tempRect.origin.y - viewFrame.origin.y);
  264.         [drawView  moveTo:insetSize.width  :insetSize.height];
  265.         if (insetSize.width != 0 || insetSize.height != 0)
  266.             [drawView  setClipping:YES];
  267.         else
  268.             [drawView setClipping:NO];
  269.     }
  270.  
  271.     return self;
  272. }
  273.  
  274. /*
  275. *    Scales the drawing view to the tag of the selected matrix cell and
  276. *    then scrolls to the point. The point is in window coordinates so
  277. *    it must be converted to the drawing view  coordinates in order
  278. *    to position it in the same relative place in the view.
  279. */
  280. - scaleDrawViewToPoint:(NXPoint *) p;
  281. {
  282.     float            newscale;
  283.  
  284.     NXPoint        viewPt;
  285.  
  286.     [window invalidateCursorRectsForView:self];
  287.     newscale = [zoomControl  selectedTag] * 0.01;
  288.     if (drawView && newscale != scale)
  289.     {
  290.         viewPt = *p;
  291.         [drawView  convertPoint:&viewPt fromView:nil];
  292.         [window disableDisplay];
  293.             /* Size and then scale the drawing view. The frame of the */
  294.             /* drawing view must reflect the changed size. Scaling */
  295.             /* alone will not change the frame. */
  296.             [self  sizeDrawViewWithScale:newscale];
  297.             [self  scaleDrawViewWithScale:newscale];
  298.             [self  setScale:newscale];
  299.  
  300.             [self  placeDrawView];
  301.             [self  scrollPoint:&viewPt  to:p];
  302.         [window reenableDisplay];
  303.         [[window contentView]  display];
  304.     }
  305.     zooming = NO;
  306.  
  307.     return self;
  308. }
  309.  
  310. /*
  311.  *    Use the point location relative to the window versus the point relative
  312.  *    to the drawing view (before the scale) to determine where to scroll
  313.  *    the drawing view. We want the same location in the drawing view to
  314.  *    appear where the mouse downed occurred.
  315.  */    
  316. - scrollPoint:(const NXPoint *) aPt  to:(const NXPoint *) windowPt
  317. {
  318.     NXPoint        viewPt, scrollPt;
  319.  
  320.     NXRect         clipFrame, visRect;
  321.  
  322.     [superview  getFrame:&clipFrame];
  323.     if (frame.size.width > clipFrame.size.width || frame.size.height > clipFrame.size.height)
  324.     {
  325.         viewPt = *aPt;
  326.         [drawView  convertPointToSuperview:&viewPt];
  327.  
  328.         scrollPt = *windowPt;
  329.         [self  convertPoint:&scrollPt  fromView:nil];
  330.         [self  getVisibleRect:&visRect];
  331.         viewPt.x  -= (scrollPt.x - visRect.origin.x);
  332.         viewPt.y  -= (scrollPt.y - visRect.origin.y);
  333.         [self  scrollPoint:&viewPt];        
  334.     }
  335.  
  336.     return self;
  337. }
  338.  
  339. /*
  340.  * This drawSelf method draws a border around the drawing view as well as a
  341.  * drop shadow.  This is only done if it will be visible however. We tell if it is visible
  342.  * if the rectangle passed in is not contained entirely within drawingView frame.
  343. */
  344. - drawSelf:(NXRect *)r :(int) count
  345. {
  346.     int            rotation;
  347.  
  348.     float            rads;
  349.  
  350.     NXRect        drawRect, viewFrame;
  351.  
  352.     PSsetgray(NX_LTGRAY);
  353.     NXRectFill(r);
  354.  
  355.     if (drawView)
  356.     {
  357.         rotation = [drawView  rotation];
  358.         rads = rotation / 180.0 * M_PI;
  359.         [drawView  getFrame:&drawRect];
  360.         RotateRectBounds(&viewFrame, &drawRect, &drawRect.origin, rads);
  361.         if (!NXContainsRect(&viewFrame, r) || IntersectsRotatedRect(r, &drawRect, rads))
  362.         {
  363.             PSgsave();
  364.                 PSrectclip(r->origin.x, r->origin.y, r->size.width, r->size.height);
  365.  
  366.                 PStranslate(drawRect.origin.x, drawRect.origin.y);
  367.                 PSrotate(rotation);
  368.                 PSsetgray(NX_BLACK);
  369.                 PSsetlinewidth(LINEWIDTH * scale);
  370.                 PSrectfill(rint(OFFSET * scale),  rint(-OFFSET * scale),
  371.                     drawRect.size.width, drawRect.size.height);
  372.                 PSrectstroke(0.0, 0.0, drawRect.size.width, drawRect.size.height);
  373.             PSgrestore();
  374.         }
  375.     }
  376.  
  377.     return self;            
  378. }
  379.  
  380. @end
  381.  
  382.