Mercurial > hg > xemacs-beta
diff pkg-src/tree-nx/TreeView.m @ 163:0132846995bd r20-3b8
Import from CVS: tag r20-3b8
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:43:35 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg-src/tree-nx/TreeView.m Mon Aug 13 09:43:35 2007 +0200 @@ -0,0 +1,274 @@ + +#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 +{ + NXColor color = [[self window] backgroundColor]; + + if (NXEqualColor(color, NX_COLORLTGRAY)) + color = NX_COLORDKGRAY; + + // PSsetgray(NX_DKGRAY); + NXSetColor(color); + NXRectFill(&bounds); + // PSsetgray(NX_BLACK); + NXSetColor(NX_COLORBLACK); + PSsetlinewidth(2.0); + + [lineList makeObjectsPerform:@selector(render)]; + [[self subviews] makeObjectsPerform:@selector(display)]; + 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