comparison 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
comparison
equal deleted inserted replaced
162:4de2936b4e77 163:0132846995bd
1
2 #import "TreeView.h"
3 #import "TreeButton.h"
4 #import "NamedTree.h"
5 #import "Line.h"
6
7 // constants to determine how the buttons are laid out
8 #define BUTTONWIDTH 155.0
9 #define BUTTONHEIGHT 24.0
10 #define VERTSPACING 8.0
11 #define HORIZSPACING 40.0
12
13 @implementation TreeView
14
15 - initFrame:(const NXRect *)frameRect
16 {
17 [super initFrame:frameRect];
18 [self setAutosizing:(unsigned int) (NX_WIDTHSIZABLE | NX_HEIGHTSIZABLE)];
19
20 currentButton = nil;
21 lineList = nil;
22 priorButton = nil;
23 [selectedField setNextText: selectedField];
24 [selectedField setPreviousText: selectedField];
25 currScale = 1.0;
26
27 [self registerForDragging];
28 [self setOpaque:YES];
29
30 return self;
31 }
32
33 - buildTreeFromNode:aNode bottom:(double)ybot
34 top:(double)ytop atX:(double)xpos parent:(NXPoint *)pos
35 { // add a button representing the node to the View
36 // This method is recursive.
37 NXRect butFrame = {{(xpos + HORIZSPACING),
38 (ybot + (ytop - ybot) / 2 - BUTTONHEIGHT / 2)},
39 {BUTTONWIDTH, BUTTONHEIGHT}};
40 id newButton = [[[TreeButton alloc] initFrame:&butFrame]
41 setTreeNode:aNode];
42 id kid, kids = [aNode branches];
43 int numBranches = [kids count];
44 int i, treeWidth; double diff, accum = ybot;
45 NXPoint myCenter = {(NX_X(&butFrame)),
46 (NX_Y(&butFrame) + BUTTONHEIGHT / 2)};
47 id newLine;
48
49 [newButton setTitle:[aNode label]];
50 [self addSubview:newButton];
51 // line to parent:
52 if (pos) { // NULL if root, so no line
53 NXPoint parentRight = { pos->x + BUTTONWIDTH, pos->y };
54 newLine = [[Line alloc] init];
55 [newLine setStart:&parentRight end:&myCenter];
56 [lineList addObject:newLine];
57 }
58 // now add any children and the lines to them.
59 for (i=numBranches - 1; i >= 0; i--) { // loop isn't entered if no kids.
60 kid = [kids objectAt:i];
61 treeWidth = [kid width];
62 diff = (treeWidth * (BUTTONHEIGHT + VERTSPACING));
63 [self buildTreeFromNode:kid bottom:accum
64 top:(accum + diff + VERTSPACING)
65 atX:(xpos + BUTTONWIDTH + HORIZSPACING)
66 parent:&myCenter];
67 accum += diff;
68 }
69 return self;
70 }
71
72 - attachTree:aTree
73 {
74 int treeWidth = [aTree width];
75 int treeDepth = [aTree depth];
76 double height = (treeWidth * (BUTTONHEIGHT + VERTSPACING) + VERTSPACING);
77 double width = (treeDepth * (BUTTONWIDTH + HORIZSPACING) + HORIZSPACING);
78
79 treeRoot = aTree;
80 if (lineList) [[lineList freeObjects] free];
81 lineList = [[List alloc] init];
82 // resize the View to accomodate the Buttons
83 [self sizeTo:width :height];
84 [self buildTreeFromNode:aTree bottom:0.0 top:height atX:0.0 parent:NULL];
85
86 return self;
87 }
88
89 - drawSelf:(NXRect *)rects :(int)rectCount // standard rendering method
90 {
91 NXColor color = [[self window] backgroundColor];
92
93 if (NXEqualColor(color, NX_COLORLTGRAY))
94 color = NX_COLORDKGRAY;
95
96 // PSsetgray(NX_DKGRAY);
97 NXSetColor(color);
98 NXRectFill(&bounds);
99 // PSsetgray(NX_BLACK);
100 NXSetColor(NX_COLORBLACK);
101 PSsetlinewidth(2.0);
102
103 [lineList makeObjectsPerform:@selector(render)];
104 [[self subviews] makeObjectsPerform:@selector(display)];
105 return self;
106 }
107
108 - scale:sender
109 {
110 id popUp = [sender window];
111 short index = [popUp indexOfItem:[popUp selectedItem]];
112 // 25% 50% 75% 100% 125% 150% 200% SizeToFit
113 // 0 1 2 3 4 5 6 7
114 float factors[] = {0.25, 0.50, 0.75, 1.0, 1.25, 1.50, 2.0, 0.20};
115 NXPoint center;
116 NXCoord scale = factors[index];
117
118 // Initialize width and height bounds when view is not scaled.
119 if (currScale == 1.0)
120 {
121 origWidth = NX_WIDTH(&bounds);
122 origHeight = NX_HEIGHT(&bounds);
123 }
124
125 // Remember the center to we can reset it after the scaling.
126 center.x = NX_X(&bounds) + NX_WIDTH(&bounds) / 2;
127 center.y = NX_Y(&bounds) + NX_HEIGHT(&bounds) / 2;
128
129 // Scale the view to its new size
130 if (index == 3) // 100% (Normal Size)
131 {
132 [self setDrawSize:origWidth :origHeight];
133 currScale = 1.0;
134 }
135 else
136 {
137 currScale *= scale;
138 [self setDrawSize:NX_WIDTH(&bounds) / currScale
139 :NX_HEIGHT(&bounds) / currScale];
140 }
141
142 // Reset the center point
143 [self setDrawOrigin:center.x - NX_WIDTH(&bounds) / 2
144 :center.y - NX_HEIGHT(&bounds) / 2];
145
146 // Ensure that selected button, if any, is visible.
147 [self displayBut:currentButton];
148
149 [self update];
150
151 return self;
152 }
153
154 - setCurrentButton:but
155 {
156 if (but)
157 {
158 priorButton = currentButton;
159 if (priorButton)
160 {
161 [priorButton setType:NX_MOMENTARYPUSH];
162 [priorButton setState:0];
163 }
164 currentButton = but;
165 [currentButton setType:NX_ONOFF]; [currentButton setState:1];
166 // [selectedField setStringValueNoCopy: [but title]];
167 }
168 return but;
169 }
170
171 - setCurrButtonByName:sender
172 {
173 id currBut = [self getButByName:[sender stringValue]];
174
175 [self displayBut:[self setCurrentButton:currBut]];
176 [treeRoot act:currBut];
177 return currBut;
178 }
179
180 - getButByName:(const char*)name
181 {
182 id butList = [self subviews];
183 id but = nil;
184 id currBut = nil;
185 int i = 0;
186
187 while (!currBut && (but = [butList objectAt:i++]))
188 {
189 if (!strcmp([but title], name))
190 currBut = but;
191 }
192 return currBut;
193 }
194
195 - displayButByName:sender
196 {
197 id but = [self getButByName:[sender stringValue]];
198
199 if (but)
200 [self displayBut:but];
201 return but;
202 }
203
204 - displayBut:but
205 {
206 NXRect butRect;
207
208 if (but)
209 {
210 [[but getBounds:&butRect] convertRectToSuperview:&butRect];
211 [self scrollRectToVisible:&butRect];
212 }
213 return self;
214 }
215
216 @end
217
218
219
220 // Color dragging support
221
222 BOOL includesType(const NXAtom *types, NXAtom type)
223 {
224 if (types)
225 while (*types)
226 if (*types++ == type)
227 return YES;
228 return NO;
229 }
230
231 @implementation TreeView(Drag)
232
233 - registerForDragging
234 {
235 [self registerForDraggedTypes:&NXColorPboardType count:1];
236 return self;
237 }
238
239 - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
240 {
241 NXDragOperation sourceMask = [sender draggingSourceOperationMask];
242 Pasteboard *pboard = [sender draggingPasteboard];
243
244 return ((includesType([pboard types], NXColorPboardType))
245 ? NX_DragOperationGeneric : NX_DragOperationNone);
246 }
247
248 - (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
249 {
250 return YES;
251 }
252
253 - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
254 {
255 Pasteboard *pboard = [sender draggingPasteboard];
256
257 if (includesType([pboard types], NXColorPboardType))
258 {
259 NXColor color = NXReadColorFromPasteboard(pboard);
260 [[self window] setBackgroundColor:color];
261 [self display]; // reflect color change
262 return YES;
263 }
264 else
265 return NO;
266 }
267
268 - concludeDragOperation:(id <NXDraggingInfo>)sender
269 {
270 // Return value ignored.
271 return nil;
272 }
273
274 @end