home *** CD-ROM | disk | FTP | other *** search
-
- #import "TreeView.h"
- #import "TreeButton.h"
- #import "NamedTree.h"
- #import "Line.h"
-
- // constants to determine how the buttons are laid out
- #define BUTTONWIDTH 155.0
- #define BUTTONHEIGHT 24.0
- #define VERTSPACING 8.0
- #define HORIZSPACING 40.0
-
- @implementation TreeView
-
- - initFrame:(const NXRect *)frameRect
- {
- [super initFrame:frameRect];
- [self setAutosizing:(unsigned int) (NX_WIDTHSIZABLE | NX_HEIGHTSIZABLE)];
-
- currentButton = nil;
- lineList = nil;
- priorButton = nil;
- [selectedField setNextText: selectedField];
- [selectedField setPreviousText: selectedField];
- currScale = 1.0;
-
- [self registerForDragging];
- [self setOpaque:YES];
-
- return self;
- }
-
- - buildTreeFromNode:aNode bottom:(double)ybot
- top:(double)ytop atX:(double)xpos parent:(NXPoint *)pos
- { // add a button representing the node to the View
- // This method is recursive.
- NXRect butFrame = {{(xpos + HORIZSPACING),
- (ybot + (ytop - ybot) / 2 - BUTTONHEIGHT / 2)},
- {BUTTONWIDTH, BUTTONHEIGHT}};
- id newButton = [[[TreeButton alloc] initFrame:&butFrame]
- setTreeNode:aNode];
- id kid, kids = [aNode branches];
- int numBranches = [kids count];
- int i, treeWidth; double diff, accum = ybot;
- NXPoint myCenter = {(NX_X(&butFrame)),
- (NX_Y(&butFrame) + BUTTONHEIGHT / 2)};
- id newLine;
-
- [newButton setTitle:[aNode label]];
- [self addSubview:newButton];
- // line to parent:
- if (pos) { // NULL if root, so no line
- NXPoint parentRight = { pos->x + BUTTONWIDTH, pos->y };
- newLine = [[Line alloc] init];
- [newLine setStart:&parentRight end:&myCenter];
- [lineList addObject:newLine];
- }
- // now add any children and the lines to them.
- for (i=numBranches - 1; i >= 0; i--) { // loop isn't entered if no kids.
- kid = [kids objectAt:i];
- treeWidth = [kid width];
- diff = (treeWidth * (BUTTONHEIGHT + VERTSPACING));
- [self buildTreeFromNode:kid bottom:accum
- top:(accum + diff + VERTSPACING)
- atX:(xpos + BUTTONWIDTH + HORIZSPACING)
- parent:&myCenter];
- accum += diff;
- }
- return self;
- }
-
- - attachTree:aTree
- {
- int treeWidth = [aTree width];
- int treeDepth = [aTree depth];
- double height = (treeWidth * (BUTTONHEIGHT + VERTSPACING) + VERTSPACING);
- double width = (treeDepth * (BUTTONWIDTH + HORIZSPACING) + HORIZSPACING);
-
- treeRoot = aTree;
- if (lineList) [[lineList freeObjects] free];
- lineList = [[List alloc] init];
- // resize the View to accomodate the Buttons
- [self sizeTo:width :height];
- [self buildTreeFromNode:aTree bottom:0.0 top:height atX:0.0 parent:NULL];
-
- return self;
- }
-
- - drawSelf:(NXRect *)rects :(int)rectCount // standard rendering method
- {
- int i;
- NXColor color = [[self window] backgroundColor];
-
- NXRectClip(rects); // clipping will reduce rendering time a bit
- // and is needed to keep lines from rendering outside the drawing area
-
- if (NXEqualColor(color, NX_COLORLTGRAY))
- color = NX_COLORDKGRAY;
-
- // PSsetgray(NX_DKGRAY);
- NXSetColor(color);
- NXRectFill(&bounds);
- // PSsetgray(NX_BLACK);
- NXSetColor(NX_COLORBLACK);
- PSsetlinewidth(2.0);
-
- for (i=0; i<[lineList count]; i++) // draw any lines in drawing area
- [[lineList objectAt:i] renderIfInRect:rects];
- for (i=0; i<[[self subviews] count]; i++) // redraw needed buttons
- [[[self subviews] objectAt:i] display:rects :rectCount];
-
- return self;
- }
-
- - scale:sender
- {
- id popUp = [sender window];
- short index = [popUp indexOfItem:[popUp selectedItem]];
- // 25% 50% 75% 100% 125% 150% 200% SizeToFit
- // 0 1 2 3 4 5 6 7
- float factors[] = {0.25, 0.50, 0.75, 1.0, 1.25, 1.50, 2.0, 0.20};
- NXPoint center;
- NXCoord scale = factors[index];
-
- // Initialize width and height bounds when view is not scaled.
- if (currScale == 1.0)
- {
- origWidth = NX_WIDTH(&bounds);
- origHeight = NX_HEIGHT(&bounds);
- }
-
- // Remember the center to we can reset it after the scaling.
- center.x = NX_X(&bounds) + NX_WIDTH(&bounds) / 2;
- center.y = NX_Y(&bounds) + NX_HEIGHT(&bounds) / 2;
-
- // Scale the view to its new size
- if (index == 3) // 100% (Normal Size)
- {
- [self setDrawSize:origWidth :origHeight];
- currScale = 1.0;
- }
- else
- {
- currScale *= scale;
- [self setDrawSize:NX_WIDTH(&bounds) / currScale
- :NX_HEIGHT(&bounds) / currScale];
- }
-
- // Reset the center point
- [self setDrawOrigin:center.x - NX_WIDTH(&bounds) / 2
- :center.y - NX_HEIGHT(&bounds) / 2];
-
- // Ensure that selected button, if any, is visible.
- [self displayBut:currentButton];
-
- [self update];
-
- return self;
- }
-
- - setCurrentButton:but
- {
- if (but)
- {
- priorButton = currentButton;
- if (priorButton)
- {
- [priorButton setType:NX_MOMENTARYPUSH];
- [priorButton setState:0];
- }
- currentButton = but;
- [currentButton setType:NX_ONOFF]; [currentButton setState:1];
- // [selectedField setStringValueNoCopy: [but title]];
- }
- return but;
- }
-
- - setCurrButtonByName:sender
- {
- id currBut = [self getButByName:[sender stringValue]];
-
- [self displayBut:[self setCurrentButton:currBut]];
- [treeRoot act:currBut];
- return currBut;
- }
-
- - getButByName:(const char*)name
- {
- id butList = [self subviews];
- id but = nil;
- id currBut = nil;
- int i = 0;
-
- while (!currBut && (but = [butList objectAt:i++]))
- {
- if (!strcmp([but title], name))
- currBut = but;
- }
- return currBut;
- }
-
- - displayButByName:sender
- {
- id but = [self getButByName:[sender stringValue]];
-
- if (but)
- [self displayBut:but];
- return but;
- }
-
- - displayBut:but
- {
- NXRect butRect;
-
- if (but)
- {
- [[but getBounds:&butRect] convertRectToSuperview:&butRect];
- [self scrollRectToVisible:&butRect];
- }
- return self;
- }
-
- @end
-
-
-
- // Color dragging support
-
- BOOL includesType(const NXAtom *types, NXAtom type)
- {
- if (types)
- while (*types)
- if (*types++ == type)
- return YES;
- return NO;
- }
-
- @implementation TreeView(Drag)
-
- - registerForDragging
- {
- [self registerForDraggedTypes:&NXColorPboardType count:1];
- return self;
- }
-
- - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
- {
- // NXDragOperation sourceMask = [sender draggingSourceOperationMask];
- Pasteboard *pboard = [sender draggingPasteboard];
-
- return ((includesType([pboard types], NXColorPboardType))
- ? NX_DragOperationGeneric : NX_DragOperationNone);
- }
-
- - (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
- {
- return YES;
- }
-
- - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
- {
- Pasteboard *pboard = [sender draggingPasteboard];
-
- if (includesType([pboard types], NXColorPboardType))
- {
- NXColor color = NXReadColorFromPasteboard(pboard);
- [[self window] setBackgroundColor:color];
- [self display]; // reflect color change
- return YES;
- }
- else
- return NO;
- }
-
- - concludeDragOperation:(id <NXDraggingInfo>)sender
- {
- // Return value ignored.
- return nil;
- }
-
- @end
-