This is Rubberband.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ /* Augmented by Slugg Jello, Mouthing Flowers 152 20th Ave. #1 Seattle, WA. 98112 slugg@mouthers.nwnexus.wa.com */ #import "Rubberband.h" #import <appkit/Window.h> #import <appkit/View.h> #import <appkit/Application.h> #import <appkit/appkit.h> #include "Rubber.h" // psw stuff #include <math.h> #define DRAG_MASK (NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK) //#define DEBUG_OUTPUT #define RUBBERBAND_WINDOW_WIDTH 1 @implementation Rubberband /***** PRIVATE METHODS *****/ - (void)correctRect :(NXRect *)rect { /* make sure it makes sense to NX routines which don't like negative size values */ if (rect->size.width < 0.0) { rect->origin.x += rect->size.width; rect->size.width = -rect->size.width; } if (rect->size.height < 0.0) { rect->origin.y += rect->size.height; rect->size.height = -rect->size.height; } } - setPosition /* Position and draw rubberband. Assumes currentRect is set and rubberband windows are initialized. Also assumes currentRect is 'corrected'. */ { struct { NXRect top,left,bottom,right; } points; NXRect tRect,screenRect=currentRect; [[myView window] convertBaseToScreen :&screenRect.origin]; /**** set size of each rubberband side ****/ /* left */ tRect = screenRect; tRect.size.width = RUBBERBAND_WINDOW_WIDTH; tRect.size.height = MAX(RUBBERBAND_WINDOW_WIDTH,screenRect.size.height); points.left = tRect; /* right */ tRect.origin.x += screenRect.size.width - 1.0; points.right = tRect; /* bottom */ tRect = screenRect; tRect.origin.x += 1.0; tRect.size.width = MAX(RUBBERBAND_WINDOW_WIDTH,screenRect.size.width-1.0); tRect.size.height = RUBBERBAND_WINDOW_WIDTH; points.bottom = tRect; /* top */ tRect.origin.y += screenRect.size.height - 1.0; points.top = tRect; /* this'll erase old one and draw new one in new position */ PSWPositionRect((float *)&points); return self; } /***** PUBLIC METHODS *****/ - initWithView :aView { [self init]; [self setView :aView]; return self; } - init { [super init]; myView = nil; [self setPivot :RB_CORNER]; [self setInclusive :TRUE]; return self; } - setView :aView /* returns previous myView, sets bounds to those of aView */ { id oldView = myView; NXRect rect; if (aView == nil) { [self setBounds :NULL]; return oldView; } myView = aView; #if defined(DEBUG_OUTPUT) fprintf(stderr,"view == %p\n",myView); #endif [myView getBounds :&rect]; [self setBounds:&rect]; return oldView; } - doStretch :(NXEvent *)event /* stretch the rubber band until user lets go of mouse */ { int oldMask; NXEvent *nextEvent; NXPoint mouseLocation; NXPoint pivotPt; NXRect tRect; if (myView == nil) return self; #if defined(DEBUG_OUTPUT) fprintf(stderr,"we's a trackin\n"); #endif currentRect.origin = event->location; currentRect.size.width = currentRect.size.height = 0.0; if (flags.useBounds) /* do nothing if first click isn't in bounds */ if (![myView mouse :¤tRect.origin inRect:&boundsRect]) return self; mouseLocation = event->location; /* we want to grab mouse dragged events */ oldMask = [[myView window] addToEventMask:NX_MOUSEDRAGGEDMASK]; if (flags.pivot == RB_CENTER) pivotPt = currentRect.origin; PSWInitRubberband(); [self setPosition]; PSWMakeVisible(TRUE); /* start our event loop, looking for mouse-dragged or mouse-up events */ nextEvent = [NXApp getNextEvent:DRAG_MASK]; tRect = currentRect; while (nextEvent->type != NX_MOUSEUP) { if (flags.pivot == RB_CORNER) { tRect.size.width += nextEvent->location.x - mouseLocation.x; tRect.size.height += nextEvent->location.y - mouseLocation.y; } else { tRect.size.width += (nextEvent->location.x - mouseLocation.x) * 2; tRect.size.height += (nextEvent->location.y - mouseLocation.y) * 2; tRect.origin.x = pivotPt.x - tRect.size.width / 2; tRect.origin.y = pivotPt.y - tRect.size.height / 2; } currentRect = tRect; [self correctRect :¤tRect]; if (flags.useBounds) NXIntersectionRect(&boundsRect,¤tRect); NXIntegralRect(¤tRect); mouseLocation = nextEvent->location; [self setPosition]; #if defined(DEBUG_OUTPUT) fprintf(stderr, "current rect: origin (%3.2lf,%3.2lf), size (%3.2lf,%3.2lf)\n", currentRect.origin.x,currentRect.origin.y, currentRect.size.width,currentRect.size.height); #endif nextEvent = [NXApp getNextEvent:DRAG_MASK]; } /* reset the event mask */ [[myView window] setEventMask:oldMask]; #if defined(DEBUG_OUTPUT) fprintf(stderr,"we's a done trackin\n"); #endif PSWMakeVisible(FALSE); return self; } - currentRect :(NXRect *)rect /* return currentRect in rect in View coords */ { if (!rect) return self; *rect = currentRect; if (!flags.inclusive) { ++rect->origin.x; ++rect->origin.y; rect->size.width -= 2.0; rect->size.height -= 2.0; } /* convert from Window to View coords */ [myView convertRect:rect fromView:nil]; return self; } - bounds :(NXRect *)rect /* return boundsRect in rect in View coords */ { if (!rect) return self; *rect = boundsRect; /* convert from Window to View coords */ [myView convertRect:rect fromView:nil]; return self; } - setBounds :(const NXRect *)rect /* set boundaries within which the rubberband may be dragged. rect is in myView coords. if rect is NULL, then no bounds. */ { if (rect == NULL) { flags.useBounds = FALSE; return self; } flags.useBounds = TRUE; boundsRect = *rect; /* convert from View to Window coords */ [myView convertRect:&boundsRect toView:nil]; #if defined(DEBUG_OUTPUT) fprintf(stderr,"bounds: origin (%f %f) size (%f %f)\n",boundsRect.origin.x, boundsRect.origin.y,boundsRect.size.width,boundsRect.size.height); #endif return self; } - setCurrentRectToBounds; { flags.useBounds = TRUE; boundsRect = currentRect; return self; } - (int)setPivot :(int)pivot { int oldPivot = flags.pivot; flags.pivot = pivot; #if defined(DEBUG_OUTPUT) fprintf(stderr,"pivot == %s\n", flags.pivot == RB_CORNER ? "CORNER":"CENTER"); #endif return oldPivot; } - (BOOL)setInclusive:(BOOL)onoff { BOOL bPrev = flags.inclusive; flags.inclusive = onoff; return bPrev; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.