home *** CD-ROM | disk | FTP | other *** search
- // HotShape.m
- // By Charles G. Fleming, Educational Computing Services, Allegheny College.
- // Copyright 1992 Allegheny College
- // You may freely copy, distribute and reuse this code.
- // Allegheny College and the author disclaim any warranty of any kind,
- // expressed or implied, as to its fitness for any particular use.
- // This work was partially supported by a grant from the Vira Heinz Endowment.
-
- #import "HotShape.h"
- #import "HotPath.h"
- #import "SmallCell.h"
-
- @implementation HotShape
-
- - (const char *)getInspectorClassName
- {
- return "HotShapeInspector";
- }
-
- // Scale the HotShape object so that it has unit length and height.
- // Give it a custom cell so that it can be resized to an arbitrarily small
- // size in InterfaceBuilder. The default shape will be a diamond shape.
- - initFrame:(const NXRect *)frameRect
- {
- SmallCell *smallCell;
-
- self = [super initFrame:frameRect];
-
- hotPathName = malloc(1);
- visible = YES;
- [self scale:bounds.size.width :bounds.size.height];
-
- smallCell = [[SmallCell allocFromZone:[self zone]] init];
- [self setCell:smallCell];
-
- // Define the hot shape paths that will be used.
- setHotPaths();
-
- tag = 0;
- [self setHotPathName:"diamond"];
-
- [self setOpaque:NO];
- return self;
- }
-
- - (BOOL)acceptsFirstMouse
- {
- return YES;
- }
-
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
- drawHotPath(hotPathName, visible);
- return self;
- }
-
- - awake
- {
- setHotPaths();
- return self;
- }
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- [super sizeTo:width :height];
- [self scale:bounds.size.width :bounds.size.height];
- return self;
- }
-
- - setHotPathName:(const char *)name
- {
- free(hotPathName);
- hotPathName = malloc(strlen(name) + 1);
- strcpy(hotPathName, name);
- return self;
- }
-
- - (char *)hotPathName
- {
- return hotPathName;
- }
-
- - (BOOL)visible
- {
- return visible;
- }
-
- - setVisible:(BOOL)seeIt
- {
- visible = seeIt;
- return self;
- }
-
- - read:(NXTypedStream *)typedStream
- {
- [super read:typedStream];
- NXReadTypes(typedStream, "*s", &hotPathName, &visible);
- return self;
- }
-
- - write:(NXTypedStream *)typedStream
- {
- [super write:typedStream];
-
- NXWriteTypes(typedStream, "*s", &hotPathName, &visible);
- return self;
- }
-
- - mouseDown:(NXEvent *)theEvent
- {
- SEL action;
- NXEvent *nextEvent;
- BOOL finished = NO, done = NO;
- int at;
- NXPoint windowCoords = {theEvent->location.x, theEvent->location.y};
- View *currentview, *currentSuperview;
- List *subviewList;
-
- if([self inHotPath:windowCoords])
- {
- if([cell isEnabled])
- while(!finished)
- {
- nextEvent = [NXApp getNextEvent:NX_MOUSEUPMASK];
- if(nextEvent->type == NX_MOUSEUP)
- {
- windowCoords.x = nextEvent->location.x;
- windowCoords.y = nextEvent->location.y;
- if([self inHotPath:windowCoords])
- {
- action = [cell action];
- if(action)
- [self sendAction:action to:[cell target]];
- }
- finished = YES;
- }
- }
- }
- else
- {
- // Pass on to the location to lower hotshape;
- currentview = self;
- currentSuperview = superview;
- while(currentSuperview && !done)
- {
- subviewList = [currentSuperview subviews];
- at = [subviewList indexOf:currentview] - 1;
- done = [self traverseTreeWithRoot:currentSuperview startAt:at
- usingLocation:windowCoords];
- currentview = currentSuperview;
- currentSuperview = [currentSuperview superview];
- }
- }
- return self;
- }
-
- // Traverse a view's subview hierarchy, starting at the specified node,
- // until we get to the front-most hotshape. If specified location is in
- // the hot path of the front-most hotshape we return YES. In all other
- // cases we return NO.
- - (BOOL)traverseTreeWithRoot:root startAt:(int)at
- usingLocation:(NXPoint)windowCoords
- {
- SEL action;
- BOOL flag = NO;
- List *subviewList;
- int index;
- id node;
- SmallCell *smallCell;
-
- subviewList = [root subviews];
- for(index = at; index > -1 && !flag; index--)
- {
- node = [subviewList objectAt:index];
- if([node subviews])
- flag = [self traverseTreeWithRoot:node
- startAt:[[node subviews] count]-1
- usingLocation:windowCoords];
- else
- if([node isKindOf:[HotShape class]])
- {
- flag = [node inHotPath:windowCoords];
- if(flag)
- {
- smallCell = [node cell];
- action = [smallCell action];
- if(action)
- [node sendAction:action to:[smallCell target]];
- }
- }
- }
-
- return flag;
- }
-
- // Determines if a point (given in window coords) is in the hot path.
- - (BOOL)inHotPath:(NXPoint)location
- {
- NXPoint viewCoords = {location.x, location.y};
- int inRegion = NO;
-
- [self convertPoint:&viewCoords fromView:nil];
- [self lockFocus];
- inHotRegion(hotPathName, viewCoords.x, viewCoords.y, &inRegion);
- [self unlockFocus];
- return inRegion;
- }
- @end
-