home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Examples / AppKit / Rulers / RectsView.m < prev    next >
Text File  |  1996-04-26  |  25KB  |  889 lines

  1. /* RectsView.m
  2.  *
  3.  * by Nik Gervae, Technical Publications, NeXT Software Inc.
  4.  *
  5.  * You may freely copy, distribute, and reuse the code in this example.
  6.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to
  7.  * its fitness for any particular use.
  8.  */
  9.  
  10.  
  11. #import "RectsView.h"
  12. #import "ColorRect.h"
  13. #import "NestleView.h"
  14.  
  15.  
  16. /* These images are displayed as markers on the rulers. */
  17. static NSImage *leftImage;
  18. static NSImage *rightImage;
  19. static NSImage *topImage;
  20. static NSImage *bottomImage;
  21.  
  22. /* These strings are used to identify the markers. */
  23.  
  24. #define STR_LEFT   @"Left Edge"
  25. #define STR_RIGHT  @"Right Edge"
  26. #define STR_TOP    @"Top Edge"
  27. #define STR_BOTTOM @"Bottom Edge"
  28.  
  29.  
  30. @implementation RectsView
  31.  
  32.  
  33. + (void)initialize
  34. {
  35.     static BOOL beenHere = NO;
  36.     NSBundle *mainBundle;
  37.     NSString *path;
  38.     NSArray *upArray;
  39.     NSArray *downArray;
  40.  
  41.     if (beenHere) return;
  42.  
  43.     beenHere = YES;
  44.  
  45.     mainBundle = [NSBundle mainBundle];
  46.     path = [mainBundle pathForResource:@"EdgeMarkerLeft" ofType:@"tiff"];
  47.     leftImage = [[NSImage alloc] initByReferencingFile:path];
  48.  
  49.     path = [mainBundle pathForResource:@"EdgeMarkerRight" ofType:@"tiff"];
  50.     rightImage = [[NSImage alloc] initByReferencingFile:path];
  51.  
  52.     path = [mainBundle pathForResource:@"EdgeMarkerTop" ofType:@"tiff"];
  53.     topImage = [[NSImage alloc] initByReferencingFile:path];
  54.  
  55.     path = [mainBundle pathForResource:@"EdgeMarkerBottom" ofType:@"tiff"];
  56.     bottomImage = [[NSImage alloc] initByReferencingFile:path];
  57.  
  58.     upArray = [NSArray arrayWithObjects:[NSNumber numberWithFloat:2.0], nil];
  59.     downArray = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.5],
  60.         [NSNumber numberWithFloat:0.2], nil];
  61.     [NSRulerView registerUnitWithName:@"Grummets"
  62.         abbreviation:NSLocalizedString(@"gt", @"Grummets abbreviation string")
  63.         unitToPointsConversionFactor:100.0
  64.         stepUpCycle:upArray stepDownCycle:downArray];
  65.  
  66.     return;
  67. }
  68.  
  69.  
  70. - (id)initWithFrame:(NSRect)frameRect
  71. {
  72.     NSRect aRect;
  73.     ColorRect *firstRect;
  74.  
  75.     self = [super initWithFrame:frameRect];
  76.     if (!self) return nil;
  77.  
  78.     [self setBoundsOrigin:NSMakePoint(-108.0, -108.0)];
  79.  
  80.     rects = [[NSMutableArray alloc] init];
  81.     selectedItem = nil;
  82.  
  83.     aRect = NSMakeRect(30.0, 45.0, 57.0, 118.0);
  84.     firstRect = [[ColorRect alloc] initWithFrame:aRect color:[NSColor blueColor]];
  85.     [rects addObject:firstRect];
  86.     [firstRect release];
  87.  
  88.     return self;
  89. }
  90.  
  91.  
  92. - (void)setRulerOffsets
  93. {
  94.     NSScrollView *scrollView = [self enclosingScrollView];
  95.     NSRulerView *horizRuler;
  96.     NSRulerView *vertRuler;
  97.     NSView *docView;
  98.     NSView *clientView;
  99.     NSPoint zero;
  100.     docView = [scrollView documentView];
  101.     clientView = self;
  102.  
  103.     if (!scrollView) return;
  104.     horizRuler = [scrollView horizontalRulerView];
  105.     vertRuler = [scrollView verticalRulerView];
  106.  
  107.     zero = [docView convertPoint:[clientView bounds].origin fromView:clientView];
  108.     [horizRuler setOriginOffset:zero.x - [docView bounds].origin.x];
  109.  
  110.     [vertRuler setOriginOffset:zero.y - [docView bounds].origin.y];
  111.  
  112.     return;
  113. }
  114.  
  115.  
  116. - (void)awakeFromNib
  117. {
  118.     NSScrollView *scrollView = [self enclosingScrollView];
  119.  
  120.     if (!scrollView) return;
  121.     [scrollView setHasHorizontalRuler:YES];
  122.     [scrollView setHasVerticalRuler:YES];
  123.     [self setRulerOffsets];
  124.     [self updateRulers];
  125.     [scrollView setRulersVisible:YES];
  126.  
  127.     return;
  128. }
  129.  
  130.  
  131. - (BOOL)acceptsFirstResponder
  132. {
  133.     return YES;
  134. }
  135.  
  136.  
  137. - (BOOL)isFlipped
  138. {
  139.     return YES;
  140. }
  141.  
  142.  
  143. - (void)drawRect:(NSRect)aRect
  144. {
  145.     NSEnumerator *numer;
  146.     ColorRect *thisRect;
  147.  
  148.     [[NSColor whiteColor] set];
  149.     NSRectFill(aRect);
  150.  
  151.     numer = [rects objectEnumerator];
  152.     while (thisRect = [numer nextObject]) {
  153.         if (NSIntersectsRect([thisRect frame], aRect)) {
  154.             [thisRect drawRect:aRect selected:(thisRect == selectedItem)];
  155.         }
  156.     }
  157.  
  158.     [[NSColor blackColor] set];
  159.     PSsetlinewidth(0.15);
  160.     PSmoveto(-10.0, 0.0);
  161.     PSrlineto(20.0, 0.0);
  162.     PSmoveto(0.0, -10.0);
  163.     PSrlineto(0.0, 20.0);
  164.     PSstroke();
  165.  
  166.     return;
  167. }
  168.  
  169.  
  170. - (void)moveselectedItemWithEvent:(NSEvent *)theEvent
  171.     mouseOffset:(NSPoint)mouseOffset
  172. {
  173.     NSRect oldRect, newRect, bounds;
  174.     NSPoint mouseLoc;
  175.  
  176.     mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
  177.  
  178.     bounds = [self bounds];
  179.     oldRect = newRect = [selectedItem frame];
  180.     newRect.origin.x = mouseLoc.x - mouseOffset.x;
  181.     newRect.origin.y = mouseLoc.y - mouseOffset.y;
  182.  
  183.     if (NSMinX(newRect) < NSMinX(bounds)) {
  184.         newRect.origin.x = NSMinX(bounds);
  185.     }
  186.     if (NSMaxX(newRect) > NSMaxX(bounds)) {
  187.         newRect.origin.x = NSMaxX(bounds) - NSWidth(newRect);
  188.     }
  189.     if (NSMinY(newRect) < NSMinY(bounds)) {
  190.         newRect.origin.y = NSMinY(bounds);
  191.     }
  192.     if (NSMaxY(newRect) > NSMaxY(bounds)) {
  193.         newRect.origin.y = NSMaxY(bounds) - NSHeight(newRect);
  194.     }
  195.  
  196.     [selectedItem setFrame:newRect];
  197.     [self updateRulerlinesWithOldRect:oldRect newRect:newRect];
  198.     [self setNeedsDisplayInRect:oldRect];
  199.     [self setNeedsDisplayInRect:newRect];
  200.     return;
  201. }
  202.  
  203.  
  204. - (void)mouseDown:(NSEvent *)theEvent
  205. {
  206.     NSEnumerator *numer;
  207.     ColorRect *oldselectedItem = selectedItem;
  208.     ColorRect *thisRect;
  209.     NSPoint mouseLoc;
  210.     NSPoint mouseOffset;
  211.     unsigned int eventMask;
  212.     BOOL dragged = NO;
  213.     BOOL timerOn = NO;
  214.     NSEvent *autoscrollEvent = nil;
  215.  
  216.     selectedItem = nil;
  217.     if (![[self window] makeFirstResponder:self]) return;
  218.  
  219.     mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
  220.  
  221.     numer = [rects reverseObjectEnumerator];
  222.     while (thisRect = [numer nextObject]) {
  223.         if ([self mouse:mouseLoc inRect:[thisRect frame]]) {
  224.             selectedItem = thisRect;
  225.             break;
  226.         }
  227.     }
  228.  
  229.     if (oldselectedItem != selectedItem) {
  230.         [self setNeedsDisplayInRect:[oldselectedItem frame]];
  231.         [self setNeedsDisplayInRect:[selectedItem frame]];
  232.         [self updateRulers];
  233.     }
  234.  
  235.     if (selectedItem == nil || [selectedItem isLocked]) return;
  236.  
  237.     mouseOffset.x = mouseLoc.x - [selectedItem frame].origin.x;
  238.     mouseOffset.y = mouseLoc.y - [selectedItem frame].origin.y;
  239.  
  240.     eventMask = NSLeftMouseDraggedMask | NSLeftMouseUpMask | NSPeriodicMask;
  241.     while (theEvent = [[self window] nextEventMatchingMask:eventMask]) {
  242.         NSRect visibleRect = [self visibleRect];
  243.  
  244.         switch ([theEvent type]) {
  245.  
  246.             case NSPeriodic:
  247.                 if (autoscrollEvent) [self autoscroll:autoscrollEvent];
  248.                 [self moveselectedItemWithEvent:autoscrollEvent
  249.                       mouseOffset:mouseOffset];
  250.                 break;
  251.  
  252.             case NSLeftMouseDragged:
  253.                 if (!dragged) {
  254.                     [self drawRulerlinesWithRect:[selectedItem frame]];
  255.                 }
  256.                 dragged = YES;
  257.                 mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
  258.  
  259.                 [self moveselectedItemWithEvent:theEvent mouseOffset:mouseOffset];
  260.  
  261.                 if (![self mouse:mouseLoc inRect:visibleRect]) {
  262.                     if (NO == timerOn) {
  263.                         [NSEvent startPeriodicEventsAfterDelay:0.1 withPeriod:0.1];
  264.                         timerOn = YES;
  265.                         if (autoscrollEvent) [autoscrollEvent release];
  266.                         autoscrollEvent = [theEvent retain];
  267.                     } else {
  268.                         if (autoscrollEvent) [autoscrollEvent release];
  269.                         autoscrollEvent = [theEvent retain];
  270.                    }
  271.                     break;
  272.                 } else if (YES == timerOn) {
  273.                     [NSEvent stopPeriodicEvents];
  274.                     timerOn = NO;
  275.                     if (autoscrollEvent) [autoscrollEvent release];
  276.                     autoscrollEvent = nil;
  277.                 }
  278.  
  279.                 [self displayIfNeeded];
  280.                 break;
  281.  
  282.             case NSLeftMouseUp:
  283.                 if (YES == timerOn) {
  284.                     [NSEvent stopPeriodicEvents];
  285.                     timerOn = NO;
  286.                     if (autoscrollEvent) [autoscrollEvent release];
  287.                     autoscrollEvent = nil;
  288.                 }
  289.                 if (dragged) [self eraseRulerlinesWithRect:[selectedItem frame]];
  290.                 [self updateRulers];
  291.                 return;
  292.  
  293.             default:
  294.                 break;
  295.         }
  296.     }
  297.     return;
  298. }
  299.  
  300.  
  301. - (void)selectRect:(ColorRect *)aColorRect
  302. {
  303.     if (selectedItem == aColorRect) return;
  304.  
  305.     if (selectedItem) [self setNeedsDisplayInRect:[selectedItem frame]];
  306.  
  307.     if (aColorRect == nil) selectedItem = nil;
  308.     else if ([rects containsObject:aColorRect]) selectedItem = aColorRect;
  309.     [self updateRulers];
  310.     if (selectedItem) [self setNeedsDisplayInRect:[selectedItem frame]];
  311.  
  312.     return;
  313. }
  314.  
  315.  
  316. - (void)lock:(id)sender
  317. {
  318.     if (selectedItem) {
  319.         [selectedItem setLocked:![selectedItem isLocked]];
  320.         [self setNeedsDisplayInRect:[selectedItem frame]];
  321.     }
  322.     return;
  323. }
  324.  
  325.  
  326. #define ZOOMINFACTOR   (2.0)
  327. #define ZOOMOUTFACTOR  (1.0 / ZOOMINFACTOR)
  328.  
  329. - (void)zoomIn:(id)sender
  330. {
  331.     NSRect tempRect;
  332.     NSRect oldBounds;
  333.     NSScrollView *scrollView = [self enclosingScrollView];
  334.  
  335.     oldBounds = [self bounds];
  336.  
  337.     tempRect = [self frame];
  338.     tempRect.size.width = ZOOMINFACTOR * NSWidth(tempRect);
  339.     tempRect.size.height = ZOOMINFACTOR * NSHeight(tempRect);
  340.     [self setFrame:tempRect];
  341.  
  342.     [self setBoundsSize:oldBounds.size];
  343.     [self setBoundsOrigin:oldBounds.origin];
  344.  
  345.     if (scrollView) [scrollView setNeedsDisplay:YES];
  346.     else [[self superview] setNeedsDisplay:YES];
  347.  
  348.     return;
  349. }
  350.  
  351.  
  352. - (void)zoomOut:(id)sender
  353. {
  354.     NSRect tempRect;
  355.     NSRect oldBounds;
  356.     NSScrollView *scrollView = [self enclosingScrollView];
  357.  
  358.     oldBounds = [self bounds];
  359.  
  360.     tempRect = [self frame];
  361.     tempRect.size.width = ZOOMOUTFACTOR * NSWidth(tempRect);
  362.     tempRect.size.height = ZOOMOUTFACTOR * NSHeight(tempRect);
  363.     [self setFrame:tempRect];
  364.  
  365.     [self setBoundsSize:oldBounds.size];
  366.     [self setBoundsOrigin:oldBounds.origin];
  367.  
  368.     if (scrollView) [scrollView setNeedsDisplay:YES];
  369.     else [[self superview] setNeedsDisplay:YES];
  370.  
  371.     return;
  372. }
  373.  
  374.  
  375. /* -nestle: slips a larger view between the enclosing NSClipView and the
  376.  * receiver, and adjusts the ruler origin to lie at the same point in the
  377.  * receiver. Apps that tile pages differently might want to do this when
  378.  * an NSView representing a page is moved. */
  379.  
  380. - (void)nestle:(id)sender
  381. {
  382.     NSScrollView *enclosingScrollView = [self enclosingScrollView];
  383.  
  384.     if (!enclosingScrollView) return;
  385.  
  386.     if ([[self superview] isKindOfClass:[NestleView class]]) {
  387.         [enclosingScrollView setDocumentView:self];
  388.     } else {
  389.         NSRect nFrame, rFrame;
  390.         NestleView *nView;
  391.  
  392.         rFrame = [self frame];
  393.         nFrame = NSMakeRect(0.0, 0.0, rFrame.size.width + 64.0,
  394.             rFrame.size.height + 64.0);
  395.  
  396.         nView = [[[NestleView alloc] initWithFrame:nFrame] autorelease];
  397.         [enclosingScrollView setDocumentView:nil];  // self vanishes without this!
  398.         [nView addSubview:self];
  399.         rFrame.origin.x = rFrame.origin.y = 32.0;
  400.         [self setFrame:rFrame];
  401.         [enclosingScrollView setDocumentView:nView];
  402.     }
  403.  
  404.     [[self window] makeFirstResponder:self];
  405.     [self setRulerOffsets];
  406.     [self updateRulers];
  407.     [enclosingScrollView setNeedsDisplay:YES];
  408.     return;
  409. }
  410.  
  411.  
  412. - (void)drawRulerlinesWithRect:(NSRect)aRect;
  413. {
  414.     NSScrollView *scrollView = [self enclosingScrollView];
  415.     NSRulerView *horizRuler;
  416.     NSRulerView *vertRuler;
  417.     NSRect convRect;
  418.  
  419.     if (!scrollView) return;
  420.  
  421.     horizRuler = [scrollView horizontalRulerView];
  422.     vertRuler = [scrollView verticalRulerView];
  423.  
  424.     if (horizRuler) {
  425.         convRect = [self convertRect:aRect toView:horizRuler];
  426.  
  427.         [horizRuler moveRulerlineFromLocation:-1.0
  428.                 toLocation:NSMinX(convRect)];
  429.         [horizRuler moveRulerlineFromLocation:-1.0
  430.                 toLocation:NSMaxX(convRect)];
  431.     }
  432.  
  433.     if (vertRuler) {
  434.         convRect = [self convertRect:aRect toView:vertRuler];
  435.  
  436.         [vertRuler moveRulerlineFromLocation:-1.0
  437.                 toLocation:NSMinY(convRect)];
  438.         [vertRuler moveRulerlineFromLocation:-1.0
  439.                 toLocation:NSMaxY(convRect)];
  440.     }
  441.     return;
  442. }
  443.  
  444.  
  445. - (void)updateRulerlinesWithOldRect:(NSRect)oldRect newRect:(NSRect)newRect
  446. {
  447.     NSScrollView *scrollView = [self enclosingScrollView];
  448.     NSRulerView *horizRuler;
  449.     NSRulerView *vertRuler;
  450.     NSRect convOldRect, convNewRect;
  451.  
  452.     if (!scrollView) return;
  453.  
  454.     horizRuler = [scrollView horizontalRulerView];
  455.     vertRuler = [scrollView verticalRulerView];
  456.  
  457.     if (horizRuler) {
  458.         convOldRect = [self convertRect:oldRect toView:horizRuler];
  459.         convNewRect = [self convertRect:newRect toView:horizRuler];
  460.         [horizRuler moveRulerlineFromLocation:NSMinX(convOldRect)
  461.                 toLocation:NSMinX(convNewRect)];
  462.         [horizRuler moveRulerlineFromLocation:NSMaxX(convOldRect)
  463.                 toLocation:NSMaxX(convNewRect)];
  464.     }
  465.  
  466.     if (vertRuler) {
  467.         convOldRect = [self convertRect:oldRect toView:vertRuler];
  468.         convNewRect = [self convertRect:newRect toView:vertRuler];
  469.         [vertRuler moveRulerlineFromLocation:NSMinY(convOldRect)
  470.                 toLocation:NSMinY(convNewRect)];
  471.         [vertRuler moveRulerlineFromLocation:NSMaxY(convOldRect)
  472.                 toLocation:NSMaxY(convNewRect)];
  473.     }
  474.     return;
  475. }
  476.  
  477.  
  478. - (void)eraseRulerlinesWithRect:(NSRect)aRect;
  479. {
  480.     NSScrollView *scrollView = [self enclosingScrollView];
  481.     NSRulerView *horizRuler;
  482.     NSRulerView *vertRuler;
  483.     NSRect convRect;
  484.  
  485.     if (!scrollView) return;
  486.  
  487.     horizRuler = [scrollView horizontalRulerView];
  488.     vertRuler = [scrollView verticalRulerView];
  489.  
  490.     if (horizRuler) {
  491.         convRect = [self convertRect:aRect toView:horizRuler];
  492.  
  493.         [horizRuler setNeedsDisplay:YES];
  494.     }
  495.  
  496.     if (vertRuler) {
  497.         convRect = [self convertRect:aRect toView:vertRuler];
  498.  
  499.         [vertRuler setNeedsDisplay:YES];
  500.     }
  501.     return;
  502. }
  503.  
  504.  
  505. - (void)updateHorizontalRuler
  506. {
  507.     NSScrollView *scrollView;
  508.     NSRulerView *horizRuler;
  509.     NSRulerMarker *leftMarker;
  510.     NSRulerMarker *rightMarker;
  511.  
  512.  
  513.     scrollView = [self enclosingScrollView];
  514.     if (!scrollView) return;
  515.  
  516.     horizRuler = [scrollView horizontalRulerView];
  517.     if (!horizRuler) return;
  518.  
  519.     if ([horizRuler clientView] != self) {
  520.         [horizRuler setClientView:self];
  521.         [horizRuler setMeasurementUnits:@"Grummets"];
  522.     }
  523.  
  524.     if (!selectedItem) {
  525.         [horizRuler setMarkers:nil];
  526.         return;
  527.     }
  528.  
  529.     leftMarker = [[NSRulerMarker alloc] initWithRulerView:horizRuler
  530.         markerLocation:NSMinX([selectedItem frame]) image:leftImage
  531.         imageOrigin:NSMakePoint(0.0, 0.0)];
  532.  
  533.     rightMarker = [[NSRulerMarker alloc] initWithRulerView:horizRuler
  534.         markerLocation:NSMaxX([selectedItem frame]) image:rightImage
  535.         imageOrigin:NSMakePoint(8.0, 0.0)];
  536.  
  537.     [horizRuler setMarkers:[NSArray arrayWithObjects:leftMarker, rightMarker, nil]];
  538.  
  539.     [leftMarker setRemovable:YES];
  540.     [rightMarker setRemovable:YES];
  541.     [leftMarker setRepresentedObject:STR_LEFT];
  542.     [rightMarker setRepresentedObject:STR_RIGHT];
  543.  
  544.     return;
  545. }
  546.  
  547.  
  548. - (void)updateVerticalRuler
  549. {
  550.     NSScrollView *scrollView;
  551.     NSRulerView *vertRuler;
  552.     NSPoint thePoint;   /* Just a temporary scratch variable */
  553.     float location;
  554.     NSRulerMarker *topMarker;
  555.     NSRulerMarker *bottomMarker;
  556.  
  557.     scrollView = [self enclosingScrollView];
  558.     if (!scrollView) return;
  559.  
  560.     vertRuler = [scrollView verticalRulerView];
  561.     if (!vertRuler) return;
  562.  
  563.     if ([vertRuler clientView] != self) {
  564.         [vertRuler setClientView:self];
  565.         [vertRuler setMeasurementUnits:@"Grummets"];
  566.     }
  567.  
  568.     if (!selectedItem) {
  569.         [vertRuler setMarkers:nil];
  570.         return;
  571.     }
  572.  
  573.     if ([self isFlipped]) location = NSMaxY([selectedItem frame]);
  574.     else location = NSMinY([selectedItem frame]);
  575.     
  576.     thePoint = NSMakePoint(8.0, 0.0);
  577.     bottomMarker = [[NSRulerMarker alloc] initWithRulerView:vertRuler
  578.         markerLocation:location image:bottomImage
  579.         imageOrigin:thePoint];
  580.     [bottomMarker setRemovable:YES];
  581.     [bottomMarker setRepresentedObject:STR_BOTTOM];
  582.  
  583.  
  584.     if ([self isFlipped]) location = NSMinY([selectedItem frame]);
  585.     else location = NSMaxY([selectedItem frame]);
  586.  
  587.     thePoint = NSMakePoint(8.0, 8.0);
  588.     topMarker = [[NSRulerMarker alloc] initWithRulerView:vertRuler
  589.         markerLocation:location image:topImage
  590.         imageOrigin:thePoint];
  591.     [topMarker setRemovable:YES];
  592.     [topMarker setRepresentedObject:STR_TOP];
  593.  
  594.     [vertRuler setMarkers:[NSArray arrayWithObjects:bottomMarker, topMarker, nil]];
  595.  
  596.     return;
  597. }
  598.  
  599.  
  600. - (void)updateRulers
  601. {
  602.     [self updateHorizontalRuler];
  603.     [self updateVerticalRuler];
  604.     return;
  605. }
  606.  
  607.  
  608. - (void)updateSelectedRectFromRulers
  609. {
  610.     NSRulerView *horizRuler;
  611.     NSRulerView *vertRuler;
  612.     NSArray *markers;
  613.     float m1Loc, m2Loc;
  614.     NSRect newRect;
  615.  
  616.     if (!selectedItem) return;
  617.  
  618.     horizRuler = [[self enclosingScrollView] horizontalRulerView];
  619.     markers = [horizRuler markers];
  620.     if ([markers count] != 2) return;
  621.  
  622.     m1Loc = [[markers objectAtIndex:0] markerLocation];
  623.     m2Loc = [[markers objectAtIndex:1] markerLocation];
  624.     if (m1Loc < m2Loc) {
  625.         newRect.origin.x = m1Loc;
  626.         newRect.size.width = m2Loc - m1Loc;
  627.     } else {
  628.         newRect.origin.x = m2Loc;
  629.         newRect.size.width = m1Loc - m2Loc;
  630.     }
  631.  
  632.     vertRuler = [[self enclosingScrollView] verticalRulerView];
  633.     markers = [vertRuler markers];
  634.     if ([markers count] != 2) return;
  635.  
  636.     m1Loc = [[markers objectAtIndex:0] markerLocation];
  637.     m2Loc = [[markers objectAtIndex:1] markerLocation];
  638.     if (m1Loc < m2Loc) {
  639.         newRect.origin.y = m1Loc;
  640.         newRect.size.height = m2Loc - m1Loc;
  641.     } else {
  642.         newRect.origin.y = m2Loc;
  643.         newRect.size.height = m1Loc - m2Loc;
  644.     }
  645.  
  646.     [self setNeedsDisplayInRect:[selectedItem frame]];
  647.     [selectedItem setFrame:newRect];
  648.     [self setNeedsDisplayInRect:newRect];
  649.  
  650.     return;
  651. }
  652.  
  653.  
  654. /***********
  655.  * NSRulerView client methods
  656.  */
  657.  
  658. - (BOOL)rulerView:(NSRulerView *)aRulerView
  659.     shouldMoveMarker:(NSRulerMarker *)aMarker
  660. {
  661.     if (!selectedItem || [selectedItem isLocked]) return NO;
  662.     return YES;
  663. }
  664.  
  665.  
  666. - (float)rulerView:(NSRulerView *)aRulerView
  667.     willMoveMarker:(NSRulerMarker *)aMarker
  668.     toLocation:(float)location
  669. {
  670.     NSEvent *currentEvent;
  671.     unsigned int eventFlags;
  672.     BOOL shifted;
  673.     NSRect rect, dirtyRect;
  674.     NSString *theEdge = [aMarker representedObject];
  675.  
  676.     if (!selectedItem) return location;
  677.     rect = [selectedItem frame];
  678.     dirtyRect = rect;
  679.     dirtyRect.size.width = NSWidth(rect) + 2.0; // fudge to counter hilite prob
  680.     dirtyRect.size.height = NSHeight(rect) + 2.0;
  681.     [self setNeedsDisplayInRect:dirtyRect];
  682.  
  683.     currentEvent = [NSApp currentEvent];
  684.     eventFlags = [currentEvent modifierFlags];
  685.     shifted = (eventFlags & NSShiftKeyMask) ? YES : NO;
  686.  
  687. #define MINSIZE (5.0)
  688.  
  689.  
  690.     if (!shifted) {
  691.         if ([theEdge isEqualToString:STR_LEFT]) {
  692.             if (location > (NSMaxX(rect) - MINSIZE)) {
  693.                 location = (NSMaxX(rect) - MINSIZE);
  694.             }
  695.             rect.size.width = NSMaxX(rect) - location;
  696.             rect.origin.x = location;
  697.         }
  698.         else if ([theEdge isEqualToString:STR_RIGHT]) {
  699.             if (location < (NSMinX(rect) + MINSIZE)) {
  700.                 location = (NSMinX(rect) + MINSIZE);
  701.             }
  702.             rect.size.width = location - NSMinX(rect);
  703.         }
  704.         else if ([theEdge isEqualToString:STR_TOP]) {
  705.             if ([self isFlipped]) {
  706.                 if (location > (NSMaxY(rect) - MINSIZE)) {
  707.                     location = (NSMaxY(rect) - MINSIZE);
  708.                 }
  709.                 rect.size.height = NSMaxY(rect) - location;
  710.                 rect.origin.y = location;
  711.             } else {
  712.                 if (location < (NSMinY(rect) + MINSIZE)) {
  713.                     location = (NSMinY(rect) + MINSIZE);
  714.                 }
  715.                 rect.size.height = location - NSMinY(rect);
  716.             }
  717.         }
  718.         else if ([theEdge isEqualToString:STR_BOTTOM]) {
  719.             if ([self isFlipped]) {
  720.                 if (location < (NSMinY(rect) + MINSIZE)) {
  721.                     location = (NSMinY(rect) + MINSIZE);
  722.                 }
  723.                 rect.size.height = location - NSMinY(rect);
  724.             } else {
  725.                 if (location > (NSMaxY(rect) - MINSIZE)) {
  726.                     location = (NSMaxY(rect) - MINSIZE);
  727.                 }
  728.                 rect.size.height = NSMaxY(rect) - location;
  729.                 rect.origin.y = location;
  730.             }
  731.  
  732.         } /* if theEdge equal... */
  733.     } else {
  734.         NSArray *markers = [aRulerView markers];
  735.         NSRulerMarker *otherMarker;
  736.  
  737.         otherMarker = [markers objectAtIndex:0];
  738.         if (otherMarker == aMarker) otherMarker = [markers objectAtIndex:1];
  739.  
  740.         if ([theEdge isEqualToString:STR_LEFT]) {
  741.             rect.origin.x = location;
  742.             [otherMarker setMarkerLocation:NSMaxX(rect)];
  743.         }
  744.         else if ([theEdge isEqualToString:STR_RIGHT]) {
  745.             rect.origin.x = location - NSWidth(rect);
  746.             [otherMarker setMarkerLocation:NSMinX(rect)];
  747.         }
  748.         else if ([theEdge isEqualToString:STR_TOP]) {
  749.             if ([self isFlipped]) {
  750.                 rect.origin.y = location;
  751.                 [otherMarker setMarkerLocation:NSMaxY(rect)];
  752.             } else {
  753.                 rect.origin.y = location - NSHeight(rect);
  754.                 [otherMarker setMarkerLocation:NSMinY(rect)];
  755.             }
  756.         }
  757.         else if ([theEdge isEqualToString:STR_BOTTOM]) {
  758.             if ([self isFlipped]) {
  759.                 rect.origin.y = location - NSHeight(rect);
  760.                 [otherMarker setMarkerLocation:NSMinY(rect)];
  761.             } else {
  762.                 rect.origin.y = location;
  763.                 [otherMarker setMarkerLocation:NSMaxY(rect)];
  764.             }
  765.         }
  766.     }
  767.  
  768.     [selectedItem setFrame:rect];
  769.     [self setNeedsDisplayInRect:rect];
  770.  
  771.     return location;
  772. }
  773.  
  774.  
  775. - (void)rulerView:(NSRulerView *)aRulerView
  776.     didMoveMarker:(NSRulerMarker *)aMarker
  777. {
  778.     [self updateSelectedRectFromRulers];
  779.     return;
  780. }
  781.  
  782.  
  783. - (BOOL)rulerView:(NSRulerView *)aRulerView
  784.     shouldRemoveMarker:(NSRulerMarker *)aMarker
  785. {
  786.     if (selectedItem && ![selectedItem isLocked]) return YES;
  787.     return NO;
  788. }
  789.  
  790.  
  791. - (void)rulerView:(NSRulerView *)aRulerView
  792.     didRemoveMarker:(NSRulerMarker *)aMarker
  793. {
  794.     if (!selectedItem) return;
  795.  
  796.     [self setNeedsDisplayInRect:[selectedItem frame]];
  797.     [rects removeObject:selectedItem];
  798.     selectedItem = nil;
  799.     [self updateRulers];
  800.  
  801.     return;
  802. }
  803.  
  804.  
  805. - (BOOL)rulerView:(NSRulerView *)aRulerView
  806.     shouldAddMarker:(NSRulerMarker *)aMarker
  807. {
  808.     return YES;
  809. }
  810.  
  811.  
  812. - (float)rulerView:(NSRulerView *)aRulerView
  813.     willAddMarker:(NSRulerMarker *)aMarker
  814.     atLocation:(float)location
  815. {
  816.     return location;
  817. }
  818.  
  819.  
  820. inline float frand(void) { return (float)rand() / (pow(2, 31)-1); }
  821.  
  822.  
  823. - (void)rulerView:(NSRulerView *)aRulerView
  824.     didAddMarker:(NSRulerMarker *)aMarker
  825. {
  826.     NSRect visibleRect;
  827.     float theOtherCoord;
  828.     NSRect newRect;
  829.     NSColor *newColor;
  830.     ColorRect *newColorRect;
  831.  
  832.     visibleRect = [self visibleRect];
  833.  
  834.     [aMarker setRemovable:YES];
  835.  
  836.     if ([aRulerView orientation] == NSHorizontalRuler) {
  837.         theOtherCoord = NSMaxY(visibleRect) - 165.0;
  838.         newRect = NSMakeRect([aMarker markerLocation], theOtherCoord, 115.0, 115.0);
  839.     } else {
  840.         if ([self isFlipped]) {
  841.             theOtherCoord = NSMinX(visibleRect) + 50;
  842.             newRect = NSMakeRect(theOtherCoord, [aMarker markerLocation],
  843.                 115.0, 115.0);
  844.         } else {
  845.             theOtherCoord = NSMinX(visibleRect) + 50;
  846.             newRect = NSMakeRect(theOtherCoord, [aMarker markerLocation] - 115.0,
  847.                 115.0, 115.0);
  848.         }
  849.     }
  850.  
  851.     newColor = [NSColor colorWithCalibratedRed:frand() green:frand()
  852.         blue:frand() alpha:1.0];
  853.  
  854.     newColorRect = [[ColorRect alloc] initWithFrame:newRect color:newColor];
  855.     [rects addObject:newColorRect];
  856.     [newColorRect release];
  857.     [self selectRect:newColorRect];
  858.  
  859.     return;
  860. }
  861.  
  862.  
  863. - (void)rulerView:(NSRulerView *)aRulerView
  864.     handleMouseDown:(NSEvent *)theEvent
  865. {
  866.     NSRulerMarker *newMarker;
  867.  
  868.     if ([aRulerView orientation] == NSHorizontalRuler) {
  869.         newMarker = [[NSRulerMarker alloc] initWithRulerView:aRulerView
  870.             markerLocation:0.0 image:leftImage imageOrigin:NSZeroPoint];
  871.     } else {
  872.         newMarker = [[NSRulerMarker alloc] initWithRulerView:aRulerView
  873.             markerLocation:0.0 image:topImage imageOrigin:NSMakePoint(8.0, 8.0)];
  874.     }
  875.     [aRulerView trackMarker:newMarker withMouseEvent:theEvent];
  876.     [newMarker release];
  877.     return;
  878. }
  879.  
  880.  
  881. - (void)rulerView:(NSRulerView *)aRulerView
  882.     willSetClientView:(NSView *)newClient
  883. {
  884.     return;
  885. }
  886.  
  887.  
  888. @end
  889.