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.