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