1
2 /*
3 * bltTreeViewStyle.c --
4 *
5 * This module implements styles for treeview widget cells.
6 *
7 * Copyright 1998-1999 Lucent Technologies, Inc.
8 *
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby
11 * granted, provided that the above copyright notice appear in all
12 * copies and that both that the copyright notice and warranty
13 * disclaimer appear in supporting documentation, and that the names
14 * of Lucent Technologies or any of their entities not be used in
15 * advertising or publicity pertaining to distribution of the software
16 * without specific, written prior permission.
17 *
18 * Lucent Technologies disclaims all warranties with regard to this
19 * software, including all implied warranties of merchantability and
20 * fitness. In no event shall Lucent Technologies be liable for any
21 * special, indirect or consequential damages or any damages
22 * whatsoever resulting from loss of use, data or profits, whether in
23 * an action of contract, negligence or other tortuous action, arising
24 * out of or in connection with the use or performance of this
25 * software.
26 *
27 * The "treeview" widget was created by George A. Howlett.
28 * Extensive cleanups and enhancements by Peter MacDonald.
29 */
30
31 #include "bltInt.h"
32
33 #ifndef NO_TREEVIEW
34
35 #include "bltTreeView.h"
36 #include "bltList.h"
37 #include <X11/Xutil.h>
38 #include <X11/Xatom.h>
39
40 #define STYLE_GAP 2
41
42 static Blt_OptionParseProc ObjToSticky;
43 static Blt_OptionPrintProc StickyToObj;
44
45 static Blt_OptionParseProc ObjToIcon;
46 static Blt_OptionPrintProc IconToObj;
47 static Blt_OptionFreeProc FreeIcon;
48 Blt_CustomOption bltTreeViewIconOption =
49 {
50 /* Contains a pointer to the widget that's currently being
51 * configured. This is used in the custom configuration parse
52 * routine for icons. */
53 ObjToIcon, IconToObj, FreeIcon, NULL,
54 };
55 extern Blt_CustomOption bltTreeViewIconsOption;
56
57
58 #define DEF_STYLE_HIGHLIGHT_BACKGROUND STD_NORMAL_BACKGROUND
59 #define DEF_STYLE_HIGHLIGHT_FOREGROUND STD_NORMAL_FOREGROUND
60 #ifdef WIN32
61 #define DEF_STYLE_ACTIVE_BACKGROUND RGB_GREY85
62 #else
63 #define DEF_STYLE_ACTIVE_BACKGROUND RGB_GREY95
64 #endif
65 #define DEF_STYLE_ACTIVE_FOREGROUND STD_ACTIVE_FOREGROUND
66 #define DEF_STYLE_GAP "2"
67
68 typedef struct {
69 TREEVIEW_STYLE_COMMON
70
71 /* TextBox-specific fields */
72 Tcl_Obj *formatCmd;
73
74 int iconside; /* Position of the text in relation to
75 * the icon. */
76 int side; /* Side to anchor cell. */
77
78 } TreeViewTextBox;
79
80 #ifdef WIN32
81 #define DEF_TEXTBOX_CURSOR "arrow"
82 #else
83 #define DEF_TEXTBOX_CURSOR "hand2"
84 #endif /*WIN32*/
85 #define DEF_TEXTBOX_SIDE "left"
86
87 #define CONF_STYLES \
88 {BLT_CONFIG_BORDER, "-activebackground", "activeBackground", \
89 "ActiveBackground", DEF_STYLE_ACTIVE_BACKGROUND, \
90 Blt_Offset(TreeViewStyle, activeBorder), BLT_CONFIG_NULL_OK}, \
91 {BLT_CONFIG_SYNONYM, "-activebg", (char *)NULL, \
92 (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-activebackground"}, \
93 {BLT_CONFIG_SYNONYM, "-activefg", (char *)NULL, \
94 (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-activeforeground"}, \
95 {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground", \
96 "ActiveForeground", DEF_STYLE_ACTIVE_FOREGROUND, \
97 Blt_Offset(TreeViewStyle, activeFgColor), 0}, \
98 {BLT_CONFIG_BORDER, "-background", (char *)NULL, (char *)NULL, \
99 (char *)NULL, Blt_Offset(TreeViewStyle, border), \
100 BLT_CONFIG_NULL_OK|BLT_CONFIG_DONT_SET_DEFAULT}, \
101 {BLT_CONFIG_SYNONYM, "-bg", (char *)NULL, (char *)NULL, (char *)NULL, \
102 0, 0, (ClientData)"-background"}, \
103 {BLT_CONFIG_CURSOR, "-cursor", "cursor", "Cursor", \
104 DEF_TEXTBOX_CURSOR, Blt_Offset(TreeViewStyle, cursor), 0}, \
105 {BLT_CONFIG_BOOLEAN, "-readonly", "readOnly", "ReadOnly", \
106 "False", Blt_Offset(TreeViewStyle, noteditable), \
107 BLT_CONFIG_DONT_SET_DEFAULT},\
108 {BLT_CONFIG_STRING, "-editopts", "editOpts", "EditOpts", \
109 (char *)NULL, Blt_Offset(TreeViewStyle, editOpts), \
110 BLT_CONFIG_NULL_OK}, \
111 {BLT_CONFIG_SYNONYM, "-fg", (char *)NULL, (char *)NULL, (char *)NULL, \
112 0, 0, (ClientData)"-foreground"}, \
113 {BLT_CONFIG_FONT, "-font", (char *)NULL, (char *)NULL, \
114 (char *)NULL, Blt_Offset(TreeViewStyle, font), \
115 BLT_CONFIG_NULL_OK|BLT_CONFIG_DONT_SET_DEFAULT}, \
116 {BLT_CONFIG_COLOR, "-foreground", (char *)NULL, (char *)NULL, \
117 (char *)NULL, Blt_Offset(TreeViewStyle, fgColor), \
118 BLT_CONFIG_NULL_OK|BLT_CONFIG_DONT_SET_DEFAULT }, \
119 {BLT_CONFIG_DISTANCE, "-gap", "gap", "Gap", \
120 DEF_STYLE_GAP, Blt_Offset(TreeViewStyle, gap), \
121 BLT_CONFIG_DONT_SET_DEFAULT}, \
122 {BLT_CONFIG_BOOLEAN, "-hide", (char *)NULL, (char *)NULL, \
123 "False", Blt_Offset(TreeViewStyle, hidden), 0}, \
124 {BLT_CONFIG_BORDER, "-highlightbackground", "highlightBackground", \
125 "HighlightBackground", DEF_STYLE_HIGHLIGHT_BACKGROUND, \
126 Blt_Offset(TreeViewStyle, highlightBorder), \
127 BLT_CONFIG_COLOR_ONLY|BLT_CONFIG_NULL_OK}, \
128 {BLT_CONFIG_COLOR, "-highlightforeground", "highlightForeground", \
129 "HighlightForeground", DEF_STYLE_HIGHLIGHT_FOREGROUND, \
130 Blt_Offset(TreeViewStyle, highlightFgColor), BLT_CONFIG_NULL_OK}, \
131 {BLT_CONFIG_SYNONYM, "-highlightbg",(char *)NULL, \
132 (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-highlightbackground"}, \
133 {BLT_CONFIG_SYNONYM, "-highlightfg", (char *)NULL, \
134 (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-highlightforeground"}, \
135 {BLT_CONFIG_CUSTOM, "-icon", (char *)NULL, (char *)NULL, \
136 (char *)NULL, Blt_Offset(TreeViewStyle, icon), \
137 BLT_CONFIG_NULL_OK, &bltTreeViewIconOption}, \
138 {BLT_CONFIG_INT, "-priority", (char *)NULL, (char *)NULL, \
139 "0", Blt_Offset(TreeViewStyle, priority), 0}, \
140 {BLT_CONFIG_SHADOW, "-shadow", "Shadow", "Shadow", \
141 (char *)NULL, Blt_Offset(TreeViewStyle, shadow), 0}, \
142 {BLT_CONFIG_TILE, "-tile", (char *)NULL, (char *)NULL, \
143 (char *)NULL, Tk_Offset(TreeViewStyle, tile), BLT_CONFIG_NULL_OK, },
144
145 static Blt_ConfigSpec textBoxSpecs[] =
146 {
147 CONF_STYLES
148 {BLT_CONFIG_OBJCMD, "-formatcmd", "formatCmd", "FormatCmd",
149 NULL, Blt_Offset(TreeViewTextBox, formatCmd),
150 BLT_CONFIG_NULL_OK},
151 {BLT_CONFIG_SIDE, "-side", (char *)NULL, (char *)NULL,
152 DEF_TEXTBOX_SIDE, Tk_Offset(TreeViewTextBox, side),
153 BLT_CONFIG_DONT_SET_DEFAULT},
154 {BLT_CONFIG_SIDE, "-iconside", (char *)NULL, (char *)NULL,
155 DEF_TEXTBOX_SIDE, Tk_Offset(TreeViewTextBox, iconside),
156 BLT_CONFIG_DONT_SET_DEFAULT},
157 {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
158 (char *)NULL, 0, 0}
159 };
160
161 typedef struct {
162 TREEVIEW_STYLE_COMMON
163
164 /* Checkbox specific fields. */
165 int size; /* Size of the checkbox. */
166 int showValue; /* If non-zero, display the on/off value. */
167 char *onValue;
168 char *offValue;
169 int lineWidth; /* Linewidth of the surrounding box. */
170 GC bgGC;
171 Tk_3DBorder checkBg; /* Normal background color of cell. */ \
172
173 XColor *boxColor; /* Rectangle (box) color (grey). */
174 XColor *fillColor; /* Fill color (white) */
175 XColor *checkColor; /* Check color (red). */
176
177 GC boxGC;
178 GC fillGC; /* Box fill GC */
179 GC checkGC;
180
181 TextLayout *onPtr, *offPtr;
182 TreeViewIcon *icons; /* Tk images */
183 int boxX, boxW, boxH;
184 int halo;
185
186 } TreeViewCheckBox;
187
188 #define DEF_CHECKBOX_BOX_COLOR "black"
189 #define DEF_CHECKBOX_CHECK_COLOR "darkblue"
190 #define DEF_CHECKBOX_FILL_COLOR "white"
191 #define DEF_CHECKBOX_OFFVALUE "0"
192 #define DEF_CHECKBOX_ONVALUE "1"
193 #define DEF_CHECKBOX_SHOWVALUE "yes"
194 #define DEF_CHECKBOX_HALO "0"
195 #define DEF_CHECKBOX_SIZE "11"
196 #define DEF_CHECKBOX_LINEWIDTH "1"
197 #define DEF_CHECKBOX_GAP "4"
198 #ifdef WIN32
199 #define DEF_CHECKBOX_CURSOR "arrow"
200 #else
201 #define DEF_CHECKBOX_CURSOR "hand2"
202 #endif /*WIN32*/
203
204 static Blt_ConfigSpec checkBoxSpecs[] =
205 {
206 CONF_STYLES
207 {BLT_CONFIG_COLOR, "-boxcolor", "boxColor", "BoxColor",
208 DEF_CHECKBOX_BOX_COLOR, Blt_Offset(TreeViewCheckBox, boxColor), 0},
209 {BLT_CONFIG_DISTANCE, "-boxsize", "boxSize", "BoxSize",
210 DEF_CHECKBOX_SIZE, Blt_Offset(TreeViewCheckBox, size),
211 BLT_CONFIG_DONT_SET_DEFAULT},
212 {BLT_CONFIG_BORDER, "-checkbg", "checkBg", "checkBg",
213 (char *)NULL, Blt_Offset(TreeViewCheckBox, checkBg), BLT_CONFIG_NULL_OK},
214 {BLT_CONFIG_COLOR, "-checkcolor", "checkColor", "CheckColor",
215 DEF_CHECKBOX_CHECK_COLOR, Blt_Offset(TreeViewCheckBox, checkColor), 0},
216 {BLT_CONFIG_CUSTOM, "-checkicons", "checkIcons", "CheckIcons",
217 (char *)NULL, Blt_Offset(TreeViewCheckBox, icons),
218 BLT_CONFIG_NULL_OK, &bltTreeViewIconsOption},
219 {BLT_CONFIG_COLOR, "-fillcolor", "fillColor", "FillColor",
220 DEF_CHECKBOX_FILL_COLOR, Blt_Offset(TreeViewCheckBox, fillColor), 0},
221 {BLT_CONFIG_TILE, "-filltile", "fillTile", "FillTile",
222 (char *)NULL, Blt_Offset(TreeViewCheckBox, fillTile), BLT_CONFIG_NULL_OK, },
223 {BLT_CONFIG_INT, "-halo", "halo", "Halo",
224 DEF_CHECKBOX_HALO, Blt_Offset(TreeViewCheckBox, halo),
225 0},
226 {BLT_CONFIG_DISTANCE, "-linewidth", "lineWidth", "LineWidth",
227 DEF_CHECKBOX_LINEWIDTH,
228 Blt_Offset(TreeViewCheckBox, lineWidth),
229 BLT_CONFIG_DONT_SET_DEFAULT},
230 {BLT_CONFIG_STRING, "-offvalue", "offValue", "OffValue",
231 DEF_CHECKBOX_OFFVALUE, Blt_Offset(TreeViewCheckBox, offValue),
232 BLT_CONFIG_NULL_OK},
233 {BLT_CONFIG_STRING, "-onvalue", "onValue", "OnValue",
234 DEF_CHECKBOX_ONVALUE, Blt_Offset(TreeViewCheckBox, onValue),
235 BLT_CONFIG_NULL_OK},
236 {BLT_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
237 DEF_CHECKBOX_SHOWVALUE, Blt_Offset(TreeViewCheckBox, showValue),
238 BLT_CONFIG_DONT_SET_DEFAULT},
239 {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
240 (char *)NULL, 0, 0}
241 };
242
243 typedef struct {
244 TREEVIEW_STYLE_COMMON
245
246 /* ComboBox-specific fields */
247
248 int borderWidth; /* Width of outer border surrounding
249 * the entire box. */
250 char *choiceCmd; /* Command to get list of available choices. */
251 char *choices; /* List of available choices. */
252 char *choiceKey; /* Key to get list of available choices. */
253 int scrollWidth;
254 int button;
255 int buttonWidth;
256 int buttonBorderWidth; /* Border width of button. */
257 int buttonRelief; /* Normal relief of button. */
258 TreeViewIcon *buttonIcons;
259
260 } TreeViewComboBox;
261
262 #define DEF_COMBOBOX_BORDERWIDTH "1"
263 #define DEF_COMBOBOX_BUTTON_BORDERWIDTH "1"
264 #define DEF_COMBOBOX_BUTTON_RELIEF "raised"
265 #define DEF_COMBOBOX_RELIEF "flat"
266 #ifdef WIN32
267 #define DEF_COMBOBOX_CURSOR "arrow"
268 #else
269 #define DEF_COMBOBOX_CURSOR "hand2"
270 #endif /*WIN32*/
271
272
273 static Blt_ConfigSpec comboBoxSpecs[] =
274 {
275 CONF_STYLES
276 {BLT_CONFIG_SYNONYM, "-bd", (char *)NULL, (char *)NULL, (char *)NULL, 0,
277 0, (ClientData)"-borderwidth"},
278 {BLT_CONFIG_DISTANCE, "-borderwidth", (char *)NULL, (char *)NULL,
279 DEF_COMBOBOX_BORDERWIDTH, Blt_Offset(TreeViewComboBox, borderWidth),
280 BLT_CONFIG_DONT_SET_DEFAULT},
281 {BLT_CONFIG_DISTANCE, "-buttonborderwidth", "buttonBorderWidth",
282 "ButtonBorderWidth", DEF_COMBOBOX_BUTTON_BORDERWIDTH,
283 Blt_Offset(TreeViewComboBox, buttonBorderWidth),
284 BLT_CONFIG_DONT_SET_DEFAULT},
285 {BLT_CONFIG_CUSTOM, "-buttonicons", "buttonIcons", "ButtonIcons",
286 (char *)NULL, Blt_Offset(TreeViewComboBox, buttonIcons),
287 BLT_CONFIG_NULL_OK, &bltTreeViewIconsOption},
288 {BLT_CONFIG_RELIEF, "-buttonrelief", "buttonRelief", "ButtonRelief",
289 DEF_COMBOBOX_BUTTON_RELIEF, Blt_Offset(TreeViewComboBox, buttonRelief),
290 BLT_CONFIG_DONT_SET_DEFAULT},
291 {BLT_CONFIG_STRING, "-choicecmd", "choiceCmd", "ChoiceCmd",
292 (char *)NULL, Blt_Offset(TreeViewComboBox, choiceCmd),
293 BLT_CONFIG_NULL_OK, 0},
294 {BLT_CONFIG_STRING, "-choicekey", "choiceKey", "ChoiceKey",
295 (char *)NULL, Blt_Offset(TreeViewComboBox, choiceKey),
296 BLT_CONFIG_NULL_OK, 0},
297 {BLT_CONFIG_STRING, "-choices", "choices", "Choices",
298 (char *)NULL, Blt_Offset(TreeViewComboBox, choices),
299 BLT_CONFIG_NULL_OK, 0},
300 {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
301 (char *)NULL, 0, 0}
302 };
303
304 typedef struct {
305 TREEVIEW_STYLE_COMMON
306
307 int windowHeight;
308 int windowWidth;
309 char *windowCmd;
310 int sticky;
311
312 } TreeViewWindowBox;
313
314 #define STICK_NORTH (1<<0)
315 #define STICK_EAST (1<<1)
316 #define STICK_SOUTH (1<<2)
317 #define STICK_WEST (1<<3)
318
319 static Blt_CustomOption bltStickyOption = {
320 ObjToSticky, StickyToObj, NULL, NULL,
321 };
322
323 #define DEF_COMBOBOX_BORDERWIDTH "1"
324 #define DEF_COMBOBOX_BUTTON_BORDERWIDTH "1"
325 #define DEF_COMBOBOX_BUTTON_RELIEF "raised"
326 #define DEF_COMBOBOX_RELIEF "flat"
327 #ifdef WIN32
328 #define DEF_COMBOBOX_CURSOR "arrow"
329 #else
330 #define DEF_COMBOBOX_CURSOR "hand2"
331 #endif /*WIN32*/
332
333 static Blt_ConfigSpec windowBoxSpecs[] =
334 {
335 {BLT_CONFIG_STRING, "-windowcmd", "windowCmd", "windowCmd",
336 (char *)NULL, Blt_Offset(TreeViewWindowBox, windowCmd),
337 BLT_CONFIG_NULL_OK, 0},
338 {BLT_CONFIG_INT, "-minwidth", "WindowWidth", "WindowWidth",
339 "0", Blt_Offset(TreeViewWindowBox, windowWidth), 0},
340 {BLT_CONFIG_INT, "-minheight", "WindowHeight", "WindowHeight",
341 "0", Blt_Offset(TreeViewWindowBox, windowHeight), 0},
342 {BLT_CONFIG_CUSTOM, "-sticky", "sticky", "Sticky",
343 "w", Tk_Offset(TreeViewWindowBox, sticky),
344 0, &bltStickyOption},
345
346 {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
347 (char *)NULL, 0, 0}
348 };
349
350 typedef struct {
351 TREEVIEW_STYLE_COMMON
352
353 /* Barbox specific fields. */
354 GC bgGC;
355 Tk_3DBorder barBg; /* Normal background color of cell. */ \
356
357 int showValue; /* If non-zero, display the on/off value. */
358 double minValue;
359 double maxValue;
360 int lineWidth; /* Linewidth of the surrounding box. */
361 Tcl_Obj *formatCmd;
362
363 XColor *boxColor; /* Rectangle (box) color (grey). */
364 XColor *fillColor; /* Fill color (white) */
365
366 GC boxGC;
367 GC fillGC; /* Box fill GC */
368
369 int barWidth;
370 int barHeight;
371
372 } TreeViewBarBox;
373
374 #define DEF_BARBOX_BOX_COLOR "black"
375 #define DEF_BARBOX_FILL_COLOR "darkgreen"
376 #define DEF_BARBOX_MINVALUE "0.0"
377 #define DEF_BARBOX_MAXVALUE "100.0"
378 #define DEF_BARBOX_WIDTH "80"
379 #define DEF_BARBOX_HEIGHT "10"
380 #define DEF_BARBOX_SHOWVALUE "yes"
381 #define DEF_BARBOX_LINEWIDTH "1"
382 #define DEF_BARBOX_GAP "4"
383 #ifdef WIN32
384 #define DEF_BARBOX_CURSOR "arrow"
385 #else
386 #define DEF_BARBOX_CURSOR "hand2"
387 #endif /*WIN32*/
388
389 static Blt_ConfigSpec barBoxSpecs[] =
390 {
391 CONF_STYLES
392 {BLT_CONFIG_BORDER, "-barbg", "barBg", "BarBg",
393 (char *)NULL, Blt_Offset(TreeViewBarBox, barBg), BLT_CONFIG_NULL_OK},
394 {BLT_CONFIG_COLOR, "-barfg", "barFg", "BarFg",
395 DEF_BARBOX_FILL_COLOR, Blt_Offset(TreeViewBarBox, fillColor), 0},
396 {BLT_CONFIG_COLOR, "-boxcolor", "boxColor", "BoxColor",
397 DEF_BARBOX_BOX_COLOR, Blt_Offset(TreeViewBarBox, boxColor), 0},
398 {BLT_CONFIG_INT, "-barwidth", "barWidth", "BarWidth",
399 DEF_BARBOX_WIDTH, Blt_Offset(TreeViewBarBox, barWidth), 0},
400 {BLT_CONFIG_INT, "-barheight", "BarHeight", "BarHeight",
401 DEF_BARBOX_HEIGHT, Blt_Offset(TreeViewBarBox, barHeight), 0},
402 {BLT_CONFIG_TILE, "-filltile", "fillTile", "FillTile",
403 (char *)NULL, Tk_Offset(TreeViewBarBox, fillTile), BLT_CONFIG_NULL_OK, },
404 {BLT_CONFIG_OBJCMD, "-formatcmd", "formatCmd", "FormatCmd",
405 NULL, Blt_Offset(TreeViewBarBox, formatCmd),
406 BLT_CONFIG_NULL_OK},
407 {BLT_CONFIG_DISTANCE, "-linewidth", "lineWidth", "LineWidth",
408 DEF_BARBOX_LINEWIDTH,
409 Blt_Offset(TreeViewBarBox, lineWidth),
410 BLT_CONFIG_DONT_SET_DEFAULT},
411 {BLT_CONFIG_DOUBLE, "-maxvalue", "maxValue", "MaxValue",
412 DEF_BARBOX_MAXVALUE, Blt_Offset(TreeViewBarBox, maxValue), 0},
413 {BLT_CONFIG_DOUBLE, "-minvalue", "minValue", "MinValue",
414 DEF_BARBOX_MINVALUE, Blt_Offset(TreeViewBarBox, minValue), 0},
415 {BLT_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
416 DEF_BARBOX_SHOWVALUE, Blt_Offset(TreeViewBarBox, showValue),
417 BLT_CONFIG_DONT_SET_DEFAULT},
418 {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
419 (char *)NULL, 0, 0}
420 };
421
422 typedef union {
423 TreeViewTextBox tb;
424 TreeViewCheckBox cb;
425 TreeViewComboBox cob;
426 TreeViewBarBox bb;
427 TreeViewWindowBox wb;
428 } TreeViewAllStyles;
429
430 typedef TreeViewStyle *(StyleCreateProc) _ANSI_ARGS_((TreeView *tvPtr,
431 Blt_HashEntry *hPtr));
432
433 static StyleConfigProc ConfigureTextBox, ConfigureCheckBox, ConfigureComboBox, ConfigureWindowBox, ConfigureBarBox;
434 static StyleCreateProc CreateTextBox, CreateCheckBox, CreateComboBox, CreateWindowBox, CreateBarBox;
435 static StyleDrawProc DrawTextBox, DrawCheckBox, DrawComboBox, DrawWindowBox, DrawBarBox;
436 static StyleEditProc EditTextBox, EditCheckBox, EditComboBox, EditWindowBox, EditBarBox;
437 static StyleFreeProc FreeTextBox, FreeCheckBox, FreeComboBox, FreeWindowBox, FreeBarBox;
438 static StyleMeasureProc MeasureTextBox, MeasureCheckBox, MeasureComboBox, MeasureWindowBox, MeasureBarBox;
439 static StylePickProc PickComboBox;
440
441
442 static Tcl_Obj *
StickyToObj(clientData,interp,tkwin,widgRec,offset)443 StickyToObj(clientData, interp, tkwin, widgRec, offset)
444 ClientData clientData; /* Not used. */
445 Tcl_Interp *interp;
446 Tk_Window tkwin; /* Not used. */
447 char *widgRec;
448 int offset;
449 {
450 int flags = *(int *)(widgRec + offset);
451
452 int count = 0;
453 char result[10];
454
455 if (flags&STICK_NORTH) result[count++] = 'n';
456 if (flags&STICK_EAST) result[count++] = 'e';
457 if (flags&STICK_SOUTH) result[count++] = 's';
458 if (flags&STICK_WEST) result[count++] = 'w';
459
460 result[count] = '\0';
461 return Tcl_NewStringObj(result, -1);
462 }
463
464 static int
ObjToSticky(clientData,interp,tkwin,objPtr,widgRec,offset)465 ObjToSticky(clientData, interp, tkwin, objPtr, widgRec, offset)
466 ClientData clientData; /* Not used. */
467 Tcl_Interp *interp; /* Interpreter to send results back to */
468 Tk_Window tkwin; /* Not used. */
469 Tcl_Obj *objPtr; /* Tcl_Obj representing the new value. */
470 char *widgRec;
471 int offset;
472 {
473 /* TreeView *tvPtr = clientData; */
474 int *stickyPtr = (int *)(widgRec + offset);
475 int sticky = 0;
476 char c;
477 char *value;
478
479 value = Tcl_GetString(objPtr);
480
481 while ((c = *value++) != '\0') {
482 switch (c) {
483 case 'n': case 'N': sticky |= STICK_NORTH; break;
484 case 'e': case 'E': sticky |= STICK_EAST; break;
485 case 's': case 'S': sticky |= STICK_SOUTH; break;
486 case 'w': case 'W': sticky |= STICK_WEST; break;
487 case ' ': case ',': case '\t': case '\r': case '\n': break;
488 default:
489 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
490 "bad sticky value \"", --value,
491 "\": must contain n, s, e or w",
492 (char *) NULL);
493 return TCL_ERROR;
494 }
495 }
496 *stickyPtr = sticky;
497 return TCL_OK;
498 }
499
500
501 /*
502 *----------------------------------------------------------------------
503 *
504 * ObjToIcon --
505 *
506 * Convert the name of an icon into a Tk image.
507 *
508 * Results:
509 * If the string is successfully converted, TCL_OK is returned.
510 * Otherwise, TCL_ERROR is returned and an error message is left in
511 * interpreter's result field.
512 *
513 *----------------------------------------------------------------------
514 */
515 /*ARGSUSED*/
516 static int
ObjToIcon(clientData,interp,tkwin,objPtr,widgRec,offset)517 ObjToIcon(clientData, interp, tkwin, objPtr, widgRec, offset)
518 ClientData clientData; /* Not used. */
519 Tcl_Interp *interp; /* Interpreter to send results back to */
520 Tk_Window tkwin; /* Not used. */
521 Tcl_Obj *objPtr; /* Tcl_Obj representing the new value. */
522 char *widgRec;
523 int offset;
524 {
525 TreeView *tvPtr = clientData;
526 TreeViewIcon *iconPtr = (TreeViewIcon *)(widgRec + offset);
527 TreeViewIcon icon;
528
529 icon = Blt_TreeViewGetIcon(tvPtr, Tcl_GetString(objPtr));
530 if (icon == NULL) {
531 return TCL_ERROR;
532 }
533 *iconPtr = icon;
534 return TCL_OK;
535 }
536 /*
537 *----------------------------------------------------------------------
538 *
539 * IconToObj --
540 *
541 * Converts the icon into its string representation (its name).
542 *
543 * Results:
544 * The name of the icon is returned.
545 *
546 *----------------------------------------------------------------------
547 */
548 /*ARGSUSED*/
549 static Tcl_Obj *
IconToObj(clientData,interp,tkwin,widgRec,offset)550 IconToObj(clientData, interp, tkwin, widgRec, offset)
551 ClientData clientData; /* Not used. */
552 Tcl_Interp *interp;
553 Tk_Window tkwin; /* Not used. */
554 char *widgRec;
555 int offset;
556 {
557 TreeViewIcon icon = *(TreeViewIcon *)(widgRec + offset);
558
559 return Tcl_NewStringObj(icon?Blt_NameOfImage((icon)->tkImage):"", -1);
560 }
561
562 /*ARGSUSED*/
563 static int
FreeIcon(clientData,display,widgRec,offset,oldPtr)564 FreeIcon(clientData, display, widgRec, offset, oldPtr)
565 ClientData clientData;
566 Display *display; /* Not used. */
567 char *widgRec;
568 int offset;
569 char *oldPtr;
570 {
571 TreeViewIcon icon = (TreeViewIcon)(oldPtr);
572 TreeView *tvPtr = clientData;
573
574 Blt_TreeViewFreeIcon(tvPtr, icon);
575 return TCL_OK;
576 }
577
578 static TreeViewStyleClass textBoxClass = {
579 "TextBoxStyle",
580 textBoxSpecs,
581 ConfigureTextBox,
582 MeasureTextBox,
583 DrawTextBox,
584 NULL,
585 EditTextBox,
586 FreeTextBox,
587 };
588
589 static TreeViewStyleClass checkBoxClass = {
590 "CheckBoxStyle",
591 checkBoxSpecs,
592 ConfigureCheckBox,
593 MeasureCheckBox,
594 DrawCheckBox,
595 NULL,
596 EditCheckBox,
597 FreeCheckBox,
598 };
599
600 static TreeViewStyleClass comboBoxClass = {
601 "ComboBoxStyle",
602 comboBoxSpecs,
603 ConfigureComboBox,
604 MeasureComboBox,
605 DrawComboBox,
606 PickComboBox,
607 EditComboBox,
608 FreeComboBox,
609 };
610
611 static TreeViewStyleClass windowBoxClass = {
612 "WindowBoxStyle",
613 windowBoxSpecs,
614 ConfigureWindowBox,
615 MeasureWindowBox,
616 DrawWindowBox,
617 NULL,
618 EditWindowBox,
619 FreeWindowBox,
620 };
621
622 static TreeViewStyleClass barBoxClass = {
623 "BarBoxStyle",
624 barBoxSpecs,
625 ConfigureBarBox,
626 MeasureBarBox,
627 DrawBarBox,
628 NULL,
629 EditBarBox,
630 FreeBarBox,
631 };
632
Blt_TreeViewStyleIsFmt(TreeView * tvPtr,TreeViewStyle * stylePtr)633 int Blt_TreeViewStyleIsFmt (TreeView *tvPtr,
634 TreeViewStyle *stylePtr)
635 {
636 if (stylePtr->classPtr == &textBoxClass) {
637 TreeViewTextBox *tbPtr;
638 tbPtr = (TreeViewTextBox *)stylePtr;
639 if (tbPtr->formatCmd != NULL && strlen(Tcl_GetString(tbPtr->formatCmd))) {
640 return 1;
641 }
642 return 0;
643 }
644 if (stylePtr->classPtr == &barBoxClass) {
645 TreeViewBarBox *bbPtr;
646 bbPtr = (TreeViewBarBox *)stylePtr;
647 if (bbPtr->formatCmd != NULL && strlen(Tcl_GetString(bbPtr->formatCmd))) {
648 return 1;
649 }
650 return 0;
651 }
652 return 0;
653 }
654
655 /* Allocate a new style. */
newStyle(TreeView * tvPtr,Blt_HashEntry * hPtr,int size)656 static TreeViewStyle *newStyle(TreeView *tvPtr, Blt_HashEntry *hPtr, int size) {
657 TreeViewStyle *stylePtr;
658 stylePtr = Blt_Calloc(1, sizeof(TreeViewAllStyles));
659 /*stylePtr = Blt_Calloc(1, size); */
660 assert(stylePtr);
661 stylePtr->gap = STYLE_GAP;
662 stylePtr->name = Blt_Strdup(Blt_GetHashKey(&tvPtr->styleTable, hPtr));
663 stylePtr->hashPtr = hPtr;
664 stylePtr->refCount = 1;
665 Blt_SetHashValue(hPtr, stylePtr);
666 return stylePtr;
667 }
668 /*
669 *----------------------------------------------------------------------
670 *
671 * CreateTextBox --
672 *
673 * Creates a "textbox" style.
674 *
675 * Results:
676 * A pointer to the new style structure.
677 *
678 *----------------------------------------------------------------------
679 */
680 static TreeViewStyle *
CreateTextBox(tvPtr,hPtr)681 CreateTextBox(tvPtr, hPtr)
682 TreeView *tvPtr;
683 Blt_HashEntry *hPtr;
684 {
685 TreeViewTextBox *tbPtr;
686
687 tbPtr = (TreeViewTextBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewTextBox));
688 tbPtr->classPtr = &textBoxClass;
689 tbPtr->iconside = SIDE_LEFT;
690 tbPtr->side = SIDE_TOP;
691 tbPtr->flags = STYLE_TEXTBOX;
692 return (TreeViewStyle *)tbPtr;
693 }
694
695 /*
696 *----------------------------------------------------------------------
697 *
698 * ConfigureTextBox --
699 *
700 * Configures a "textbox" style. This routine performs
701 * generates the GCs required for a textbox style.
702 *
703 * Results:
704 * None.
705 *
706 * Side Effects:
707 * GCs are created for the style.
708 *
709 *----------------------------------------------------------------------
710 */
711 static void
ConfigureTextBox(tvPtr,stylePtr)712 ConfigureTextBox(tvPtr, stylePtr)
713 TreeView *tvPtr;
714 TreeViewStyle *stylePtr;
715 {
716 GC newGC;
717 XColor *bgColor;
718 XGCValues gcValues;
719 unsigned long gcMask;
720
721 gcMask = GCForeground | GCBackground | GCFont;
722 gcValues.font = Tk_FontId(CHOOSE(tvPtr->font, stylePtr->font));
723 bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, stylePtr->border));
724
725 gcValues.background = bgColor->pixel;
726 gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
727 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
728 if (stylePtr->gc != NULL) {
729 Tk_FreeGC(tvPtr->display, stylePtr->gc);
730 }
731 stylePtr->gc = newGC;
732 if (stylePtr->highlightBorder) {
733 gcValues.background = Tk_3DBorderColor(stylePtr->highlightBorder)->pixel;
734 } else {
735 gcValues.background = bgColor->pixel;
736 }
737 if (stylePtr->highlightFgColor) {
738 gcValues.foreground = stylePtr->highlightFgColor->pixel;
739 } else {
740 gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
741 }
742 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
743 if (stylePtr->highlightGC != NULL) {
744 Tk_FreeGC(tvPtr->display, stylePtr->highlightGC);
745 }
746 stylePtr->highlightGC = newGC;
747
748 if (stylePtr->activeBorder) {
749 gcValues.background = Tk_3DBorderColor(stylePtr->activeBorder)->pixel;
750 } else {
751 gcValues.background = bgColor->pixel;
752 }
753 if (stylePtr->activeFgColor) {
754 gcValues.foreground = stylePtr->activeFgColor->pixel;
755 } else {
756 gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
757 }
758 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
759 if (stylePtr->activeGC != NULL) {
760 Tk_FreeGC(tvPtr->display, stylePtr->activeGC);
761 }
762 stylePtr->activeGC = newGC;
763 stylePtr->flags |= STYLE_DIRTY;
764 }
765
766 /*
767 *----------------------------------------------------------------------
768 *
769 * MeasureTextBox --
770 *
771 * Determines the space requirements for the "textbox" given
772 * the value to be displayed. Depending upon whether an icon
773 * or text is displayed and their relative placements, this
774 * routine computes the space needed for the text entry.
775 *
776 * Results:
777 * None.
778 *
779 * Side Effects:
780 * The width and height fields of *valuePtr* are set with the
781 * computed dimensions.
782 *
783 *----------------------------------------------------------------------
784 */
785 static void
MeasureTextBox(tvPtr,stylePtr,valuePtr)786 MeasureTextBox(tvPtr, stylePtr, valuePtr)
787 TreeView *tvPtr;
788 TreeViewStyle *stylePtr;
789 TreeViewValue *valuePtr;
790 {
791 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
792 TreeViewColumn *columnPtr = valuePtr->columnPtr;
793 int iconWidth, iconHeight;
794 int textWidth, textHeight;
795 int gap;
796 TreeViewIcon icon;
797 int rel = 0;
798
799 textWidth = textHeight = 0;
800 iconWidth = iconHeight = 0;
801 valuePtr->width = valuePtr->height = 0;
802 icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
803 if (icon != NULL && tvPtr->hideStyleIcons == 0) {
804 iconWidth = TreeViewIconWidth(icon);
805 iconHeight = TreeViewIconHeight(icon);
806 }
807 if (valuePtr->textPtr != NULL) {
808 Blt_Free(valuePtr->textPtr);
809 valuePtr->textPtr = NULL;
810 }
811 #define NotNullObj(p) ((p != NULL && strlen(Tcl_GetString(p))) ? p : NULL)
812
813 if (valuePtr->string != NULL) {
814 /* New string defined. */
815 TextStyle ts;
816 Tcl_Obj *fmtObj;
817
818 fmtObj = NotNullObj(tbPtr->formatCmd);
819 if (fmtObj == NULL) {
820 fmtObj = NotNullObj(columnPtr->formatCmd);
821 }
822 if (fmtObj == NULL) {
823 fmtObj = NotNullObj(tvPtr->formatCmd);
824 }
825
826 Blt_InitTextStyle(&ts);
827 ts.font = CHOOSE3(tvPtr->font, columnPtr->font , stylePtr->font);
828 ts.anchor = TK_ANCHOR_NW;
829 ts.justify = columnPtr->justify;
830 if (fmtObj != NULL) {
831 Tcl_DString cmdString;
832 char *string;
833 int result;
834 Tcl_Interp *interp = tvPtr->interp;
835
836 Tcl_Preserve(valuePtr->entryPtr);
837 rel = 1;
838 Blt_TreeViewPercentSubst(tvPtr, valuePtr->entryPtr, columnPtr, Tcl_GetString(fmtObj), valuePtr->string, &cmdString);
839 result = Tcl_GlobalEval(interp, Tcl_DStringValue(&cmdString));
840 Blt_TreeViewOptsInit(tvPtr);
841 Tcl_DStringFree(&cmdString);
842 if (result == TCL_OK) {
843 string = Tcl_GetStringResult(interp);
844 valuePtr->textPtr = Blt_GetTextLayoutStr(string, &ts);
845 }
846 }
847 if (valuePtr->textPtr == NULL) {
848 valuePtr->textPtr = Blt_GetTextLayoutStr(valuePtr->string, &ts);
849 }
850 }
851 gap = 0;
852 if (valuePtr->textPtr != NULL && tvPtr->hideStyleText == 0) {
853 textWidth = valuePtr->textPtr->width;
854 textHeight = valuePtr->textPtr->height;
855 if (stylePtr->icon != NULL) {
856 gap = stylePtr->gap;
857 }
858 }
859 if (SIDE_VERTICAL(tbPtr->iconside)) {
860 valuePtr->height = iconHeight + gap + textHeight;
861 valuePtr->width = MAX(textWidth, iconWidth);
862 } else {
863 valuePtr->width = iconWidth + gap + textWidth;
864 valuePtr->height = MAX(textHeight, iconHeight);
865 }
866 if (rel) {
867 Tcl_Release(valuePtr->entryPtr);
868 }
869 }
870
871 /*
872 * Fill in the bg, fg, font from styles from value, entry, column and tvjj. */
873 static void
GetPriorityStyle(TreeView * tvPtr,TreeViewEntry * entryPtr,TreeViewValue * valuePtr,TreeViewStyle * inStylePtr,TreeViewStyle * stylePtr)874 GetPriorityStyle(
875 TreeView *tvPtr,
876 TreeViewEntry *entryPtr,
877 TreeViewValue *valuePtr,
878 TreeViewStyle *inStylePtr,
879 TreeViewStyle *stylePtr
880 ) {
881 TreeViewStyle *s[4];
882 int i = -1, bgprio = -1, fgprio = -1, fntprio = -1;
883 int disabled = (entryPtr->state == STATE_DISABLED);
884
885 s[0] = valuePtr?valuePtr->stylePtr:NULL;
886 s[1] = entryPtr?entryPtr->stylePtr:NULL;
887 s[2] = valuePtr?valuePtr->columnPtr->stylePtr:NULL;
888 s[3] = tvPtr->stylePtr;
889 /*stylePtr->font = CHOOSE3(tvPtr->font, inStylePtr->font, entryPtr->font); */
890 stylePtr->font = tvPtr->font;
891 if (valuePtr != NULL && valuePtr->columnPtr->font) {
892 stylePtr->font = valuePtr->columnPtr->font;
893 stylePtr->gc = valuePtr->columnPtr->textGC;
894 } else if (inStylePtr->font) {
895 stylePtr->font = inStylePtr->font;
896 stylePtr->gc = stylePtr->gc;
897 }
898 stylePtr->border = CHOOSE3(tvPtr->border, inStylePtr->border, entryPtr->border);
899 if (disabled) {
900 stylePtr->fgColor = tvPtr->disabledColor;
901 } else if (valuePtr != NULL) {
902 stylePtr->fgColor = CHOOSE4(tvPtr->fgColor, valuePtr->columnPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
903 } else {
904 stylePtr->fgColor = CHOOSE3(tvPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
905 }
906 while (++i<4) {
907 if (s[i]) {
908 if (s[i]->border && (s[i]->priority>bgprio||stylePtr->border==NULL)) {
909 stylePtr->border = s[i]->border;
910 bgprio = s[i]->priority;
911 }
912 if (disabled == 0 && s[i]->fgColor && (s[i]->priority>fgprio||stylePtr->fgColor==NULL)) {
913 stylePtr->fgColor = s[i]->fgColor;
914 fgprio = s[i]->priority;
915 }
916 if (s[i]->font && (s[i]->priority>fntprio||stylePtr->font==NULL)) {
917 stylePtr->font = s[i]->font;
918 stylePtr->gc = s[i]->gc;
919 fntprio = s[i]->priority;
920 }
921 }
922 }
923 }
924
925 /* Fill in stylePtr with font, border, fgColor, etc. UNUSED */
926 void
Blt_GetPriorityStyle(TreeViewStyle * stylePtr,TreeView * tvPtr,TreeViewColumn * columnPtr,TreeViewEntry * entryPtr,TreeViewValue * valuePtr,TreeViewStyle * inStylePtr,int flags)927 Blt_GetPriorityStyle(
928 TreeViewStyle *stylePtr, /* Style to fillin. */
929 TreeView *tvPtr,
930 TreeViewColumn *columnPtr,
931 TreeViewEntry *entryPtr,
932 TreeViewValue *valuePtr,
933 TreeViewStyle *inStylePtr,
934 int flags
935 ) {
936 TreeViewStyle *s[20];
937 int n = 0, i = -1;
938 int bgprio = -1, fgprio = -1, fntprio = -1, shadprio = -1, tileprio = -1;
939 int iconprio = -1;
940 int disabled = (entryPtr->state == STATE_DISABLED);
941
942 if ((flags&STYLEFLAG_NOCLEAR) == 0) {
943 memset(stylePtr, 0, sizeof(*stylePtr));
944 }
945 /* Is a sub label */
946 if ((flags&STYLEFLAG_SUBSTYLE) && tvPtr->subStylePtr) {
947 s[n++] = tvPtr->subStylePtr;
948 }
949 /* Is an empty value. */
950 if ((flags&STYLEFLAG_EMPTYSTYLE) && tvPtr->emptyStylePtr) {
951 s[n++] = tvPtr->emptyStylePtr;
952 }
953 /* Is an alt row. */
954 if ((flags&STYLEFLAG_ALTSTYLE) && tvPtr->altStylePtr) {
955 s[n++] = tvPtr->altStylePtr;
956 }
957 /* Is a title. */
958 if ((flags&STYLEFLAG_TITLESTYLE) && columnPtr && columnPtr->titleStylePtr) {
959 s[n++] = columnPtr->titleStylePtr;
960 }
961 if (inStylePtr) s[n++] = inStylePtr;
962 if (valuePtr && valuePtr->stylePtr) s[n++] = valuePtr->stylePtr;
963 if (entryPtr && entryPtr->stylePtr) s[n++] = entryPtr->stylePtr;
964 if (columnPtr && columnPtr->stylePtr) s[n++] = columnPtr->stylePtr;
965 if (tvPtr->stylePtr) s[n++] = tvPtr->stylePtr;
966 if (inStylePtr == NULL) inStylePtr = tvPtr->stylePtr;
967 /*stylePtr->font = CHOOSE(tvPtr->font, entryPtr->font); */
968 /*stylePtr->font = tvPtr->font;
969 stylePtr->border = tvPtr->border;
970 stylePtr->fgColor = tvPtr->fgColor;
971 stylePtr->shadow.color = NULL;
972 stylePtr->tile = NULL;
973 stylePtr->icon = NULL;*/
974 stylePtr->gc = (entryPtr?entryPtr->gc:NULL);
975 /* stylePtr->font = tvPtr->font; */
976 if (valuePtr != NULL && valuePtr->columnPtr->font) {
977 stylePtr->font = valuePtr->columnPtr->font;
978 stylePtr->gc = valuePtr->columnPtr->textGC;
979 } else if (inStylePtr->font) {
980 stylePtr->font = inStylePtr->font;
981 stylePtr->gc = stylePtr->gc;
982 } else if (columnPtr && columnPtr->font) {
983 stylePtr->font = columnPtr->font;
984 stylePtr->gc = columnPtr->textGC;
985 }
986 stylePtr->border = CHOOSE3(tvPtr->border, inStylePtr->border, entryPtr->border);
987 if (disabled) {
988 stylePtr->fgColor = tvPtr->disabledColor;
989 } else if (valuePtr != NULL) {
990 stylePtr->fgColor = CHOOSE4(tvPtr->fgColor, valuePtr->columnPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
991 } else {
992 stylePtr->fgColor = CHOOSE3(tvPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
993 }
994 i = -1;
995 while (++i<n) {
996 if (s[i]->border && (s[i]->priority>bgprio||stylePtr->border==NULL)) {
997 stylePtr->border = s[i]->border;
998 bgprio = s[i]->priority;
999 }
1000 if (disabled == 0 && s[i]->fgColor && (s[i]->priority>fgprio||stylePtr->fgColor==NULL)) {
1001 stylePtr->fgColor = s[i]->fgColor;
1002 fgprio = s[i]->priority;
1003 }
1004 if (s[i]->font && (s[i]->priority>fntprio||stylePtr->font==NULL)) {
1005 stylePtr->font = s[i]->font;
1006 fntprio = s[i]->priority;
1007 stylePtr->gc = s[i]->gc;
1008 }
1009 if (s[i]->shadow.color && (s[i]->priority>shadprio||stylePtr->shadow.color==NULL)) {
1010 stylePtr->shadow = s[i]->shadow;
1011 shadprio = s[i]->priority;
1012 }
1013 if (s[i]->icon && (s[i]->priority>iconprio||stylePtr->icon==NULL)) {
1014 stylePtr->icon = s[i]->icon;
1015 iconprio = s[i]->priority;
1016 }
1017 if (s[i]->tile && (s[i]->priority>tileprio||stylePtr->tile==NULL)) {
1018 stylePtr->tile = s[i]->tile;
1019 tileprio = s[i]->priority;
1020 }
1021 }
1022 if (entryPtr == NULL) {
1023 if (stylePtr->font==NULL) stylePtr->font = tvPtr->font;
1024 if (stylePtr->border==NULL) stylePtr->border = tvPtr->border;
1025 if (stylePtr->fgColor==NULL) stylePtr->fgColor = tvPtr->fgColor;
1026 } else {
1027 if (stylePtr->font==NULL) stylePtr->font = CHOOSE3(tvPtr->font,(columnPtr?columnPtr->font:NULL),entryPtr->font);
1028 if (stylePtr->border==NULL) stylePtr->border = CHOOSE(tvPtr->border,entryPtr->border);
1029 if (stylePtr->fgColor==NULL) stylePtr->fgColor = CHOOSE(tvPtr->fgColor,entryPtr->color);
1030 if (stylePtr->shadow.color==NULL) stylePtr->shadow = entryPtr->shadow;
1031 }
1032 if (stylePtr->tile==NULL) stylePtr->tile = tvPtr->tile;
1033 }
1034
1035 #define IFSET(var,val) var = (val?val:var)
1036
1037 /* Fill background. */
1038 /* TODO: return GC for element/style that sets the font!!!! */
1039 /* TODO: lookup font from style for Measure routines. */
1040 void
drawTextBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y,sRec)1041 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, sRec)
1042 TreeView *tvPtr;
1043 Drawable drawable;
1044 TreeViewEntry *entryPtr;
1045 TreeViewValue *valuePtr;
1046 TreeViewStyle *stylePtr;
1047 TreeViewIcon icon;
1048 int x, y;
1049 TreeViewStyle *sRec;
1050 {
1051 TreeViewColumn *columnPtr;
1052 int altRow = (entryPtr->flags&ENTRY_ALTROW);
1053
1054 columnPtr = valuePtr->columnPtr;
1055 sRec->font = CHOOSE(tvPtr->font, columnPtr->font);
1056 sRec->fgColor = CHOOSE(tvPtr->fgColor, columnPtr->fgColor);
1057 sRec->border = tvPtr->border;
1058 sRec->gc = tvPtr->stylePtr->gc;
1059 GetPriorityStyle(tvPtr, entryPtr, valuePtr, stylePtr, sRec);
1060 /* TODO: fix font/gc bug where altStyle has tile and bg */
1061 if ((tvPtr->activeColumnPtr == valuePtr->columnPtr && tvPtr->actCol) ||
1062 (valuePtr == tvPtr->activeValuePtr) ||
1063 (tvPtr->activeButtonPtr == entryPtr && tvPtr->actEntry) ||
1064 (stylePtr->flags & STYLE_HIGHLIGHT)) {
1065 IFSET(sRec->border, stylePtr->highlightBorder);
1066 IFSET(sRec->fgColor, stylePtr->highlightFgColor);
1067 } else if (valuePtr->stylePtr && valuePtr->stylePtr->border) {
1068 sRec->border = valuePtr->stylePtr->border;
1069 } else if (columnPtr->hasbg) {
1070 sRec->border = columnPtr->border;
1071 /*((tvPtr->tile != NULL || columnPtr->tile != NULL) && stylePtr->tile==NULL)*/
1072 } else if ((Blt_HasTile(tvPtr->tile) || Blt_HasTile(columnPtr->tile)) && Blt_HasTile(stylePtr->tile)==0) {
1073 sRec->border = NULL;
1074 } else if (altRow && tvPtr->altStylePtr && Blt_HasTile(tvPtr->altStylePtr->tile)) {
1075 stylePtr = tvPtr->altStylePtr;
1076 }
1077 if (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
1078 /*
1079 * Draw the active or normal background color over the entire
1080 * label area. This includes both the tab's text and image.
1081 * The rectangle should be 2 pixels wider/taller than this
1082 * area. So if the label consists of just an image, we get an
1083 * halo around the image when the tab is active.
1084 */
1085 if (sRec->border != NULL && (altRow==0 ||
1086 (altRow && stylePtr->tile && stylePtr == tvPtr->altStylePtr))) {
1087 Blt_TreeViewFill3DTile(tvPtr, drawable, sRec->border,
1088 x - columnPtr->pad.side1, y - tvPtr->leader/2,
1089 columnPtr->width, entryPtr->height,
1090 0, TK_RELIEF_FLAT, entryPtr->gc?NULL:stylePtr->tile, tvPtr->scrollTile, 1);
1091 }
1092 }
1093 }
1094
1095 /*
1096 * Set fg color based on string pattern match
1097 */
1098 static void
GetColorPats(tvPtr,entryPtr,valuePtr,stylePtr,fgPtr)1099 GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, fgPtr)
1100 TreeView *tvPtr;
1101 TreeViewEntry *entryPtr;
1102 TreeViewValue *valuePtr;
1103 TreeViewStyle *stylePtr;
1104 XColor **fgPtr;
1105 {
1106 XColor *color = NULL;
1107 Tcl_Interp *interp = tvPtr->interp;
1108 int objc, i;
1109 Tcl_Obj **objv, *objPtr = NULL;
1110 TreeViewColumn *columnPtr = valuePtr->columnPtr;
1111
1112 if (columnPtr->colorPats != NULL && strlen(Tcl_GetString(columnPtr->colorPats))) {
1113 if (Tcl_ListObjGetElements(NULL, columnPtr->colorPats, &objc, &objv) != TCL_OK) return;
1114 if (objc%2) return;
1115 for (i = 0; i < objc; i += 2) {
1116 if (Tcl_StringMatch(valuePtr->string, Tcl_GetString(objv[i]))) {
1117 color = Tk_AllocColorFromObj(interp, tvPtr->tkwin, objv[i+1]);
1118 if (color != NULL) {
1119 *fgPtr = color;
1120 return;
1121 }
1122 }
1123 }
1124 }
1125 if (columnPtr->colorRegex != NULL && strlen(Tcl_GetString(columnPtr->colorRegex))) {
1126 if (Tcl_ListObjGetElements(NULL, columnPtr->colorRegex, &objc, &objv) != TCL_OK) return;
1127 if (objc%2) return;
1128 for (i = 0; i < objc; i += 2) {
1129 if (objPtr == NULL) {
1130 objPtr = Tcl_NewStringObj(valuePtr->string,-1);
1131 Tcl_IncrRefCount(objPtr);
1132 }
1133 if (Tcl_RegExpMatchObj(NULL, objPtr, objv[i]) == 1) {
1134 color = Tk_AllocColorFromObj(interp, tvPtr->tkwin, objv[i+1]);
1135 if (color != NULL) {
1136 *fgPtr = color;
1137 break;
1138 }
1139 }
1140 }
1141 if (objPtr != NULL) {
1142 Tcl_DecrRefCount(objPtr);
1143 }
1144 }
1145 }
1146
1147 /*
1148 *----------------------------------------------------------------------
1149 *
1150 * DrawTextBox --
1151 *
1152 * Draws the "textbox" given the screen coordinates and the
1153 * value to be displayed.
1154 *
1155 * Results:
1156 * None.
1157 *
1158 * Side Effects:
1159 * The textbox value is drawn.
1160 *
1161 *----------------------------------------------------------------------
1162 */
1163 static void
DrawTextBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)1164 DrawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
1165 TreeView *tvPtr;
1166 Drawable drawable;
1167 TreeViewEntry *entryPtr;
1168 TreeViewValue *valuePtr;
1169 TreeViewStyle *stylePtr;
1170 TreeViewIcon icon;
1171 int x, y;
1172 {
1173 GC gc;
1174 TreeViewColumn *columnPtr;
1175 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
1176 int iconX, iconY, iconWidth, iconHeight;
1177 int textX, textY, textWidth, textHeight;
1178 int gap, columnWidth, ix = x;
1179 TreeViewStyle sRec = *stylePtr;
1180 int valWidth;
1181 TextLayout *layPtr;
1182
1183 layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
1184 columnPtr = valuePtr->columnPtr;
1185 valWidth = (layPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
1186 if (!stylePtr) return;
1187 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
1188 gc = sRec.gc;
1189 columnWidth = columnPtr->width -
1190 (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
1191
1192 textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */
1193
1194 iconWidth = iconHeight = 0;
1195 if (icon != NULL) {
1196 iconWidth = TreeViewIconWidth(icon);
1197 iconHeight = TreeViewIconHeight(icon);
1198 }
1199 textWidth = textHeight = 0;
1200 if (layPtr != NULL) {
1201 textWidth = layPtr->width;
1202 textHeight = layPtr->height;
1203 }
1204 gap = 0;
1205 if ((icon != NULL) && (layPtr != NULL)) {
1206 gap = stylePtr->gap;
1207 }
1208 if (columnWidth >= valWidth) {
1209 switch(columnPtr->justify) {
1210 case TK_JUSTIFY_RIGHT:
1211 ix = x + columnWidth - iconWidth;
1212 x += (columnWidth - valWidth);
1213 break;
1214 case TK_JUSTIFY_CENTER:
1215 ix = x + (columnWidth - iconWidth)/2;
1216 x += (columnWidth - valWidth) / 2;
1217 break;
1218 case TK_JUSTIFY_LEFT:
1219 break;
1220 }
1221 }
1222
1223 switch (tbPtr->iconside) {
1224 case SIDE_RIGHT:
1225 textX = x;
1226 textY = y + (entryPtr->height - textHeight) / 2;
1227 iconX = textX + textWidth + gap;
1228 iconY = y + (entryPtr->height - iconHeight) / 2;
1229 break;
1230 case SIDE_LEFT:
1231 iconX = x;
1232 iconY = y + (entryPtr->height - iconHeight) / 2;
1233 textX = iconX + iconWidth + gap;
1234 textY = y + (entryPtr->height - textHeight) / 2;
1235 break;
1236 case SIDE_TOP:
1237 iconY = y;
1238 if (tbPtr->side == SIDE_BOTTOM) {
1239 iconY = y + (entryPtr->height - textHeight - iconHeight - gap*2);
1240 }
1241 iconX = ix;
1242 textY = iconY + iconHeight + gap;
1243 textX = x;
1244 if (iconWidth>textWidth) {
1245 textX = x + (iconWidth-textWidth)/2;
1246 }
1247 break;
1248 case SIDE_BOTTOM:
1249 textX = x;
1250 textY = y;
1251 if (tbPtr->side == SIDE_BOTTOM) {
1252 textY = y + (entryPtr->height - textHeight - iconHeight - gap*2);
1253 }
1254 if (iconWidth>textWidth) {
1255 textX = x + (iconWidth-textWidth)/2;
1256 }
1257 iconY = textY + textHeight + gap;
1258 iconX = ix;
1259 break;
1260 }
1261 valuePtr->iX = iconX;
1262 valuePtr->iY = iconY;
1263 valuePtr->iW = iconWidth;
1264 valuePtr->iH = iconHeight;
1265 valuePtr->tX = textX;
1266 valuePtr->tY = textY;
1267 valuePtr->tW = textWidth;
1268 valuePtr->tH = textHeight;
1269 if (icon != NULL) {
1270 if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth,
1271 iconHeight, drawable, iconX, iconY) != TCL_OK) return;
1272 }
1273 if (layPtr != NULL) {
1274 TextStyle ts;
1275 XColor *color;
1276 int disabled = (entryPtr->state == STATE_DISABLED);
1277
1278 if (disabled) {
1279 color = tvPtr->disabledColor;
1280 } else if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
1281 color = SELECT_FG(tvPtr);
1282 } else if (entryPtr->color != NULL) {
1283 color = entryPtr->color;
1284 } else {
1285 color = sRec.fgColor;
1286 GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
1287 }
1288 XSetForeground(tvPtr->display, gc, color->pixel);
1289 Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor,
1290 stylePtr->shadow.color, 0.0,
1291 TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
1292 Blt_DrawTextLayout(tvPtr->tkwin, drawable, layPtr,
1293 &ts, textX, textY);
1294 if (color != sRec.fgColor) {
1295 XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
1296 }
1297 } else {
1298 valuePtr->tW = 0;
1299 }
1300 stylePtr->flags &= ~STYLE_DIRTY;
1301 }
1302
1303 /*
1304 *----------------------------------------------------------------------
1305 *
1306 * EditTextbox --
1307 *
1308 * Edits the "textbox".
1309 *
1310 * Results:
1311 * None.
1312 *
1313 * Side Effects:
1314 * The checkbox value is drawn.
1315 *
1316 *----------------------------------------------------------------------
1317 */
1318 /*ARGSUSED*/
1319 static int
EditTextBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)1320 EditTextBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
1321 TreeView *tvPtr;
1322 TreeViewEntry *entryPtr;
1323 TreeViewValue *valuePtr;
1324 TreeViewStyle *stylePtr; /* Not used. */
1325 int x;
1326 int y;
1327 int *retVal;
1328 {
1329 int isTest = *retVal;
1330 *retVal = 0;
1331 if (isTest) {
1332 return TCL_OK;
1333 }
1334 return Blt_TreeViewTextbox(tvPtr, entryPtr, valuePtr->columnPtr);
1335 }
1336
1337
1338 /*
1339 *----------------------------------------------------------------------
1340 *
1341 * FreeTextBox --
1342 *
1343 * Releases resources allocated for the textbox. The resources
1344 * freed by this routine are specific only to the "textbox".
1345 * Other resources (common to all styles) are freed in the
1346 * Blt_TreeViewFreeStyle routine.
1347 *
1348 * Results:
1349 * None.
1350 *
1351 * Side Effects:
1352 * GCs allocated for the textbox are freed.
1353 *
1354 *----------------------------------------------------------------------
1355 */
1356 static void
FreeTextBox(tvPtr,stylePtr)1357 FreeTextBox(tvPtr, stylePtr)
1358 TreeView *tvPtr;
1359 TreeViewStyle *stylePtr;
1360 {
1361 if (!stylePtr) return;
1362 if (stylePtr->highlightGC != NULL) {
1363 Tk_FreeGC(tvPtr->display, stylePtr->highlightGC);
1364 }
1365 if (stylePtr->activeGC != NULL) {
1366 Tk_FreeGC(tvPtr->display, stylePtr->activeGC);
1367 }
1368 if (stylePtr->gc != NULL) {
1369 Tk_FreeGC(tvPtr->display, stylePtr->gc);
1370 }
1371 if (stylePtr->icon != NULL) {
1372 Blt_TreeViewFreeIcon(tvPtr, stylePtr->icon);
1373 }
1374
1375 }
1376
1377
1378 /*
1379 *----------------------------------------------------------------------
1380 *
1381 * CreateCheckbox --
1382 *
1383 * Creates a "checkbox" style.
1384 *
1385 * Results:
1386 * A pointer to the new style structure.
1387 *
1388 *----------------------------------------------------------------------
1389 */
1390 static TreeViewStyle *
CreateCheckBox(tvPtr,hPtr)1391 CreateCheckBox(tvPtr, hPtr)
1392 TreeView *tvPtr;
1393 Blt_HashEntry *hPtr;
1394 {
1395 TreeViewCheckBox *cbPtr;
1396
1397 cbPtr = (TreeViewCheckBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewCheckBox));
1398 cbPtr->classPtr = &checkBoxClass;
1399 cbPtr->gap = 4;
1400 cbPtr->size = 11;
1401 cbPtr->lineWidth = 1;
1402 cbPtr->showValue = TRUE;
1403 cbPtr->flags = STYLE_CHECKBOX;
1404 return (TreeViewStyle *)cbPtr;
1405 }
1406
1407 /*
1408 *----------------------------------------------------------------------
1409 *
1410 * ConfigureCheckbox --
1411 *
1412 * Configures a "checkbox" style. This routine performs
1413 * generates the GCs required for a checkbox style.
1414 *
1415 * Results:
1416 * None.
1417 *
1418 * Side Effects:
1419 * GCs are created for the style.
1420 *
1421 *----------------------------------------------------------------------
1422 */
1423 static void
ConfigureCheckBox(tvPtr,stylePtr)1424 ConfigureCheckBox(tvPtr, stylePtr)
1425 TreeView *tvPtr;
1426 TreeViewStyle *stylePtr;
1427 {
1428 GC newGC;
1429 TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1430 XColor *bgColor;
1431 XGCValues gcValues;
1432 unsigned long gcMask;
1433
1434 bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, stylePtr->border));
1435
1436 gcValues.background = bgColor->pixel;
1437 gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
1438 ConfigureTextBox(tvPtr, stylePtr);
1439 gcMask = GCForeground;
1440 gcValues.foreground = cbPtr->fillColor->pixel;
1441 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1442 if (cbPtr->fillGC != NULL) {
1443 Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
1444 }
1445 cbPtr->fillGC = newGC;
1446
1447 gcMask = GCForeground | GCLineWidth;
1448 gcValues.line_width = cbPtr->lineWidth;
1449 gcValues.foreground = cbPtr->boxColor->pixel;
1450 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1451 if (cbPtr->boxGC != NULL) {
1452 Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
1453 }
1454 cbPtr->boxGC = newGC;
1455
1456 gcMask = GCForeground | GCLineWidth;
1457 gcValues.line_width = 1;
1458 gcValues.foreground = cbPtr->checkColor->pixel;
1459 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1460 if (cbPtr->checkGC != NULL) {
1461 Tk_FreeGC(tvPtr->display, cbPtr->checkGC);
1462 }
1463 cbPtr->checkGC = newGC;
1464 if (cbPtr->checkBg) {
1465 bgColor = Tk_3DBorderColor(cbPtr->checkBg);
1466 gcValues.background = bgColor->pixel;
1467 gcValues.foreground = bgColor->pixel;
1468 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1469 if (cbPtr->bgGC != NULL) {
1470 Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
1471 }
1472 cbPtr->bgGC = newGC;
1473 }
1474 stylePtr->flags |= STYLE_DIRTY;
1475 }
1476
1477 /*
1478 *----------------------------------------------------------------------
1479 *
1480 * MeasureCheckbox --
1481 *
1482 * Determines the space requirements for the "checkbox" given
1483 * the value to be displayed. Depending upon whether an icon
1484 * or text is displayed and their relative placements, this
1485 * routine computes the space needed for the text entry.
1486 *
1487 * Results:
1488 * None.
1489 *
1490 * Side Effects:
1491 * The width and height fields of *valuePtr* are set with the
1492 * computed dimensions.
1493 *
1494 *----------------------------------------------------------------------
1495 */
1496 static void
MeasureCheckBox(tvPtr,stylePtr,valuePtr)1497 MeasureCheckBox(tvPtr, stylePtr, valuePtr)
1498 TreeView *tvPtr;
1499 TreeViewStyle *stylePtr;
1500 TreeViewValue *valuePtr;
1501 {
1502 TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1503 TreeViewColumn *columnPtr = valuePtr->columnPtr;
1504 int iconWidth, iconHeight;
1505 int textWidth, textHeight;
1506 int gap;
1507 int boxWidth, boxHeight;
1508 TreeViewIcon icon;
1509
1510 boxWidth = boxHeight = ODD(cbPtr->size);
1511
1512 if (cbPtr->icons) {
1513 TreeViewIcon mIcon;
1514 int i;
1515
1516 for (i=0; i<2; i++) {
1517 mIcon = cbPtr->icons[i];
1518 if (mIcon) {
1519 int mwid = TreeViewIconWidth(mIcon);
1520 int mhig = TreeViewIconHeight(mIcon);
1521 if (mwid>boxWidth) { boxWidth = mwid; }
1522 if (mhig>boxHeight) { boxHeight = mhig; }
1523 }
1524 }
1525 }
1526 textWidth = textHeight = iconWidth = iconHeight = 0;
1527 valuePtr->width = valuePtr->height = 0;
1528 icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
1529 if (icon != NULL && tvPtr->hideStyleIcons == 0) {
1530 iconWidth = TreeViewIconWidth(icon);
1531 iconHeight = TreeViewIconHeight(icon);
1532 }
1533 if (cbPtr->onPtr != NULL) {
1534 Blt_Free(cbPtr->onPtr);
1535 cbPtr->onPtr = NULL;
1536 }
1537 if (cbPtr->offPtr != NULL) {
1538 Blt_Free(cbPtr->offPtr);
1539 cbPtr->offPtr = NULL;
1540 }
1541 gap = 0;
1542 if (cbPtr->showValue && tvPtr->hideStyleText == 0) {
1543 TextStyle ts;
1544 char *string;
1545
1546 Blt_InitTextStyle(&ts);
1547 ts.font = CHOOSE3(tvPtr->font, columnPtr->font, stylePtr->font);
1548 ts.anchor = TK_ANCHOR_NW;
1549 ts.justify = columnPtr->justify;
1550 string = (cbPtr->onValue != NULL) ? cbPtr->onValue : valuePtr->string;
1551 cbPtr->onPtr = Blt_GetTextLayout(string, &ts);
1552 string = (cbPtr->offValue != NULL) ? cbPtr->offValue : valuePtr->string;
1553 cbPtr->offPtr = Blt_GetTextLayout(string, &ts);
1554 textWidth = MAX(cbPtr->offPtr->width, cbPtr->onPtr->width);
1555 textHeight = MAX(cbPtr->offPtr->height, cbPtr->onPtr->height);
1556 if (stylePtr->icon != NULL) {
1557 gap = stylePtr->gap;
1558 }
1559 }
1560 valuePtr->width = stylePtr->gap * 2 + boxWidth + iconWidth + gap + textWidth;
1561 valuePtr->height = MAX3(boxHeight, textHeight, iconHeight);
1562 }
1563
1564 /*
1565 *----------------------------------------------------------------------
1566 *
1567 *
1568 box --
1569 *
1570 * Draws the "checkbox" given the screen coordinates and the
1571 * value to be displayed.
1572 *
1573 * Results:
1574 * None.
1575 *
1576 * Side Effects:
1577 * The checkbox value is drawn.
1578 *
1579 *----------------------------------------------------------------------
1580 */
1581 static void
DrawCheckBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)1582 DrawCheckBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
1583 TreeView *tvPtr;
1584 Drawable drawable;
1585 TreeViewEntry *entryPtr;
1586 TreeViewValue *valuePtr;
1587 TreeViewStyle *stylePtr;
1588 TreeViewIcon icon;
1589 int x, y;
1590 {
1591 GC gc;
1592 TreeViewColumn *columnPtr;
1593 TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1594 int iconX, iconY, iconWidth, iconHeight;
1595 int textX, textY, textHeight;
1596 int gap, columnWidth, ttlWidth;
1597 int bool;
1598 int borderWidth, relief;
1599 TextLayout *textPtr;
1600 int boxX, boxY, boxWidth, boxHeight;
1601 TreeViewStyle *csPtr, sRec = *stylePtr;
1602 int valWidth = (valuePtr->textPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
1603 TextLayout *layPtr;
1604 int showValue;
1605
1606 layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
1607 showValue = (tvPtr->hideStyleText ? 0 : cbPtr->showValue);
1608
1609 columnPtr = valuePtr->columnPtr;
1610 csPtr = columnPtr->stylePtr;
1611
1612 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
1613 gc = sRec.gc;
1614
1615 if (gc != stylePtr->activeGC) {
1616 borderWidth = 0;
1617 relief = TK_RELIEF_FLAT;
1618 } else {
1619 borderWidth = 1;
1620 relief = TK_RELIEF_RAISED;
1621 }
1622
1623 columnWidth = columnPtr->width - PADDING(columnPtr->pad);
1624 if (!valuePtr->string) {
1625 return;
1626 }
1627
1628 if (cbPtr->size) {
1629 boxWidth = boxHeight = ODD(cbPtr->size);
1630 } else {
1631 boxWidth = boxHeight = 0;
1632 }
1633 ttlWidth = ( boxWidth + stylePtr->gap * 2);
1634 if (showValue) {
1635 ttlWidth += (valWidth + stylePtr->gap);
1636 }
1637 if (icon != NULL) {
1638 iconWidth = TreeViewIconWidth(icon);
1639 iconHeight = TreeViewIconHeight(icon);
1640 ttlWidth += iconWidth + stylePtr->gap;
1641 }
1642
1643 if (columnWidth > ttlWidth) {
1644 switch(columnPtr->justify) {
1645 case TK_JUSTIFY_RIGHT:
1646 x += (columnWidth - ttlWidth - stylePtr->gap*2);
1647 break;
1648 case TK_JUSTIFY_CENTER:
1649 x += (columnWidth - ttlWidth) / 2;
1650 break;
1651 case TK_JUSTIFY_LEFT:
1652 break;
1653 }
1654 }
1655
1656 bool = (strcmp(valuePtr->string, cbPtr->onValue) == 0);
1657 textPtr = (bool) ? cbPtr->onPtr : cbPtr->offPtr;
1658
1659 cbPtr->boxW = cbPtr->boxH = 0;
1660 cbPtr->boxX = boxX = x + stylePtr->gap;
1661 boxY = y + (entryPtr->height - boxHeight) / 2;
1662
1663 if (cbPtr->icons != NULL) {
1664 TreeViewIcon mIcon;
1665 mIcon = cbPtr->icons[bool];
1666 if (mIcon) {
1667 int mwid = TreeViewIconWidth(mIcon);
1668 int mhig = TreeViewIconHeight(mIcon);
1669 cbPtr->boxW = mwid;
1670 cbPtr->boxH = mhig;
1671 boxY = y + (entryPtr->height - mhig) / 2;
1672 if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, mIcon, 0, 0, mwid,
1673 mhig, drawable, boxX, boxY) != TCL_OK) return;
1674 }
1675
1676 } else {
1677 /*
1678 * Draw the box and check.
1679 *
1680 * +-----------+
1681 * | |
1682 * | * |
1683 * | * |
1684 * | * * |
1685 * | * * |
1686 * | * * |
1687 * | * |
1688 * +-----------+
1689 */
1690 if (boxWidth) {
1691 if (cbPtr->checkBg) {
1692 XFillRectangle(tvPtr->display, drawable, cbPtr->bgGC, boxX, boxY,
1693 boxWidth, boxHeight);
1694 } else {
1695 if (Blt_HasTile(stylePtr->fillTile)) {
1696 Blt_SetTileOrigin(tvPtr->tkwin, stylePtr->fillTile, -boxX, -boxY);
1697 Blt_TileRectangle(tvPtr->tkwin, drawable, stylePtr->fillTile,
1698 boxX, boxY, boxWidth, boxHeight );
1699 } else if (csPtr != NULL && Blt_HasTile(csPtr->fillTile)) {
1700 Blt_SetTileOrigin(tvPtr->tkwin, csPtr->fillTile, -boxX, -boxY);
1701 Blt_TileRectangle(tvPtr->tkwin, drawable, csPtr->fillTile,
1702 boxX, boxY, boxWidth, boxHeight );
1703 } else {
1704 XFillRectangle(tvPtr->display, drawable, cbPtr->fillGC, boxX, boxY, boxWidth, boxHeight);
1705
1706 }
1707 }
1708 cbPtr->boxW = boxWidth;
1709 cbPtr->boxH = boxHeight;
1710 XDrawRectangle(tvPtr->display, drawable, cbPtr->boxGC, boxX, boxY,
1711 boxWidth, boxHeight);
1712
1713 if (bool) {
1714 int midX, midY;
1715 int i;
1716
1717 for (i = 0; i < 3; i++) {
1718 midX = boxX + 2 * boxWidth / 5;
1719 midY = boxY + boxHeight - 5 + i;
1720 XDrawLine(tvPtr->display, drawable, cbPtr->checkGC,
1721 boxX + 2, boxY + boxHeight / 3 + 1 + i, midX, midY);
1722 XDrawLine(tvPtr->display, drawable, cbPtr->checkGC,
1723 midX, midY, boxX + boxWidth - 2, boxY + i + 1);
1724 }
1725 }
1726 }
1727 }
1728 #ifdef notdef
1729 textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */
1730 #endif
1731 iconWidth = iconHeight = 0;
1732 if (icon != NULL) {
1733 iconWidth = TreeViewIconWidth(icon);
1734 iconHeight = TreeViewIconHeight(icon);
1735 }
1736 textHeight = 0;
1737 gap = 0;
1738 if (showValue) {
1739 textHeight = textPtr->height;
1740 if (icon != NULL) {
1741 gap = stylePtr->gap;
1742 }
1743 }
1744 x = boxX + boxWidth + stylePtr->gap;
1745
1746 /* The icon sits to the left of the text. */
1747 iconX = x;
1748 iconY = y + (entryPtr->height - iconHeight) / 2;
1749 textX = iconX + iconWidth + gap;
1750 textY = y + (entryPtr->height - textHeight) / 2;
1751
1752 valuePtr->iX = iconX;
1753 valuePtr->iY = iconY;
1754 valuePtr->iW = iconWidth;
1755 valuePtr->iH = iconHeight;
1756 valuePtr->tX = textX;
1757 valuePtr->tY = textY;
1758 valuePtr->tW = (textPtr?textPtr->width:0);
1759 valuePtr->tH = textHeight;
1760
1761 if (icon != NULL) {
1762 if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth,
1763 iconHeight, drawable, iconX, iconY) != TCL_OK) return;
1764 } else {
1765 valuePtr->iW = 0;
1766 }
1767 if ((showValue) && (textPtr != NULL)) {
1768 TextStyle ts;
1769 XColor *color;
1770
1771 int disabled = (entryPtr->state == STATE_DISABLED);
1772
1773 if (disabled) {
1774 color = tvPtr->disabledColor;
1775 } else if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
1776 color = SELECT_FG(tvPtr);
1777 } else if (entryPtr->color != NULL) {
1778 color = entryPtr->color;
1779 } else {
1780 color = sRec.fgColor;
1781 GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
1782 }
1783 XSetForeground(tvPtr->display, gc, color->pixel);
1784 Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor,
1785 stylePtr->shadow.color, 0.0,
1786 TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
1787 Blt_DrawTextLayout(tvPtr->tkwin, drawable, textPtr, &ts, textX, textY);
1788 if (color != sRec.fgColor) {
1789 XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
1790 }
1791 } else {
1792 valuePtr->tW = 0;
1793 }
1794 stylePtr->flags &= ~STYLE_DIRTY;
1795 }
1796
1797 #if 0
1798 /*
1799 *----------------------------------------------------------------------
1800 *
1801 * PickCheckbox --
1802 *
1803 * Draws the "checkbox" given the screen coordinates and the
1804 * value to be displayed.
1805 *
1806 * Results:
1807 * None.
1808 *
1809 * Side Effects:
1810 * The checkbox value is drawn.
1811 *
1812 *----------------------------------------------------------------------
1813 */
1814 static int
PickCheckBox(entryPtr,valuePtr,stylePtr,worldX,worldY)1815 PickCheckBox(entryPtr, valuePtr, stylePtr, worldX, worldY)
1816 TreeViewEntry *entryPtr;
1817 TreeViewValue *valuePtr;
1818 TreeViewStyle *stylePtr;
1819 int worldX, worldY;
1820 {
1821 TreeViewColumn *columnPtr;
1822 TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1823 int columnWidth;
1824 int x, y, width, height;
1825
1826 columnPtr = valuePtr->columnPtr;
1827 columnWidth = columnPtr->width -
1828 (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
1829 if (columnWidth > valuePtr->width) {
1830 switch(columnPtr->justify) {
1831 case TK_JUSTIFY_RIGHT:
1832 worldX += (columnWidth - valuePtr->width);
1833 break;
1834 case TK_JUSTIFY_CENTER:
1835 worldX += (columnWidth - valuePtr->width) / 2;
1836 break;
1837 case TK_JUSTIFY_LEFT:
1838 break;
1839 }
1840 }
1841 width = height = ODD(cbPtr->size) + 2 * cbPtr->lineWidth;
1842 x = columnPtr->worldX + columnPtr->pad.side1 + stylePtr->gap -
1843 cbPtr->lineWidth;
1844 y = entryPtr->worldY + (entryPtr->height - height) / 2;
1845 if ((worldX >= x) && (worldX < (x + width)) &&
1846 (worldY >= y) && (worldY < (y + height))) {
1847 return TRUE;
1848 }
1849 return FALSE;
1850 }
1851 #endif
1852 /*
1853 *----------------------------------------------------------------------
1854 *
1855 * EditCheckbox --
1856 *
1857 * Edits the "checkbox".
1858 *
1859 * Results:
1860 * None.
1861 *
1862 * Side Effects:
1863 * The checkbox value is drawn.
1864 *
1865 *----------------------------------------------------------------------
1866 */
1867 static int
EditCheckBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)1868 EditCheckBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
1869 TreeView *tvPtr;
1870 TreeViewEntry *entryPtr;
1871 TreeViewValue *valuePtr;
1872 TreeViewStyle *stylePtr;
1873 int x;
1874 int y;
1875 int *retVal;
1876 {
1877 TreeViewColumn *columnPtr;
1878 TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1879 Tcl_Obj *objPtr;
1880 int boxY, isTest = *retVal;
1881 TreeViewStyle *vsPtr;
1882
1883 *retVal = 1;
1884 columnPtr = valuePtr->columnPtr;
1885 if (Blt_TreeGetValueByKey(tvPtr->interp, tvPtr->tree,
1886 entryPtr->node, columnPtr->key, &objPtr) != TCL_OK) {
1887 return TCL_ERROR;
1888 }
1889 vsPtr = valuePtr->stylePtr;
1890 if (vsPtr && vsPtr->noteditable) {
1891 *retVal = 0;
1892 return TCL_OK;
1893 }
1894 boxY = SCREENY(tvPtr, entryPtr->worldY) + (entryPtr->height -cbPtr->boxH) / 2;
1895 if (cbPtr->halo>=0) {
1896 int h = cbPtr->halo;
1897
1898 if (x < (cbPtr->boxX - h) || x > (cbPtr->boxX + cbPtr->boxW + h) ||
1899 y < (boxY - h) || y > (boxY + cbPtr->boxH + h)) {
1900 *retVal = 0;
1901 return TCL_OK;
1902 }
1903 }
1904 if (isTest) {
1905 return TCL_OK;
1906 }
1907 if (strcmp(Tcl_GetString(objPtr), cbPtr->onValue) == 0) {
1908 objPtr = Tcl_NewStringObj(cbPtr->offValue, -1);
1909 } else {
1910 objPtr = Tcl_NewStringObj(cbPtr->onValue, -1);
1911 }
1912 entryPtr->flags |= ENTRY_DIRTY;
1913 tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_RESORT);
1914 if (Blt_TreeSetValueByKey(tvPtr->interp, tvPtr->tree,
1915 entryPtr->node, columnPtr->key, objPtr) != TCL_OK) {
1916 return TCL_ERROR;
1917 }
1918 return TCL_OK;
1919 }
1920
1921 /*
1922 *----------------------------------------------------------------------
1923 *
1924 * FreeCheckbox --
1925 *
1926 * Releases resources allocated for the checkbox. The resources
1927 * freed by this routine are specific only to the "checkbox".
1928 * Other resources (common to all styles) are freed in the
1929 * Blt_TreeViewFreeStyle routine.
1930 *
1931 * Results:
1932 * None.
1933 *
1934 * Side Effects:
1935 * GCs allocated for the checkbox are freed.
1936 *
1937 *----------------------------------------------------------------------
1938 */
1939 static void
FreeCheckBox(tvPtr,stylePtr)1940 FreeCheckBox(tvPtr, stylePtr)
1941 TreeView *tvPtr;
1942 TreeViewStyle *stylePtr;
1943 {
1944 TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1945
1946 FreeTextBox(tvPtr, stylePtr);
1947 if (cbPtr->fillGC != NULL) {
1948 Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
1949 }
1950 if (cbPtr->boxGC != NULL) {
1951 Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
1952 }
1953 if (cbPtr->checkGC != NULL) {
1954 Tk_FreeGC(tvPtr->display, cbPtr->checkGC);
1955 }
1956 if (cbPtr->offPtr != NULL) {
1957 Blt_Free(cbPtr->offPtr);
1958 }
1959 if (cbPtr->onPtr != NULL) {
1960 Blt_Free(cbPtr->onPtr);
1961 }
1962 if (cbPtr->bgGC != NULL) {
1963 Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
1964 }
1965 }
1966
1967 /*
1968 *----------------------------------------------------------------------
1969 *
1970 * CreateComboBox --
1971 *
1972 * Creates a "combobox" style.
1973 *
1974 * Results:
1975 * A pointer to the new style structure.
1976 *
1977 *----------------------------------------------------------------------
1978 */
1979 static TreeViewStyle *
CreateComboBox(tvPtr,hPtr)1980 CreateComboBox(tvPtr, hPtr)
1981 TreeView *tvPtr;
1982 Blt_HashEntry *hPtr;
1983 {
1984 TreeViewComboBox *cbPtr;
1985
1986 cbPtr = (TreeViewComboBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewComboBox));
1987 cbPtr->classPtr = &comboBoxClass;
1988 cbPtr->buttonRelief = TK_RELIEF_RAISED;
1989 cbPtr->buttonBorderWidth = 1;
1990 cbPtr->borderWidth = 1;
1991 cbPtr->flags = STYLE_COMBOBOX;
1992 return (TreeViewStyle *)cbPtr;
1993 }
1994
1995 /*
1996 *----------------------------------------------------------------------
1997 *
1998 * ConfigureComboBox --
1999 *
2000 * Configures a "combobox" style. This routine performs
2001 * generates the GCs required for a combobox style.
2002 *
2003 * Results:
2004 * None.
2005 *
2006 * Side Effects:
2007 * GCs are created for the style.
2008 *
2009 *----------------------------------------------------------------------
2010 */
2011 static void
ConfigureComboBox(tvPtr,stylePtr)2012 ConfigureComboBox(tvPtr, stylePtr)
2013 TreeView *tvPtr;
2014 TreeViewStyle *stylePtr;
2015 {
2016 ConfigureTextBox(tvPtr, stylePtr);
2017 }
2018
2019 /*
2020 *----------------------------------------------------------------------
2021 *
2022 * MeasureComboBox --
2023 *
2024 * Determines the space requirements for the "combobox" given
2025 * the value to be displayed. Depending upon whether an icon
2026 * or text is displayed and their relative placements, this
2027 * routine computes the space needed for the text entry.
2028 *
2029 * Results:
2030 * None.
2031 *
2032 * Side Effects:
2033 * The width and height fields of *valuePtr* are set with the
2034 * computed dimensions.
2035 *
2036 *----------------------------------------------------------------------
2037 */
2038 static void
MeasureComboBox(tvPtr,stylePtr,valuePtr)2039 MeasureComboBox(tvPtr, stylePtr, valuePtr)
2040 TreeView *tvPtr;
2041 TreeViewStyle *stylePtr;
2042 TreeViewValue *valuePtr;
2043 {
2044 TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr;
2045 TreeViewColumn *columnPtr = valuePtr->columnPtr;
2046 int iconWidth, iconHeight, biconWidth, biconHeight;
2047 int textWidth, textHeight;
2048 int gap;
2049 Tk_Font font;
2050 TreeViewIcon icon, *butIcons;
2051
2052 textWidth = textHeight = 0;
2053 iconWidth = iconHeight = 0;
2054 valuePtr->width = valuePtr->height = 0;
2055
2056 butIcons = cbPtr->buttonIcons;
2057 icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
2058 if (icon != NULL && tvPtr->hideStyleIcons == 0) {
2059 iconWidth = TreeViewIconWidth(icon);
2060 iconHeight = TreeViewIconHeight(icon);
2061 }
2062 if (valuePtr->textPtr != NULL) {
2063 Blt_Free(valuePtr->textPtr);
2064 valuePtr->textPtr = NULL;
2065 }
2066 font = CHOOSE3(tvPtr->font, columnPtr->font, stylePtr->font);
2067 if (valuePtr->string != NULL) { /* New string defined. */
2068 TextStyle ts;
2069
2070 Blt_InitTextStyle(&ts);
2071 ts.font = font;
2072 ts.anchor = TK_ANCHOR_NW;
2073 ts.justify = valuePtr->columnPtr->justify;
2074 valuePtr->textPtr = Blt_GetTextLayoutStr(valuePtr->string, &ts);
2075 }
2076 gap = 0;
2077 if (valuePtr->textPtr != NULL && tvPtr->hideStyleText == 0) {
2078 textWidth = valuePtr->textPtr->width;
2079 textHeight = valuePtr->textPtr->height;
2080 if (stylePtr->icon != NULL) {
2081 gap = stylePtr->gap;
2082 }
2083 }
2084 if (butIcons != NULL) {
2085 TreeViewIcon mIcon;
2086 int i;
2087
2088 biconWidth = 0;
2089 biconHeight = 0;
2090 for (i=0; i<2; i++) {
2091 mIcon = butIcons[i];
2092 if (!mIcon) continue;
2093 biconWidth = MAX(biconWidth,TreeViewIconWidth(mIcon));
2094 biconHeight = MAX(biconHeight,TreeViewIconHeight(mIcon));
2095 }
2096 biconHeight = MAX(iconHeight,biconHeight);
2097 } else {
2098 biconWidth = STD_ARROW_WIDTH + 6;
2099 biconHeight = iconHeight;
2100 }
2101 cbPtr->buttonWidth = biconWidth + 2 * cbPtr->buttonBorderWidth;
2102 valuePtr->width = 2 * cbPtr->borderWidth + iconWidth + 4 * gap +
2103 cbPtr->buttonWidth + textWidth;
2104 valuePtr->height = MAX(textHeight, biconHeight) + 2 * cbPtr->borderWidth;
2105 }
2106
2107 /*
2108 *----------------------------------------------------------------------
2109 *
2110 * DrawComboBox --
2111 *
2112 * Draws the "combobox" given the screen coordinates and the
2113 * value to be displayed.
2114 *
2115 * Results:
2116 * None.
2117 *
2118 * Side Effects:
2119 * The combobox value is drawn.
2120 *
2121 *----------------------------------------------------------------------
2122 */
2123 static void
DrawComboBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)2124 DrawComboBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
2125 TreeView *tvPtr;
2126 Drawable drawable;
2127 TreeViewEntry *entryPtr;
2128 TreeViewValue *valuePtr;
2129 TreeViewStyle *stylePtr;
2130 TreeViewIcon icon;
2131 int x, y;
2132 {
2133 GC gc;
2134 TreeViewColumn *columnPtr;
2135 TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr;
2136 int iconX, iconY, iconWidth, iconHeight;
2137 int textX, textY, textHeight;
2138 int buttonX, buttonY;
2139 int gap, columnWidth;
2140 TreeViewStyle sRec;
2141 int valWidth = (valuePtr->textPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
2142 TextLayout *layPtr;
2143
2144 layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
2145
2146 columnPtr = valuePtr->columnPtr;
2147 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
2148 gc = sRec.gc;
2149
2150 if (!valuePtr->string) {
2151 return;
2152 }
2153 buttonX = x + columnPtr->width;
2154 buttonX -= columnPtr->pad.side2 + cbPtr->borderWidth +
2155 cbPtr->buttonWidth + stylePtr->gap;
2156 buttonY = y;
2157
2158 columnWidth = columnPtr->width -
2159 (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
2160 if (columnWidth > valWidth) {
2161 switch(columnPtr->justify) {
2162 case TK_JUSTIFY_RIGHT:
2163 x += (columnWidth - valWidth);
2164 break;
2165 case TK_JUSTIFY_CENTER:
2166 x += (columnWidth - valWidth) / 2;
2167 break;
2168 case TK_JUSTIFY_LEFT:
2169 break;
2170 }
2171 }
2172
2173 #ifdef notdef
2174 textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */
2175 #endif
2176
2177 iconWidth = iconHeight = 0;
2178 if (icon != NULL) {
2179 iconWidth = TreeViewIconWidth(icon);
2180 iconHeight = TreeViewIconHeight(icon);
2181 }
2182 textHeight = 0;
2183 if (layPtr != NULL) {
2184 textHeight = layPtr->height;
2185 }
2186 gap = 0;
2187 if ((icon != NULL) && (layPtr != NULL)) {
2188 gap = stylePtr->gap;
2189 }
2190
2191 iconX = x + gap;
2192 iconY = y + (entryPtr->height - iconHeight) / 2;
2193 textX = iconX + iconWidth + gap;
2194 textY = y + (entryPtr->height - textHeight) / 2;
2195
2196 valuePtr->iX = iconX;
2197 valuePtr->iY = iconY;
2198 valuePtr->iW = iconWidth;
2199 valuePtr->iH = iconHeight;
2200 valuePtr->tX = textX;
2201 valuePtr->tY = textY;
2202 valuePtr->tW = valuePtr->textPtr->width;
2203 valuePtr->tH = textHeight;
2204 if (icon != NULL) {
2205 if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth,
2206 iconHeight, drawable, iconX, iconY) != TCL_OK) return;
2207 } else {
2208 valuePtr->iW = 0;
2209 }
2210 if (layPtr != NULL) {
2211 TextStyle ts;
2212 XColor *color;
2213
2214 int disabled = (entryPtr->state == STATE_DISABLED);
2215
2216 if (disabled) {
2217 color = tvPtr->disabledColor;
2218 } else if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
2219 color = SELECT_FG(tvPtr);
2220 } else if (entryPtr->color != NULL) {
2221 color = entryPtr->color;
2222 } else {
2223 color = sRec.fgColor;
2224 GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
2225 }
2226 XSetForeground(tvPtr->display, gc, color->pixel);
2227 Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor,
2228 stylePtr->shadow.color, 0.0,
2229 TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
2230 Blt_DrawTextLayout(tvPtr->tkwin, drawable, valuePtr->textPtr,
2231 &ts, textX, textY);
2232 if (color != sRec.fgColor) {
2233 XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
2234 }
2235 } else {
2236 valuePtr->tW = 0;
2237 }
2238 if (cbPtr->buttonIcons == NULL) {
2239 if (valuePtr == tvPtr->activeValuePtr) {
2240 Blt_Fill3DRectangle(tvPtr->tkwin, drawable, stylePtr->activeBorder,
2241 buttonX, buttonY + cbPtr->borderWidth, cbPtr->buttonWidth,
2242 entryPtr->height - 2 * cbPtr->borderWidth,
2243 cbPtr->buttonBorderWidth, cbPtr->buttonRelief);
2244 } else {
2245 Blt_Fill3DRectangle(tvPtr->tkwin, drawable, columnPtr->titleBorder,
2246 buttonX, buttonY + cbPtr->borderWidth, cbPtr->buttonWidth,
2247 entryPtr->height - 2 * cbPtr->borderWidth,
2248 cbPtr->buttonBorderWidth, cbPtr->buttonRelief);
2249 }
2250 buttonX += cbPtr->buttonWidth / 2;
2251 buttonY += entryPtr->height / 2;
2252 Blt_DrawArrow(tvPtr->display, drawable, gc, buttonX, buttonY,
2253 STD_ARROW_HEIGHT, ARROW_DOWN);
2254 stylePtr->flags &= ~STYLE_DIRTY;
2255 } else {
2256 TreeViewIcon butIcon;
2257 int biconWidth;
2258 int biconHeight;
2259 if (valuePtr == tvPtr->activeValuePtr && cbPtr->buttonIcons[1]) {
2260 butIcon = cbPtr->buttonIcons[1];
2261 } else {
2262 butIcon = cbPtr->buttonIcons[0];
2263 }
2264 biconWidth = TreeViewIconWidth(butIcon);
2265 biconHeight = MAX(iconHeight,TreeViewIconHeight(butIcon));
2266
2267 buttonY += (entryPtr->height-biconHeight)/2;
2268 Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, butIcon, 0, 0, biconWidth,
2269 biconHeight, drawable, buttonX, buttonY);
2270 }
2271 }
2272
2273 /*
2274 *----------------------------------------------------------------------
2275 *
2276 * PickCombobox --
2277 *
2278 * Draws the "checkbox" given the screen coordinates and the
2279 * value to be displayed.
2280 *
2281 * Results:
2282 * None.
2283 *
2284 * Side Effects:
2285 * The checkbox value is drawn.
2286 *
2287 *----------------------------------------------------------------------
2288 */
2289 static int
PickComboBox(entryPtr,valuePtr,stylePtr,worldX,worldY)2290 PickComboBox(entryPtr, valuePtr, stylePtr, worldX, worldY)
2291 TreeViewEntry *entryPtr;
2292 TreeViewValue *valuePtr;
2293 TreeViewStyle *stylePtr;
2294 int worldX, worldY;
2295 {
2296 TreeViewColumn *columnPtr;
2297 TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr;
2298 int x, y, width, height;
2299
2300 columnPtr = valuePtr->columnPtr;
2301 width = cbPtr->buttonWidth;
2302 height = entryPtr->height - 4;
2303 x = columnPtr->worldX + columnPtr->width - columnPtr->pad.side2 -
2304 cbPtr->borderWidth - columnPtr->borderWidth - width;
2305 y = entryPtr->worldY + cbPtr->borderWidth;
2306 if ((worldX >= x) && (worldX < (x + width)) &&
2307 (worldY >= y) && (worldY < (y + height))) {
2308 return TRUE;
2309 }
2310 return FALSE;
2311 }
2312
2313 /*
2314 *----------------------------------------------------------------------
2315 *
2316 * EditCombobox --
2317 *
2318 * Edits the "combobox".
2319 *
2320 * Results:
2321 * None.
2322 *
2323 * Side Effects:
2324 * The checkbox value is drawn.
2325 *
2326 *----------------------------------------------------------------------
2327 */
2328 /*ARGSUSED*/
2329 static int
EditComboBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)2330 EditComboBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
2331 TreeView *tvPtr;
2332 TreeViewEntry *entryPtr;
2333 TreeViewValue *valuePtr;
2334 TreeViewStyle *stylePtr; /* Not used. */
2335 int x;
2336 int y;
2337 int *retVal;
2338 {
2339 int isTest = *retVal;
2340 *retVal = 1;
2341 if (isTest) {
2342 return TCL_OK;
2343 }
2344 return Blt_TreeViewTextbox(tvPtr, entryPtr, valuePtr->columnPtr);
2345 }
2346
2347 /*
2348 *----------------------------------------------------------------------
2349 *
2350 * FreeComboBox --
2351 *
2352 * Releases resources allocated for the combobox. The resources
2353 * freed by this routine are specific only to the "combobox".
2354 * Other resources (common to all styles) are freed in the
2355 * Blt_TreeViewFreeStyle routine.
2356 *
2357 * Results:
2358 * None.
2359 *
2360 * Side Effects:
2361 * GCs allocated for the combobox are freed.
2362 *
2363 *----------------------------------------------------------------------
2364 */
2365 static void
FreeComboBox(tvPtr,stylePtr)2366 FreeComboBox(tvPtr, stylePtr)
2367 TreeView *tvPtr;
2368 TreeViewStyle *stylePtr;
2369 {
2370 FreeTextBox(tvPtr, stylePtr);
2371 }
2372
2373 /*
2374 *----------------------------------------------------------------------
2375 *
2376 * CreateBarbox --
2377 *
2378 * Creates a "checkbox" style.
2379 *
2380 * Results:
2381 * A pointer to the new style structure.
2382 *
2383 *----------------------------------------------------------------------
2384 */
2385 static TreeViewStyle *
CreateBarBox(tvPtr,hPtr)2386 CreateBarBox(tvPtr, hPtr)
2387 TreeView *tvPtr;
2388 Blt_HashEntry *hPtr;
2389 {
2390 TreeViewBarBox *cbPtr;
2391
2392 cbPtr = (TreeViewBarBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewBarBox));
2393 cbPtr->classPtr = &barBoxClass;
2394 cbPtr->gap = 4;
2395 cbPtr->lineWidth = 1;
2396 cbPtr->showValue = TRUE;
2397 cbPtr->flags = STYLE_BARBOX;
2398 return (TreeViewStyle *)cbPtr;
2399 }
2400
2401 /*
2402 *----------------------------------------------------------------------
2403 *
2404 * ConfigureBarbox --
2405 *
2406 * Configures a "checkbox" style. This routine performs
2407 * generates the GCs required for a checkbox style.
2408 *
2409 * Results:
2410 * None.
2411 *
2412 * Side Effects:
2413 * GCs are created for the style.
2414 *
2415 *----------------------------------------------------------------------
2416 */
2417 static void
ConfigureBarBox(tvPtr,stylePtr)2418 ConfigureBarBox(tvPtr, stylePtr)
2419 TreeView *tvPtr;
2420 TreeViewStyle *stylePtr;
2421 {
2422 GC newGC;
2423 TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2424 XColor *bgColor;
2425 XGCValues gcValues;
2426 unsigned long gcMask;
2427
2428 bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, stylePtr->border));
2429
2430 gcValues.background = bgColor->pixel;
2431 gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
2432 ConfigureTextBox(tvPtr, stylePtr);
2433 gcMask = GCForeground;
2434 gcValues.foreground = cbPtr->fillColor->pixel;
2435 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
2436 if (cbPtr->fillGC != NULL) {
2437 Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
2438 }
2439 cbPtr->fillGC = newGC;
2440
2441 gcMask = GCForeground | GCLineWidth;
2442 gcValues.line_width = cbPtr->lineWidth;
2443 gcValues.foreground = cbPtr->boxColor->pixel;
2444 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
2445 if (cbPtr->boxGC != NULL) {
2446 Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
2447 }
2448 cbPtr->boxGC = newGC;
2449 if (cbPtr->barBg) {
2450 bgColor = Tk_3DBorderColor(cbPtr->barBg);
2451 gcValues.background = bgColor->pixel;
2452 gcValues.foreground = bgColor->pixel;
2453 newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
2454 if (cbPtr->bgGC != NULL) {
2455 Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
2456 }
2457 cbPtr->bgGC = newGC;
2458 }
2459 stylePtr->flags |= STYLE_DIRTY;
2460 }
2461
2462 /*
2463 *----------------------------------------------------------------------
2464 *
2465 * MeasureBarbox --
2466 *
2467 * Determines the space requirements for the "barbox" given
2468 * the value to be displayed. Depending upon whether an icon
2469 * or text is displayed and their relative placements, this
2470 * routine computes the space needed for the text entry.
2471 *
2472 * Results:
2473 * None.
2474 *
2475 * Side Effects:
2476 * The width and height fields of *valuePtr* are set with the
2477 * computed dimensions.
2478 *
2479 *----------------------------------------------------------------------
2480 */
2481 static void
MeasureBarBox(tvPtr,stylePtr,valuePtr)2482 MeasureBarBox(tvPtr, stylePtr, valuePtr)
2483 TreeView *tvPtr;
2484 TreeViewStyle *stylePtr;
2485 TreeViewValue *valuePtr;
2486 {
2487 TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2488 TreeViewColumn *columnPtr = valuePtr->columnPtr;
2489 TreeViewEntry *entryPtr;
2490 int iconWidth, iconHeight;
2491 int textWidth, textHeight;
2492 int gap, bGap;
2493 int boxWidth, boxHeight;
2494 TreeViewIcon icon;
2495 int rel = 0;
2496
2497 entryPtr = valuePtr->entryPtr;
2498 bGap = stylePtr->gap;
2499 if (cbPtr->barWidth <= 0) {
2500 boxWidth = 0;
2501 bGap = 0;
2502 } else if (cbPtr->barWidth >= 4000) {
2503 boxWidth = 4000;
2504 } else {
2505 boxWidth = ODD(cbPtr->barWidth);
2506 }
2507 if (cbPtr->barHeight <= 0) {
2508 boxHeight = 0;
2509 } else if (cbPtr->barHeight >= 4000) {
2510 boxHeight = 4000;
2511 } else {
2512 boxHeight = ODD(cbPtr->barHeight);
2513 }
2514
2515 textWidth = textHeight = iconWidth = iconHeight = 0;
2516 valuePtr->width = valuePtr->height = 0;
2517 icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
2518 if (icon != NULL && tvPtr->hideStyleIcons == 0) {
2519 iconWidth = TreeViewIconWidth(icon);
2520 iconHeight = TreeViewIconHeight(icon);
2521 }
2522 /* TODO: recalc over/under only on change.*/
2523 gap = 0;
2524 if (cbPtr->showValue) {
2525
2526 if (valuePtr->textPtr != NULL) {
2527 Blt_Free(valuePtr->textPtr);
2528 valuePtr->textPtr = NULL;
2529 }
2530 if (valuePtr->string != NULL) {
2531 /* New string defined. */
2532 TextStyle ts;
2533 Tcl_Obj *fmtObj;
2534
2535 fmtObj = NotNullObj(cbPtr->formatCmd);
2536 if (fmtObj == NULL) {
2537 fmtObj = NotNullObj(columnPtr->formatCmd);
2538 }
2539 if (fmtObj == NULL) {
2540 fmtObj = NotNullObj(tvPtr->formatCmd);
2541 }
2542
2543 Blt_InitTextStyle(&ts);
2544 ts.font = CHOOSE3(tvPtr->font, columnPtr->font, stylePtr->font);
2545 ts.anchor = TK_ANCHOR_NW;
2546 ts.justify = valuePtr->columnPtr->justify;
2547 if (fmtObj) {
2548 Tcl_DString cmdString;
2549 char *string;
2550 int result;
2551 Tcl_Interp *interp = tvPtr->interp;
2552
2553 Tcl_Preserve(entryPtr);
2554 rel = 1;
2555 Blt_TreeViewPercentSubst(tvPtr, valuePtr->entryPtr, valuePtr->columnPtr, Tcl_GetString(fmtObj), valuePtr->string, &cmdString);
2556 result = Tcl_GlobalEval(interp, Tcl_DStringValue(&cmdString));
2557 if ((entryPtr->flags & ENTRY_DELETED) || (tvPtr->flags & TV_DELETED)) {
2558 Tcl_Release(entryPtr);
2559 return;
2560 }
2561
2562 Blt_TreeViewOptsInit(tvPtr);
2563 Tcl_DStringFree(&cmdString);
2564 if (result == TCL_OK) {
2565 string = Tcl_GetStringResult(interp);
2566 valuePtr->textPtr = Blt_GetTextLayoutStr(string, &ts);
2567 }
2568 }
2569 if (valuePtr->textPtr == NULL) {
2570 valuePtr->textPtr = Blt_GetTextLayoutStr(valuePtr->string, &ts);
2571 }
2572 }
2573 if (valuePtr->textPtr != NULL && tvPtr->hideStyleText == 0) {
2574 textWidth = valuePtr->textPtr->width;
2575 textHeight = valuePtr->textPtr->height;
2576 if (stylePtr->icon != NULL) {
2577 gap = stylePtr->gap;
2578 }
2579 }
2580
2581 if (stylePtr->icon != NULL) {
2582 gap = stylePtr->gap;
2583 }
2584 }
2585 valuePtr->width = stylePtr->gap + bGap + boxWidth + iconWidth + gap + textWidth + 2;
2586 valuePtr->height = MAX3(boxHeight, textHeight, iconHeight);
2587 if (rel) Tcl_Release(entryPtr);
2588 }
2589
2590 /*
2591 *----------------------------------------------------------------------
2592 *
2593 * DrawBarbox --
2594 *
2595 * Draws the "checkbox" given the screen coordinates and the
2596 * value to be displayed.
2597 *
2598 * Results:
2599 * None.
2600 *
2601 * Side Effects:
2602 * The checkbox value is drawn.
2603 *
2604 *----------------------------------------------------------------------
2605 */
2606 static void
DrawBarBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)2607 DrawBarBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
2608 TreeView *tvPtr;
2609 Drawable drawable;
2610 TreeViewEntry *entryPtr;
2611 TreeViewValue *valuePtr;
2612 TreeViewStyle *stylePtr;
2613 TreeViewIcon icon;
2614 int x, y;
2615 {
2616 GC gc;
2617 TreeViewColumn *columnPtr;
2618 TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2619 int iconX, iconY, iconWidth, iconHeight;
2620 int textX, textY, textHeight, ttlWidth, bGap, iGap;
2621 int gap, columnWidth;
2622 TextLayout *textPtr;
2623 int boxX, boxY, boxWidth, boxHeight, bw;
2624 TreeViewStyle *csPtr, sRec = *stylePtr;
2625 int valWidth = (valuePtr->textPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
2626 double curValue;
2627 char *string;
2628 TextStyle ts;
2629 XColor *color;
2630 TextLayout *layPtr;
2631 int showValue = (tvPtr->hideStyleText ? 0 : cbPtr->showValue);
2632
2633 layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
2634
2635 string = NULL;
2636 textPtr = NULL;
2637 columnPtr = valuePtr->columnPtr;
2638 csPtr = columnPtr->stylePtr;
2639
2640 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
2641 gc = sRec.gc;
2642
2643 columnWidth = columnPtr->width - PADDING(columnPtr->pad);
2644 if (!valuePtr->string) {
2645 return;
2646 }
2647 if (Tcl_GetDouble(NULL, valuePtr->string, &curValue) != TCL_OK) {
2648 if (sscanf(valuePtr->string, "%lg", &curValue) != 1) {
2649 return;
2650 }
2651 }
2652 if (cbPtr->maxValue<=cbPtr->minValue) {
2653 return;
2654 }
2655
2656 #ifdef notdef
2657 textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */
2658 #endif
2659 iconWidth = iconHeight = 0;
2660 bGap = stylePtr->gap;
2661 iGap = 0;
2662 if (cbPtr->barWidth<=0) {
2663 boxWidth = 0;
2664 bGap = 0;
2665 } else if (cbPtr->barWidth >= 4000) {
2666 boxWidth = 4000;
2667 } else {
2668 boxWidth = ODD(cbPtr->barWidth);
2669 }
2670 if (cbPtr->barHeight<=0) {
2671 boxHeight = 0;
2672 } else if (cbPtr->barHeight >= 4000) {
2673 boxHeight = 4000;
2674 } else {
2675 boxHeight = ODD(cbPtr->barHeight);
2676 }
2677 ttlWidth = ( boxWidth + stylePtr->gap * 2);
2678 if (showValue) {
2679 ttlWidth += (valWidth + stylePtr->gap);
2680 Blt_InitTextStyle(&ts);
2681 ts.font = CHOOSE(tvPtr->font, stylePtr->font);
2682 ts.anchor = TK_ANCHOR_NW;
2683 ts.justify = columnPtr->justify;
2684 }
2685 if (icon != NULL) {
2686 iGap = stylePtr->gap;
2687 iconWidth = TreeViewIconWidth(icon);
2688 iconHeight = TreeViewIconHeight(icon);
2689 ttlWidth += iconWidth + stylePtr->gap;
2690 }
2691
2692 if (columnWidth > ttlWidth) {
2693 switch(columnPtr->justify) {
2694 case TK_JUSTIFY_RIGHT:
2695 x += (columnWidth - ttlWidth - stylePtr->gap*2);
2696 break;
2697 case TK_JUSTIFY_CENTER:
2698 x += (columnWidth - ttlWidth) / 2;
2699 break;
2700 case TK_JUSTIFY_LEFT:
2701 break;
2702 }
2703 }
2704
2705 /*
2706 * Draw the barbox
2707 */
2708 boxX = x + iGap;
2709 boxY = y + (entryPtr->height - boxHeight) / 2;
2710 if (curValue<cbPtr->minValue) {
2711 bw = 0;
2712 } else if (curValue > cbPtr->maxValue) {
2713 bw = boxWidth;
2714 } else if (cbPtr->minValue >= cbPtr->maxValue) {
2715 bw = 0;
2716 } else {
2717 int diff = (cbPtr->maxValue-cbPtr->minValue);
2718 bw = (int)(boxWidth*(1.0*(curValue-cbPtr->minValue)/diff));
2719 }
2720 if (boxHeight && boxWidth) {
2721 if (cbPtr->barBg) {
2722 XFillRectangle(tvPtr->display, drawable, cbPtr->bgGC, boxX, boxY, boxWidth, boxHeight);
2723 }
2724 if (bw>0) {
2725 if (Blt_HasTile(stylePtr->fillTile)) {
2726 Blt_SetTileOrigin(tvPtr->tkwin, stylePtr->fillTile, -boxX, -boxY);
2727 Blt_TileRectangle(tvPtr->tkwin, drawable, stylePtr->fillTile,
2728 boxX, boxY, bw, boxHeight );
2729 } else if (csPtr != NULL && Blt_HasTile(csPtr->fillTile)) {
2730 Blt_SetTileOrigin(tvPtr->tkwin, csPtr->fillTile, -boxX, -boxY);
2731 Blt_TileRectangle(tvPtr->tkwin, drawable, csPtr->fillTile,
2732 boxX, boxY, bw, boxHeight );
2733 } else {
2734
2735 XFillRectangle(tvPtr->display, drawable, cbPtr->fillGC, boxX, boxY, bw, boxHeight);
2736 }
2737 }
2738 XDrawRectangle(tvPtr->display, drawable, cbPtr->boxGC, boxX, boxY,
2739 boxWidth, boxHeight);
2740 }
2741
2742 textHeight = 0;
2743 gap = 0;
2744 if (showValue) {
2745
2746 int disabled = (entryPtr->state == STATE_DISABLED);
2747
2748 if (disabled) {
2749 color = tvPtr->disabledColor;
2750 } else if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
2751 color = SELECT_FG(tvPtr);
2752 } else if (entryPtr->color != NULL) {
2753 color = entryPtr->color;
2754 } else {
2755 color = sRec.fgColor;
2756 GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
2757 }
2758 Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor, stylePtr->shadow.color, 0.0, TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
2759 textPtr = valuePtr->textPtr; // Blt_GetTextLayout(string, &ts);
2760 textHeight = textPtr->height;
2761 if (icon != NULL) {
2762 gap = stylePtr->gap;
2763 }
2764 }
2765 x = boxX + boxWidth + bGap;
2766
2767 /* The icon sits to the left of the text. */
2768 iconX = x;
2769 iconY = y + (entryPtr->height - iconHeight) / 2;
2770 textX = iconX + iconWidth + gap;
2771 textY = y + (entryPtr->height - textHeight) / 2;
2772
2773 valuePtr->iX = iconX;
2774 valuePtr->iY = iconY;
2775 valuePtr->iW = iconWidth;
2776 valuePtr->iH = iconHeight;
2777 valuePtr->tX = textX;
2778 valuePtr->tY = textY;
2779 valuePtr->tW = (textPtr?textPtr->width:0);
2780 valuePtr->tH = textHeight;
2781
2782 if (icon != NULL) {
2783 if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth,
2784 iconHeight, drawable, iconX, iconY) != TCL_OK) return;
2785 } else {
2786 valuePtr->iW = 0;
2787 }
2788 if ((showValue) && (textPtr != NULL)) {
2789 XSetForeground(tvPtr->display, gc, color->pixel);
2790 Blt_DrawTextLayout(tvPtr->tkwin, drawable, textPtr, &ts, textX, textY);
2791 if (color != sRec.fgColor) {
2792 XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
2793 }
2794 } else {
2795 valuePtr->tW = 0;
2796 }
2797 stylePtr->flags &= ~STYLE_DIRTY;
2798 }
2799
2800 #if 0
2801 /*
2802 *----------------------------------------------------------------------
2803 *
2804 * PickBarbox --
2805 *
2806 * Draws the "checkbox" given the screen coordinates and the
2807 * value to be displayed.
2808 *
2809 * Results:
2810 * None.
2811 *
2812 * Side Effects:
2813 * The checkbox value is drawn.
2814 *
2815 *----------------------------------------------------------------------
2816 */
2817 static int
PickBarBox(entryPtr,valuePtr,stylePtr,worldX,worldY)2818 PickBarBox(entryPtr, valuePtr, stylePtr, worldX, worldY)
2819 TreeViewEntry *entryPtr;
2820 TreeViewValue *valuePtr;
2821 TreeViewStyle *stylePtr;
2822 int worldX, worldY;
2823 {
2824 TreeViewColumn *columnPtr;
2825 TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2826 int columnWidth;
2827 int x, y, width, height;
2828
2829 columnPtr = valuePtr->columnPtr;
2830 columnWidth = columnPtr->width -
2831 (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
2832 if (columnWidth > valuePtr->width) {
2833 switch(columnPtr->justify) {
2834 case TK_JUSTIFY_RIGHT:
2835 worldX += (columnWidth - valuePtr->width);
2836 break;
2837 case TK_JUSTIFY_CENTER:
2838 worldX += (columnWidth - valuePtr->width) / 2;
2839 break;
2840 case TK_JUSTIFY_LEFT:
2841 break;
2842 }
2843 }
2844 width = ODD(cbPtr->barWidth) + 2 * cbPtr->lineWidth;
2845 height = ODD(cbPtr->barHeight) + 2 * cbPtr->lineWidth;
2846 x = columnPtr->worldX + columnPtr->pad.side1 + cbPtr->gap -
2847 cbPtr->lineWidth;
2848 y = entryPtr->worldY + (entryPtr->height - height) / 2;
2849 if ((worldX >= x) && (worldX < (x + width)) &&
2850 (worldY >= y) && (worldY < (y + height))) {
2851 return TRUE;
2852 }
2853 return FALSE;
2854 }
2855 #endif
2856 /*
2857 *----------------------------------------------------------------------
2858 *
2859 * EditBarbox --
2860 *
2861 * Edits the "checkbox".
2862 *
2863 * Results:
2864 * None.
2865 *
2866 * Side Effects:
2867 * The checkbox value is drawn.
2868 *
2869 *----------------------------------------------------------------------
2870 */
2871 static int
EditBarBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)2872 EditBarBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
2873 TreeView *tvPtr;
2874 TreeViewEntry *entryPtr;
2875 TreeViewValue *valuePtr;
2876 TreeViewStyle *stylePtr;
2877 int x;
2878 int y;
2879 int *retVal;
2880 {
2881 *retVal = 0;
2882 return TCL_OK;
2883 }
2884
2885 /*
2886 *----------------------------------------------------------------------
2887 *
2888 * FreeBarbox --
2889 *
2890 * Releases resources allocated for the checkbox. The resources
2891 * freed by this routine are specific only to the "checkbox".
2892 * Other resources (common to all styles) are freed in the
2893 * Blt_TreeViewFreeStyle routine.
2894 *
2895 * Results:
2896 * None.
2897 *
2898 * Side Effects:
2899 * GCs allocated for the checkbox are freed.
2900 *
2901 *----------------------------------------------------------------------
2902 */
2903 static void
FreeBarBox(tvPtr,stylePtr)2904 FreeBarBox(tvPtr, stylePtr)
2905 TreeView *tvPtr;
2906 TreeViewStyle *stylePtr;
2907 {
2908 TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2909
2910 FreeTextBox(tvPtr, stylePtr);
2911 if (cbPtr->fillGC != NULL) {
2912 Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
2913 }
2914 if (cbPtr->boxGC != NULL) {
2915 Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
2916 }
2917 if (cbPtr->bgGC != NULL) {
2918 Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
2919 }
2920 }
2921
2922 /*
2923 *----------------------------------------------------------------------
2924 *
2925 * CreateWindowBox --
2926 *
2927 * Creates a "textbox" style.
2928 *
2929 * Results:
2930 * A pointer to the new style structure.
2931 *
2932 *----------------------------------------------------------------------
2933 */
2934 static TreeViewStyle *
CreateWindowBox(tvPtr,hPtr)2935 CreateWindowBox(tvPtr, hPtr)
2936 TreeView *tvPtr;
2937 Blt_HashEntry *hPtr;
2938 {
2939 TreeViewWindowBox *tbPtr;
2940
2941 tbPtr = (TreeViewWindowBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewWindowBox));
2942 tbPtr->classPtr = &windowBoxClass;
2943 tbPtr->flags = STYLE_WINDOWBOX;
2944 return (TreeViewStyle *)tbPtr;
2945 }
2946
2947 /*
2948 *----------------------------------------------------------------------
2949 *
2950 * ConfigureWindowBox --
2951 *
2952 * Configures a "textbox" style. This routine performs
2953 * generates the GCs required for a textbox style.
2954 *
2955 * Results:
2956 * None.
2957 *
2958 * Side Effects:
2959 * GCs are created for the style.
2960 *
2961 *----------------------------------------------------------------------
2962 */
2963 static void
ConfigureWindowBox(tvPtr,stylePtr)2964 ConfigureWindowBox(tvPtr, stylePtr)
2965 TreeView *tvPtr;
2966 TreeViewStyle *stylePtr;
2967 {
2968 TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
2969 tbPtr->flags |= STYLE_DIRTY;
2970 }
2971
2972 /*
2973 *----------------------------------------------------------------------
2974 *
2975 * MeasureWindowBox --
2976 *
2977 * Determines the space requirements for the "textbox" given
2978 * the value to be displayed. Depending upon whether an icon
2979 * or text is displayed and their relative placements, this
2980 * routine computes the space needed for the text entry.
2981 *
2982 * Results:
2983 * None.
2984 *
2985 * Side Effects:
2986 * The width and height fields of *valuePtr* are set with the
2987 * computed dimensions.
2988 *
2989 *----------------------------------------------------------------------
2990 */
2991 static void
MeasureWindowBox(tvPtr,stylePtr,valuePtr)2992 MeasureWindowBox(tvPtr, stylePtr, valuePtr)
2993 TreeView *tvPtr;
2994 TreeViewStyle *stylePtr;
2995 TreeViewValue *valuePtr;
2996 {
2997 TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
2998 valuePtr->width = tbPtr->windowWidth;
2999 valuePtr->height = tbPtr->windowHeight;
3000 }
3001
3002
3003 typedef struct {
3004 int flags;
3005 char *name;
3006 TreeView *tvPtr;
3007 TreeViewEntry *entryPtr;
3008 TreeViewColumn *columnPtr;
3009 Blt_HashEntry *hPtr;
3010 Tk_Window tkwin;
3011 TreeViewWindowBox *stylePtr;
3012 } WindowCell;
3013
3014 static void EmbWinStructureProc( ClientData clientData, XEvent *eventPtr);
3015
3016 static void
EmbWinRemove(WindowCell * wcPtr)3017 EmbWinRemove(WindowCell *wcPtr) {
3018 Blt_HashEntry *hPtr;
3019 TreeView *tvPtr = wcPtr->tvPtr;
3020 hPtr = Blt_FindHashEntry(&tvPtr->winTable, wcPtr->name);
3021 if (hPtr != NULL && wcPtr == (WindowCell*)Blt_GetHashValue(hPtr)) {
3022 Blt_DeleteHashEntry(&tvPtr->winTable, hPtr);
3023 }
3024 Blt_Free(wcPtr->name);
3025 wcPtr->name = NULL;
3026 if (wcPtr->hPtr) Blt_DeleteHashEntry(&tvPtr->winCellTable, wcPtr->hPtr);
3027 wcPtr->hPtr = NULL;
3028 if (wcPtr->tkwin) {
3029 Tk_DeleteEventHandler(wcPtr->tkwin, StructureNotifyMask,
3030 EmbWinStructureProc, (ClientData) wcPtr);
3031 Tk_ManageGeometry(wcPtr->tkwin, NULL, NULL);
3032 wcPtr->tkwin = NULL;
3033 }
3034 Blt_Free(wcPtr);
3035 }
3036
3037 /* Free all windows on widget delete. */
3038 void
Blt_TreeViewFreeWindows(TreeView * tvPtr)3039 Blt_TreeViewFreeWindows( TreeView *tvPtr)
3040 {
3041 Blt_HashEntry *hPtr;
3042 Blt_HashSearch cursor;
3043 WindowCell *wcPtr;
3044
3045 for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3046 hPtr = Blt_NextHashEntry(&cursor)) {
3047 wcPtr = Blt_GetHashValue(hPtr);
3048 if (wcPtr) {
3049 EmbWinRemove(wcPtr);
3050 }
3051 }
3052 }
3053
3054 static void
EmbWinUnmapNow(Tk_Window ewTkwin,Tk_Window tkwin)3055 EmbWinUnmapNow(Tk_Window ewTkwin, Tk_Window tkwin)
3056 {
3057 if (tkwin != Tk_Parent(ewTkwin)) {
3058 Tk_UnmaintainGeometry(ewTkwin, tkwin);
3059 }
3060 Tk_UnmapWindow(ewTkwin);
3061 }
3062
EmbWinRequestProc(ClientData clientData,Tk_Window tkwin)3063 static void EmbWinRequestProc(ClientData clientData,
3064 Tk_Window tkwin)
3065 {
3066 }
3067
3068 static void EmbWinLostSlaveProc(ClientData clientData, Tk_Window tkwin);
3069
3070 static Tk_GeomMgr windowGeomType = {
3071 "treeview", /* name */
3072 EmbWinRequestProc, /* requestProc */
3073 EmbWinLostSlaveProc, /* lostSlaveProc */
3074 };
3075
3076
3077 void
Blt_TreeViewMarkWindows(TreeView * tvPtr,int flag)3078 Blt_TreeViewMarkWindows( TreeView *tvPtr, int flag)
3079 {
3080 Blt_HashEntry *hPtr;
3081 Blt_HashSearch cursor;
3082 WindowCell *wcPtr;
3083
3084 for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3085 hPtr = Blt_NextHashEntry(&cursor)) {
3086 wcPtr = Blt_GetHashValue(hPtr);
3087 if (wcPtr) {
3088 if (flag == TV_WINDOW_CLEAR) {
3089 /* Clear window drawn flags. */
3090 wcPtr->flags &= ~TV_WINDOW_DRAW;
3091 } else if (flag == TV_WINDOW_UNMAP && (wcPtr->flags&TV_WINDOW_DRAW)==0) {
3092 /* Unmapped undrawn window. */
3093 EmbWinUnmapNow(wcPtr->tkwin, tvPtr->tkwin);
3094 }
3095 }
3096 }
3097 }
3098
3099 static WindowCell *
bltTreeViewFindWindow(TreeViewEntry * entryPtr,TreeViewColumn * columnPtr)3100 bltTreeViewFindWindow(TreeViewEntry *entryPtr,
3101 TreeViewColumn *columnPtr)
3102 {
3103 TreeView *tvPtr = columnPtr->tvPtr;
3104 Blt_HashEntry *hPtr;
3105 WindowCell *wcPtr;
3106 Tcl_DString dStr;
3107 char *key;
3108
3109 Tcl_DStringInit(&dStr);
3110 Tcl_DStringAppendElement(&dStr, columnPtr->key);
3111 Tcl_DStringAppendElement(&dStr, Blt_Itoa(entryPtr->node->inode));
3112 key = Tcl_DStringValue(&dStr);
3113 hPtr = Blt_FindHashEntry(&tvPtr->winCellTable, key);
3114 Tcl_DStringFree(&dStr);
3115 if (hPtr == NULL) return NULL;
3116 wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3117 return wcPtr;
3118 }
3119
isValidSubWin(TreeView * tvPtr,Tk_Window tkwin)3120 static int isValidSubWin( TreeView *tvPtr, Tk_Window tkwin) {
3121 Tk_Window ancestor, parent;
3122 parent = Tk_Parent(tkwin);
3123 for (ancestor = tvPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
3124 if (ancestor == parent) {
3125 break;
3126 }
3127 if (Tk_IsTopLevel(ancestor)) {
3128 return 0;
3129 }
3130 }
3131 if (Tk_IsTopLevel(tkwin) || (tkwin == tvPtr->tkwin)) {
3132 return 0;
3133 }
3134 return 1;
3135 }
3136
3137 static WindowCell *
bltTreeViewWindowMake(TreeView * tvPtr,TreeViewEntry * entryPtr,TreeViewValue * valuePtr,TreeViewWindowBox * wbPtr)3138 bltTreeViewWindowMake( TreeView *tvPtr, TreeViewEntry *entryPtr,
3139 TreeViewValue *valuePtr, TreeViewWindowBox *wbPtr)
3140 {
3141 char *name, *key;
3142 Blt_HashEntry *hPtr;
3143 WindowCell *wcPtr = NULL, *w2Ptr;
3144 TreeViewColumn *columnPtr = valuePtr->columnPtr;
3145 Tcl_DString dStr;
3146 Tk_Window tkwin;
3147 int result, isNew;
3148 Tcl_Interp *interp;
3149 char *execCmd = wbPtr->windowCmd;
3150
3151 interp = tvPtr->interp;
3152
3153 Tcl_DStringInit(&dStr);
3154 Tcl_DStringAppendElement(&dStr, columnPtr->key);
3155 Tcl_DStringAppendElement(&dStr, Blt_Itoa(entryPtr->node->inode));
3156 key = Tcl_DStringValue(&dStr);
3157 hPtr = Blt_CreateHashEntry(&tvPtr->winCellTable, key, &isNew);
3158 Tcl_DStringFree(&dStr);
3159 Tcl_DStringInit(&dStr);
3160
3161 if (hPtr == NULL) return NULL;
3162 if (!isNew) {
3163 wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3164 if (wcPtr && wcPtr->tkwin == NULL) {
3165 return NULL;
3166 }
3167 return wcPtr;
3168 }
3169
3170 wcPtr = (WindowCell*)Blt_Calloc(1, sizeof(WindowCell));
3171 Blt_SetHashValue(hPtr, wcPtr);
3172 wcPtr->name = NULL;
3173 wcPtr->tvPtr = tvPtr;
3174 wcPtr->columnPtr = columnPtr;
3175 wcPtr->entryPtr = entryPtr;
3176 wcPtr->hPtr = hPtr;
3177 wcPtr->stylePtr = wbPtr;
3178 wcPtr->flags |= TV_WINDOW_DRAW;
3179
3180 if (execCmd != NULL) {
3181 Tcl_DString cmdString;
3182
3183 Blt_TreeViewPercentSubst(tvPtr, entryPtr, columnPtr, execCmd, valuePtr->string, &cmdString);
3184 result = Tcl_GlobalEval(interp, Tcl_DStringValue(&cmdString));
3185 Blt_TreeViewOptsInit(tvPtr);
3186 Tcl_DStringFree(&cmdString);
3187 if ((entryPtr->flags & ENTRY_DELETED) || (tvPtr->flags & TV_DELETED)) {
3188 result = TCL_ERROR;
3189 }
3190 if (result != TCL_OK) {
3191 goto error;
3192 }
3193 name = Tcl_GetStringResult(interp);
3194 } else {
3195 name = valuePtr->string;
3196 if (name == NULL) {
3197 goto error;
3198 }
3199 if (name[0] != '.') {
3200 Tcl_DStringAppend(&dStr, Tk_PathName(tvPtr->tkwin), -1);
3201 Tcl_DStringAppend(&dStr, ".", -1);
3202 Tcl_DStringAppend(&dStr, name, -1);
3203 name = Tcl_DStringValue(&dStr);
3204 }
3205 }
3206 tkwin = Tk_NameToWindow(tvPtr->interp, name, tvPtr->tkwin);
3207 if (tkwin == NULL || !isValidSubWin(tvPtr, tkwin)) {
3208 goto error;
3209 }
3210 if (name && name[0]) {
3211
3212 wcPtr->name = Blt_Strdup(name);
3213 hPtr = Blt_CreateHashEntry(&tvPtr->winTable, wcPtr->name, &isNew);
3214 if (hPtr != NULL) {
3215 w2Ptr = (WindowCell*)Blt_GetHashValue(hPtr);
3216 if (w2Ptr && (w2Ptr->flags&TV_WINDOW_DRAW)) {
3217 goto error;
3218 }
3219 Blt_SetHashValue(hPtr, wcPtr);
3220 }
3221 }
3222 Tcl_DStringFree(&dStr);
3223 if (execCmd == NULL) {
3224 entryPtr->flags |= ENTRY_DATA_WINDOW;
3225 }
3226 entryPtr->flags |= ENTRY_WINDOW;
3227 wcPtr->tkwin = tkwin;
3228 Tk_ManageGeometry(tkwin, &windowGeomType, wcPtr);
3229 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
3230 EmbWinStructureProc, (ClientData) wcPtr);
3231 return wcPtr;
3232
3233 error:
3234 if (wcPtr) {
3235 Blt_DeleteHashEntry(&tvPtr->winCellTable, wcPtr->hPtr);
3236 if (wcPtr->name) Blt_Free(wcPtr->name);
3237 Blt_Free(wcPtr);
3238 }
3239 Tcl_DStringFree(&dStr);
3240 return NULL;
3241 }
3242
3243 /* Some other manager took control. */
EmbWinLostSlaveProc(ClientData clientData,Tk_Window tkwin)3244 static void EmbWinLostSlaveProc(ClientData clientData, Tk_Window tkwin)
3245 {
3246 register WindowCell *wcPtr = (WindowCell *) clientData;
3247 EmbWinUnmapNow(tkwin, wcPtr->tvPtr->tkwin);
3248 EmbWinRemove(wcPtr);
3249 }
3250
3251 static void
EmbWinStructureProc(clientData,eventPtr)3252 EmbWinStructureProc(clientData, eventPtr)
3253 ClientData clientData; /* Pointer to record describing window item. */
3254 XEvent *eventPtr; /* Describes what just happened. */
3255 {
3256 register WindowCell *ewPtr = (WindowCell *) clientData;
3257
3258 if (eventPtr->type != DestroyNotify) {
3259 return;
3260 }
3261 EmbWinRemove(ewPtr);
3262 }
3263
3264 int
Blt_WinResizeAlways(Tk_Window tkwin)3265 Blt_WinResizeAlways(Tk_Window tkwin)
3266 {
3267 while (tkwin != NULL) {
3268 #ifdef Tk_IsResizeYes
3269 if (Tk_IsResizeYes(tkwin)) return 1;
3270 #endif
3271 if (Tk_TopWinHierarchy(tkwin)) break;
3272 tkwin = Tk_Parent(tkwin);
3273 }
3274 return 0;
3275 }
3276
3277 static void
EmbWinDisplay(TreeView * tvPtr,WindowCell * wcPtr,int x,int y,int width,int height)3278 EmbWinDisplay(TreeView *tvPtr, WindowCell *wcPtr,
3279 int x, int y, int width, int height)
3280 {
3281 Tk_Window tkwin = tvPtr->tkwin;
3282 Tk_Window cwTkwin = wcPtr->tkwin;
3283 int diff, reqWidth, reqHeight, sticky, diffx, diffy;
3284
3285
3286 if ((diff = (y-tvPtr->titleHeight- tvPtr->insetY))<0) {
3287 height += diff;
3288 y -= diff;
3289 }
3290 if (width < 2 || height < 2) {
3291 if (wcPtr->flags&TV_WINDOW_DRAW) {
3292 EmbWinUnmapNow(cwTkwin, tkwin);
3293 }
3294 return;
3295 }
3296 reqWidth = Tk_ReqWidth(cwTkwin);
3297 if (reqWidth > width) { reqWidth = width; }
3298 reqHeight = Tk_ReqHeight(cwTkwin);
3299 if (reqHeight > height) { reqHeight = height; }
3300 diffx = width - reqWidth;
3301 diffy = height - reqHeight;
3302
3303 sticky = wcPtr->stylePtr->sticky;
3304
3305 if (sticky&STICK_EAST && sticky&STICK_WEST) {
3306 reqWidth += diffx;
3307 }
3308 if (sticky&STICK_NORTH && sticky&STICK_SOUTH) {
3309 reqHeight += diffy;
3310 }
3311 if (!(sticky&STICK_WEST)) {
3312 x += (sticky&STICK_EAST) ? diffx : diffx/2;
3313 }
3314 if (!(sticky&STICK_NORTH)) {
3315 y += (sticky&STICK_SOUTH) ? diffy : diffy/2;
3316 }
3317 width = reqWidth;
3318 height = reqHeight;
3319 if (tkwin == Tk_Parent(cwTkwin)) {
3320 if ((x != Tk_X(cwTkwin)) || (y != Tk_Y(cwTkwin))
3321 || (width != Tk_Width(cwTkwin))
3322 || (height != Tk_Height(cwTkwin))
3323 || Blt_WinResizeAlways(cwTkwin)
3324 ) {
3325 Tk_MoveResizeWindow(cwTkwin, x, y, width, height);
3326 }
3327 Tk_MapWindow(cwTkwin);
3328 } else {
3329 Tk_MaintainGeometry(cwTkwin, tkwin, x, y, width, height);
3330 }
3331 wcPtr->flags |= TV_WINDOW_DRAW;
3332 }
3333
3334 /*
3335 * Called when a cell has a window from data.
3336 */
3337 void
Blt_TreeViewWindowUpdate(TreeViewEntry * entryPtr,TreeViewColumn * columnPtr)3338 Blt_TreeViewWindowUpdate(TreeViewEntry *entryPtr, TreeViewColumn *columnPtr)
3339 {
3340 TreeViewWindowBox *wbPtr;
3341 WindowCell *wcPtr;
3342
3343 if (entryPtr->flags & ENTRY_DATA_WINDOW) {
3344 /* Cell may already have a window from data. */
3345
3346 } else if (columnPtr->stylePtr != NULL &&
3347 columnPtr->stylePtr->classPtr->className[0] == 'w') {
3348 wbPtr = (TreeViewWindowBox *)columnPtr->stylePtr;
3349 if (wbPtr->windowCmd != NULL) return;
3350
3351 } else {
3352 return;
3353 }
3354 wcPtr = bltTreeViewFindWindow(entryPtr, columnPtr);
3355 if (wcPtr == NULL || wcPtr->tkwin == NULL) return;
3356 EmbWinUnmapNow(wcPtr->tkwin, wcPtr->tvPtr->tkwin);
3357 Tk_ManageGeometry(wcPtr->tkwin, NULL, NULL);
3358 EmbWinRemove(wcPtr);
3359 }
3360
3361 void
Blt_TreeViewWindowRelease(TreeViewEntry * entryPtr,TreeViewColumn * columnPtr)3362 Blt_TreeViewWindowRelease(TreeViewEntry *entryPtr, TreeViewColumn *columnPtr)
3363 {
3364 Blt_HashEntry *hPtr;
3365 Blt_HashSearch cursor;
3366 WindowCell *wcPtr;
3367 TreeView *tvPtr;
3368
3369 tvPtr = (columnPtr?columnPtr->tvPtr:entryPtr->tvPtr);
3370
3371 for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3372 hPtr = Blt_NextHashEntry(&cursor)) {
3373 wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3374 if (wcPtr == NULL) continue;
3375 if (entryPtr && entryPtr == wcPtr->entryPtr) {
3376 EmbWinUnmapNow(wcPtr->tkwin, wcPtr->tvPtr->tkwin);
3377 EmbWinRemove(wcPtr);
3378 continue;
3379 }
3380 if (columnPtr && columnPtr == wcPtr->columnPtr) {
3381 EmbWinUnmapNow(wcPtr->tkwin, wcPtr->tvPtr->tkwin);
3382 EmbWinRemove(wcPtr);
3383 continue;
3384 }
3385 }
3386 }
3387 /*
3388 *----------------------------------------------------------------------
3389 *
3390 * DrawWindowBox --
3391 *
3392 * Draws the "windowbox" given the screen coordinates.
3393 * The window name is taken from the data value.
3394 *
3395 * Results:
3396 * None.
3397 *
3398 * Side Effects:
3399 * The window is drawn.
3400 *
3401 *----------------------------------------------------------------------
3402 */
3403 static void
DrawWindowBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)3404 DrawWindowBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
3405 TreeView *tvPtr;
3406 Drawable drawable;
3407 TreeViewEntry *entryPtr;
3408 TreeViewValue *valuePtr;
3409 TreeViewStyle *stylePtr;
3410 TreeViewIcon icon;
3411 int x, y;
3412 {
3413 TreeViewColumn *columnPtr;
3414 TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
3415 Tk_Window tkwin;
3416 int width, height, diff;
3417 WindowCell *wcPtr;
3418 TreeViewStyle sRec = *stylePtr;
3419
3420 columnPtr = valuePtr->columnPtr;
3421
3422 Tcl_Preserve(entryPtr);
3423 wcPtr = bltTreeViewWindowMake(tvPtr, entryPtr, valuePtr, tbPtr);
3424 if ((entryPtr->flags & ENTRY_DELETED) || (tvPtr->flags & TV_DELETED)) {
3425 Tcl_Release(entryPtr);
3426 return;
3427 }
3428 Tcl_Release(entryPtr);
3429
3430 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
3431
3432 if (wcPtr != NULL) {
3433 int columnWidth = columnPtr->width -
3434 (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
3435
3436 tkwin = wcPtr->tkwin;
3437 width = columnWidth;
3438 height = entryPtr->height-1;
3439 if ((diff = (y-tvPtr->titleHeight- tvPtr->insetY))<0) {
3440 height += diff;
3441 y -= diff;
3442 }
3443 EmbWinDisplay(tvPtr, wcPtr, x, y, width, height);
3444 }
3445 stylePtr->flags &= ~STYLE_DIRTY;
3446 }
3447
3448 /*
3449 *----------------------------------------------------------------------
3450 *
3451 * EditWindowbox --
3452 *
3453 * Edits the "windowbox".
3454 *
3455 * Results:
3456 * None.
3457 *
3458 *----------------------------------------------------------------------
3459 */
3460 /*ARGSUSED*/
3461 static int
EditWindowBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)3462 EditWindowBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
3463 TreeView *tvPtr;
3464 TreeViewEntry *entryPtr;
3465 TreeViewValue *valuePtr;
3466 TreeViewStyle *stylePtr; /* Not used. */
3467 int x;
3468 int y;
3469 int *retVal;
3470 {
3471 return TCL_ERROR;
3472 }
3473
3474 /*
3475 *----------------------------------------------------------------------
3476 *
3477 * FreeWindowBox --
3478 *
3479 * Releases resources allocated for the textbox. The resources
3480 * freed by this routine are specific only to the "textbox".
3481 * Other resources (common to all styles) are freed in the
3482 * Blt_TreeViewFreeStyle routine.
3483 *
3484 * Results:
3485 * None.
3486 *
3487 * Side Effects:
3488 * GCs allocated for the textbox are freed.
3489 *
3490 *----------------------------------------------------------------------
3491 */
3492 static void
FreeWindowBox(tvPtr,stylePtr)3493 FreeWindowBox(tvPtr, stylePtr)
3494 TreeView *tvPtr;
3495 TreeViewStyle *stylePtr;
3496 {
3497 TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
3498 Blt_HashEntry *hPtr;
3499 Blt_HashSearch cursor;
3500 WindowCell *wcPtr;
3501
3502 if (!tbPtr) return;
3503
3504 for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3505 hPtr = Blt_NextHashEntry(&cursor)) {
3506 wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3507 if (wcPtr && stylePtr == (TreeViewStyle*)wcPtr->stylePtr) {
3508 EmbWinRemove(wcPtr);
3509 }
3510 }
3511
3512 }
3513
3514 static TreeViewStyle *
GetStyle(interp,tvPtr,styleName)3515 GetStyle(interp, tvPtr, styleName)
3516 Tcl_Interp *interp;
3517 TreeView *tvPtr;
3518 char *styleName;
3519 {
3520 Blt_HashEntry *hPtr;
3521
3522 hPtr = Blt_FindHashEntry(&tvPtr->styleTable, styleName);
3523 if (hPtr == NULL) {
3524 if (interp != NULL) {
3525 Tcl_AppendResult(interp, "can't find style \"", styleName,
3526 "\"", (char *)NULL);
3527 }
3528 return NULL;
3529 }
3530 return Blt_GetHashValue(hPtr);
3531 }
3532
3533 int
Blt_TreeViewGetStyle(interp,tvPtr,styleName,stylePtrPtr)3534 Blt_TreeViewGetStyle(interp, tvPtr, styleName, stylePtrPtr)
3535 Tcl_Interp *interp;
3536 TreeView *tvPtr;
3537 char *styleName;
3538 TreeViewStyle **stylePtrPtr;
3539 {
3540 TreeViewStyle *stylePtr;
3541
3542 stylePtr = GetStyle(interp, tvPtr, styleName);
3543 if (stylePtr == NULL) {
3544 return TCL_ERROR;
3545 }
3546 stylePtr->refCount++;
3547 *stylePtrPtr = stylePtr;
3548 return TCL_OK;
3549 }
3550
3551 int
Blt_TreeViewGetStyleMake(interp,tvPtr,styleName,stylePtrPtr,columnPtr,entryPtr,valuePtr)3552 Blt_TreeViewGetStyleMake(interp, tvPtr, styleName, stylePtrPtr, columnPtr, entryPtr, valuePtr)
3553 Tcl_Interp *interp;
3554 TreeView *tvPtr;
3555 char *styleName;
3556 TreeViewStyle **stylePtrPtr;
3557 TreeViewColumn *columnPtr;
3558 TreeViewEntry *entryPtr;
3559 TreeViewValue *valuePtr;
3560 {
3561 TreeViewStyle *stylePtr = NULL;
3562 Tcl_DString dString;
3563 int result;
3564
3565 if (strlen(styleName)==0) {
3566 Tcl_AppendResult(interp, "can not use style with empty name", 0);
3567 return TCL_ERROR;
3568 }
3569 if (Blt_TreeViewGetStyle(NULL, tvPtr, styleName, &stylePtr) != TCL_OK) {
3570 if (tvPtr->styleCmd == NULL) {
3571 if (stylePtr == NULL) {
3572 if (interp != NULL) {
3573 Tcl_AppendResult(interp, "style not found: ", styleName, 0);
3574 }
3575 return TCL_ERROR;
3576 }
3577 } else if (!strcmp(tvPtr->styleCmd, "%W style create textbox %V")) {
3578 stylePtr = Blt_TreeViewCreateStyle(interp, tvPtr, STYLE_TEXTBOX, styleName);
3579 assert(stylePtr);
3580 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
3581
3582 } else {
3583 Tcl_DStringInit(&dString);
3584 Blt_TreeViewPercentSubst(tvPtr, entryPtr, columnPtr, tvPtr->styleCmd, styleName, &dString);
3585 /* TODO: should save/restore intep state. */
3586 result = Tcl_GlobalEval(tvPtr->interp, Tcl_DStringValue(&dString));
3587 Tcl_DStringFree(&dString);
3588 if ((tvPtr->flags & TV_DELETED)) {
3589 return TCL_ERROR;
3590 }
3591 if (result != TCL_OK) {
3592 if (interp != NULL) {
3593 Tcl_AppendResult(interp, "error in -stylecommand ", tvPtr->styleCmd, " for: ", styleName, 0);
3594 }
3595 return TCL_ERROR;
3596 }
3597 result = Blt_TreeViewGetStyle(interp, tvPtr, styleName, &stylePtr);
3598 if (result != TCL_OK) {
3599 if (interp != NULL) {
3600 Tcl_AppendResult(interp, "style not found: ", styleName, 0);
3601 }
3602 return TCL_ERROR;
3603 }
3604 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
3605 if (interp != NULL) {
3606 Tcl_ResetResult(interp);
3607 }
3608 }
3609 }
3610 *stylePtrPtr = stylePtr;
3611 return TCL_OK;
3612 }
3613
3614 static TreeViewStyle *
CreateStyle(interp,tvPtr,type,styleName,objc,objv,create)3615 CreateStyle(interp, tvPtr, type, styleName, objc, objv, create)
3616 Tcl_Interp *interp;
3617 TreeView *tvPtr; /* TreeView widget. */
3618 int type; /* Type of style: either
3619 * STYLE_TEXTBOX,
3620 * STYLE_COMBOBOX, or
3621 * STYLE_CHECKBOX */
3622 char *styleName; /* Name of the new style. */
3623 int objc;
3624 Tcl_Obj *CONST *objv;
3625 int create;
3626 {
3627 Blt_HashEntry *hPtr;
3628 int isNew, ref = 1;
3629 TreeViewStyle *stylePtr;
3630
3631 hPtr = Blt_CreateHashEntry(&tvPtr->styleTable, styleName, &isNew);
3632 if (!isNew) {
3633 /* Don't kick an error unless styleCmd is changed. */
3634 if (create && (tvPtr->styleCmd == NULL || strcmp(tvPtr->styleCmd, "%W style create textbox %V") == 0 || (tvPtr->styleCmd[0] == 0))) {
3635 stylePtr = Blt_GetHashValue(hPtr);
3636 if (type == (stylePtr->flags&STYLE_TYPE)) {
3637 ref = 0;
3638 goto doconf;
3639 }
3640 }
3641 if (interp != NULL) {
3642 Tcl_AppendResult(interp, "style \"", styleName,
3643 "\" already exists", (char *)NULL);
3644 }
3645 return NULL;
3646 }
3647 /* Create the new marker based upon the given type */
3648 switch (type) {
3649 case STYLE_TEXTBOX:
3650 stylePtr = CreateTextBox(tvPtr, hPtr);
3651 break;
3652 case STYLE_COMBOBOX:
3653 stylePtr = CreateComboBox(tvPtr, hPtr);
3654 break;
3655 case STYLE_CHECKBOX:
3656 stylePtr = CreateCheckBox(tvPtr, hPtr);
3657 break;
3658 case STYLE_WINDOWBOX:
3659 stylePtr = CreateWindowBox(tvPtr, hPtr);
3660 break;
3661 case STYLE_BARBOX:
3662 stylePtr = CreateBarBox(tvPtr, hPtr);
3663 break;
3664 default:
3665 return NULL;
3666 }
3667 doconf:
3668 Blt_TreeViewOptsInit(tvPtr);
3669 if (Blt_ConfigureComponentFromObj(tvPtr->interp, tvPtr->tkwin, styleName,
3670 stylePtr->classPtr->className, stylePtr->classPtr->specsPtr,
3671 objc, objv, (char *)stylePtr, 0) != TCL_OK) {
3672 if (ref) {
3673 Blt_TreeViewFreeStyle(tvPtr, stylePtr);
3674 }
3675 return NULL;
3676 }
3677 if (stylePtr->tile != NULL) {
3678 Blt_SetTileChangedProc(stylePtr->tile, Blt_TreeViewTileChangedProc, tvPtr);
3679 }
3680 if (stylePtr->fillTile != NULL) {
3681 Blt_SetTileChangedProc(stylePtr->fillTile, Blt_TreeViewTileChangedProc, tvPtr);
3682 }
3683 stylePtr->refCount += ref;
3684 return stylePtr;
3685 }
3686
3687 void
Blt_TreeViewUpdateStyleGCs(tvPtr,stylePtr)3688 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr)
3689 TreeView *tvPtr;
3690 TreeViewStyle *stylePtr;
3691 {
3692 if (tvPtr->font == NULL) return;
3693 (*stylePtr->classPtr->configProc)(tvPtr, stylePtr);
3694 stylePtr->flags |= STYLE_DIRTY;
3695 Blt_TreeViewEventuallyRedraw(tvPtr);
3696 }
3697
3698 void
Blt_TreeViewUpdateStyles(tvPtr)3699 Blt_TreeViewUpdateStyles(tvPtr)
3700 TreeView *tvPtr;
3701 {
3702 Blt_HashEntry *hPtr;
3703 Blt_HashSearch cursor;
3704 TreeViewStyle *stylePtr;
3705 Blt_TreeViewUpdateStyleGCs(tvPtr, tvPtr->stylePtr);
3706
3707 for (hPtr = Blt_FirstHashEntry(&tvPtr->styleTable, &cursor); hPtr != NULL;
3708 hPtr = Blt_NextHashEntry(&cursor)) {
3709 stylePtr = Blt_GetHashValue(hPtr);
3710 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
3711 }
3712 }
3713
3714 TreeViewStyle *
Blt_TreeViewCreateStyle(interp,tvPtr,type,styleName)3715 Blt_TreeViewCreateStyle(interp, tvPtr, type, styleName)
3716 Tcl_Interp *interp;
3717 TreeView *tvPtr; /* TreeView widget. */
3718 int type; /* Type of style: either
3719 * STYLE_TEXTBOX,
3720 * STYLE_COMBOBOX, or
3721 * STYLE_CHECKBOX */
3722 char *styleName; /* Name of the new style. */
3723 {
3724 return CreateStyle(interp, tvPtr, type, styleName, 0, (Tcl_Obj **)NULL, 0);
3725 }
3726
3727 void
Blt_TreeViewFreeStyle(tvPtr,stylePtr)3728 Blt_TreeViewFreeStyle(tvPtr, stylePtr)
3729 TreeView *tvPtr;
3730 TreeViewStyle *stylePtr;
3731 {
3732 stylePtr->refCount--;
3733 #ifdef notdef
3734 fprint(f(stderr, "Blt_TreeViewFreeStyle %s count=%d\n", stylePtr->name,
3735 stylePtr->refCount);
3736 #endif
3737 /* Remove the style from the hash table so that it's name can be used.*/
3738 /* If no cell is using the style, remove it.*/
3739 if ((stylePtr->refCount <= 0) && !(stylePtr->flags & STYLE_USER)){
3740 #ifdef notdef
3741 fprintf(stderr, "freeing %s\n", stylePtr->name);
3742 #endif
3743 /*Blt_HashEntry *hPtr;
3744 hPtr = Blt_FindHashEntry(&tvPtr->styleTagTable, stylePtr->name, &isNew);
3745 if (hPtr != NULL) {
3746 Blt_DeleteHashEntry(&tvPtr->styleTagTable, hPtr);
3747 }*/
3748 Blt_TreeViewOptsInit(tvPtr);
3749 Blt_FreeObjOptions(tvPtr->interp,
3750 stylePtr->classPtr->specsPtr, (char *)stylePtr,
3751 tvPtr->display, 0);
3752 (*stylePtr->classPtr->freeProc)(tvPtr, stylePtr);
3753 if (stylePtr->hashPtr != NULL) {
3754 Blt_DeleteHashEntry(&tvPtr->styleTable, stylePtr->hashPtr);
3755 }
3756 if (stylePtr->name != NULL) {
3757 Blt_Free(stylePtr->name);
3758 }
3759 if (tvPtr->subStylePtr == stylePtr) { tvPtr->subStylePtr = NULL; }
3760 if (tvPtr->altStylePtr == stylePtr) { tvPtr->altStylePtr = NULL; }
3761 if (tvPtr->emptyStylePtr == stylePtr) { tvPtr->emptyStylePtr = NULL; }
3762 Blt_Free(stylePtr);
3763 }
3764 }
3765
3766 void
3767 Blt_TreeViewSetStyleIcon(tvPtr, stylePtr, icon)
3768 TreeView *tvPtr;
3769 TreeViewStyle *stylePtr;
3770 TreeViewIcon icon;
3771 {
3772 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3773
3774 if (tbPtr && tbPtr->icon != NULL) {
3775 Blt_TreeViewFreeIcon(tvPtr, tbPtr->icon);
3776 }
3777 tbPtr->icon = icon;
3778 }
3779
3780 GC
3781 Blt_TreeViewGetStyleGC(tvPtr, stylePtr)
3782 TreeView *tvPtr;
3783 TreeViewStyle *stylePtr;
3784 {
3785 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3786 return (tbPtr && tbPtr->gc) ? tbPtr->gc : tvPtr->stylePtr->gc;
3787 }
3788
3789 Tk_3DBorder
3790 Blt_TreeViewGetStyleBorder(tvPtr, stylePtr)
3791 TreeView *tvPtr;
3792 TreeViewStyle *stylePtr;
3793 {
3794 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3795 Tk_3DBorder border;
3796
3797 if (!tbPtr) {
3798 return tvPtr->border;
3799 }
3800 border = (tbPtr->flags & STYLE_HIGHLIGHT)
3801 ? tbPtr->highlightBorder : tbPtr->border;
3802 return (border != NULL) ? border : tvPtr->border;
3803 }
3804
3805 Tk_Font
3806 Blt_TreeViewGetStyleFont(tvPtr, columnPtr, stylePtr)
3807 TreeView *tvPtr;
3808 TreeViewColumn *columnPtr;
3809 TreeViewStyle *stylePtr;
3810 {
3811 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3812
3813 if (tbPtr != NULL && tbPtr->font != NULL) {
3814 return tbPtr->font;
3815 }
3816 if (columnPtr != NULL && columnPtr->font != NULL) {
3817 return columnPtr->font;
3818 }
3819 return tvPtr->font;
3820 }
3821
3822 XColor *
3823 Blt_TreeViewGetStyleFg(tvPtr, columnPtr, stylePtr)
3824 TreeView *tvPtr;
3825 TreeViewColumn *columnPtr;
3826 TreeViewStyle *stylePtr;
3827 {
3828 TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3829
3830 if (tbPtr && tbPtr->fgColor != NULL) {
3831 return tbPtr->fgColor;
3832 }
3833 if (columnPtr && columnPtr->fgColor) {
3834 return columnPtr->fgColor;
3835 }
3836 return tvPtr->fgColor;
3837 }
3838
3839 static void
3840 DrawValue(tvPtr, entryPtr, valuePtr)
3841 TreeView *tvPtr;
3842 TreeViewEntry *entryPtr;
3843 TreeViewValue *valuePtr;
3844 {
3845 Drawable drawable;
3846 int sx, sy, dx, dy;
3847 int width, height, ishid;
3848 int left, right, top, bottom;
3849 TreeViewColumn *columnPtr;
3850 TreeViewStyle *stylePtr;
3851 Tk_3DBorder selBorder;
3852
3853 stylePtr = valuePtr->stylePtr;
3854 ishid = (stylePtr?stylePtr->hidden:0);
3855 if (stylePtr == NULL) {
3856 stylePtr = CHOOSE(tvPtr->stylePtr, valuePtr->columnPtr->stylePtr);
3857 }
3858 if (stylePtr->cursor != None) {
3859 if (valuePtr == tvPtr->activeValuePtr) {
3860 Tk_DefineCursor(tvPtr->tkwin, stylePtr->cursor);
3861 } else {
3862 if (tvPtr->cursor != None) {
3863 Tk_DefineCursor(tvPtr->tkwin, tvPtr->cursor);
3864 } else {
3865 Tk_UndefineCursor(tvPtr->tkwin);
3866 }
3867 }
3868 }
3869 columnPtr = valuePtr->columnPtr;
3870 dx = SCREENX(tvPtr, columnPtr->worldX) + columnPtr->pad.side1-1;
3871 dy = SCREENY(tvPtr, entryPtr->worldY);
3872 height = entryPtr->height - 1;
3873 width = valuePtr->columnPtr->width - PADDING(columnPtr->pad);
3874
3875 top = tvPtr->titleHeight + tvPtr->insetY;
3876 bottom = Tk_Height(tvPtr->tkwin) - tvPtr->insetY;
3877 left = tvPtr->insetX;
3878 right = Tk_Width(tvPtr->tkwin) - tvPtr->insetX;
3879
3880 if (((dx + width) < left) || (dx > right) ||
3881 ((dy + height) < top) || (dy > bottom)) {
3882 return; /* Value is clipped. */
3883 }
3884
3885 drawable = Tk_GetPixmap(tvPtr->display, Tk_WindowId(tvPtr->tkwin),
3886 width, height, Tk_Depth(tvPtr->tkwin));
3887 /* Draw the background of the value. */
3888
3889 if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
3890 selBorder = SELECT_BORDER(tvPtr);
3891 Blt_Fill3DRectangle(tvPtr->tkwin, drawable, selBorder, 0, 0, width, height,
3892 0, TK_RELIEF_FLAT);
3893 } else if ((valuePtr == tvPtr->activeValuePtr) ||
3894 (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr))) {
3895 Tk_3DBorder border;
3896
3897 border = Blt_TreeViewGetStyleBorder(tvPtr, tvPtr->stylePtr);
3898 Blt_Fill3DRectangle(tvPtr->tkwin, drawable, border, 0, 0, width, height,
3899 0, TK_RELIEF_FLAT);
3900 } else if (Blt_HasTile(tvPtr->tile) == 0 && Blt_HasTile(columnPtr->tile) == 0) {
3901
3902 Blt_Draw3DRectangle(tvPtr->tkwin, drawable, SELECT_BORDER(tvPtr), 0, 0,
3903 width, height, tvPtr->selBorderWidth, tvPtr->selRelief);
3904 }
3905 Blt_TreeViewDrawValue(tvPtr, entryPtr, valuePtr, drawable, 0, 0, entryPtr->flags & ENTRY_ALTROW, ishid);
3906
3907 /* Clip the drawable if necessary */
3908 sx = sy = 0;
3909 if (dx < left) {
3910 width -= left - dx;
3911 sx += left - dx;
3912 dx = left;
3913 }
3914 if ((dx + width) >= right) {
3915 width -= (dx + width) - right;
3916 }
3917 if (dy < top) {
3918 height -= top - dy;
3919 sy += top - dy;
3920 dy = top;
3921 }
3922 if ((dy + height) >= bottom) {
3923 height -= (dy + height) - bottom;
3924 }
3925 XCopyArea(tvPtr->display, drawable, Tk_WindowId(tvPtr->tkwin),
3926 tvPtr->lineGC, sx, sy, width, height, dx, dy);
3927 Tk_FreePixmap(tvPtr->display, drawable);
3928 }
3929
3930 /*
3931 *----------------------------------------------------------------------
3932 *
3933 * StyleActivateOp --
3934 *
3935 * Turns on/off highlighting for a particular style.
3936 *
3937 * .t style activate entry column
3938 *
3939 * Results:
3940 * A standard Tcl result. If TCL_ERROR is returned, then
3941 * interp->result contains an error message.
3942 *
3943 *----------------------------------------------------------------------
3944 */
3945 /*ARGSUSED*/
3946 static int
3947 StyleActivateOp(tvPtr, interp, objc, objv)
3948 TreeView *tvPtr;
3949
3950 Tcl_Interp *interp;
3951 int objc; /* Not used. */
3952 Tcl_Obj *CONST *objv;
3953 {
3954 TreeViewEntry *entryPtr;
3955 TreeViewValue *valuePtr, *oldPtr;
3956
3957 oldPtr = tvPtr->activeValuePtr;
3958 if (objc == 3) {
3959 Tcl_Obj *listObjPtr;
3960
3961 valuePtr = tvPtr->activeValuePtr;
3962 entryPtr = tvPtr->activePtr;
3963 listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
3964 if ((entryPtr != NULL) && (valuePtr != NULL)) {
3965 Tcl_Obj *objPtr;
3966 objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node));
3967 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
3968 objPtr = Tcl_NewStringObj(valuePtr->columnPtr->key, -1);
3969 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
3970 }
3971 Tcl_SetObjResult(interp, listObjPtr);
3972 return TCL_OK;
3973 } else if (objc == 4) {
3974 tvPtr->activeValuePtr = NULL;
3975 if ((oldPtr != NULL) && (tvPtr->activePtr != NULL)) {
3976 DrawValue(tvPtr, tvPtr->activePtr, oldPtr);
3977 }
3978 } else {
3979 TreeViewColumn *columnPtr;
3980
3981 if (Blt_TreeViewGetEntry(tvPtr, objv[3], &entryPtr) != TCL_OK) {
3982 return TCL_ERROR;
3983 }
3984
3985 if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr)
3986 != TCL_OK) {
3987 return TCL_ERROR;
3988 }
3989 valuePtr = Blt_TreeViewFindValue(entryPtr, columnPtr);
3990 if (valuePtr == NULL) {
3991 return TCL_OK;
3992 }
3993 tvPtr->activePtr = entryPtr;
3994 tvPtr->activeColumnPtr = columnPtr;
3995 oldPtr = tvPtr->activeValuePtr;
3996 tvPtr->activeValuePtr = valuePtr;
3997 if (valuePtr != oldPtr) {
3998 if (oldPtr != NULL) {
3999 DrawValue(tvPtr, entryPtr, oldPtr);
4000 }
4001 if (valuePtr != NULL) {
4002 DrawValue(tvPtr, entryPtr, valuePtr);
4003 }
4004 }
4005 }
4006 return TCL_OK;
4007 }
4008
4009
4010 /*
4011 *----------------------------------------------------------------------
4012 *
4013 * StyleCgetOp --
4014 *
4015 * .t style cget "styleName" -background
4016 *
4017 *----------------------------------------------------------------------
4018 */
4019 /*ARGSUSED*/
4020 static int
4021 StyleCgetOp(tvPtr, interp, objc, objv)
4022 TreeView *tvPtr;
4023 Tcl_Interp *interp;
4024 int objc; /* Not used. */
4025 Tcl_Obj *CONST *objv;
4026 {
4027 TreeViewStyle *stylePtr;
4028
4029 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4030 if (stylePtr == NULL) {
4031 return TCL_ERROR;
4032 }
4033 Blt_TreeViewOptsInit(tvPtr);
4034 return Blt_ConfigureValueFromObj(interp, tvPtr->tkwin,
4035 stylePtr->classPtr->specsPtr, (char *)stylePtr, objv[4], 0);
4036 }
4037
4038 /*
4039 *----------------------------------------------------------------------
4040 *
4041 * StyleCheckBoxOp --
4042 *
4043 * .t style checkbox "styleName" -background blue
4044 *
4045 *----------------------------------------------------------------------
4046 */
4047 /*ARGSUSED*/
4048 static int
4049 StyleCheckBoxOp(tvPtr, interp, objc, objv)
4050 TreeView *tvPtr;
4051 Tcl_Interp *interp;
4052 int objc; /* Not used. */
4053 Tcl_Obj *CONST *objv;
4054 {
4055 TreeViewStyle *stylePtr;
4056
4057 stylePtr = CreateStyle(interp, tvPtr, STYLE_CHECKBOX,
4058 Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4059 if (stylePtr == NULL) {
4060 return TCL_ERROR;
4061 }
4062 stylePtr->refCount = 0;
4063 stylePtr->flags |= STYLE_USER;
4064 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4065 Tcl_SetObjResult(interp, objv[3]);
4066 return TCL_OK;
4067 }
4068
4069
4070 /*
4071 *----------------------------------------------------------------------
4072 *
4073 * StyleComboBoxOp --
4074 *
4075 * .t style combobox "styleName" -background blue
4076 *
4077 *----------------------------------------------------------------------
4078 */
4079 /*ARGSUSED*/
4080 static int
4081 StyleComboBoxOp(tvPtr, interp, objc, objv)
4082 TreeView *tvPtr;
4083 Tcl_Interp *interp;
4084 int objc; /* Not used. */
4085 Tcl_Obj *CONST *objv;
4086 {
4087 TreeViewStyle *stylePtr;
4088
4089 stylePtr = CreateStyle(interp, tvPtr, STYLE_COMBOBOX,
4090 Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4091 if (stylePtr == NULL) {
4092 return TCL_ERROR;
4093 }
4094 stylePtr->refCount = 0;
4095 stylePtr->flags |= STYLE_USER;
4096 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4097 Tcl_SetObjResult(interp, objv[3]);
4098 return TCL_OK;
4099 }
4100
4101 /*
4102 *----------------------------------------------------------------------
4103 *
4104 * StyleConfigureOp --
4105 *
4106 * This procedure is called to process a list of configuration
4107 * options database, in order to reconfigure a style.
4108 *
4109 * .t style configure "styleName" option value
4110 *
4111 * Results:
4112 * A standard Tcl result. If TCL_ERROR is returned, then
4113 * interp->result contains an error message.
4114 *
4115 * Side effects:
4116 * Configuration information, such as text string, colors, font,
4117 * etc. get set for stylePtr; old resources get freed, if there
4118 * were any.
4119 *
4120 *----------------------------------------------------------------------
4121 */
4122 static int
4123 StyleConfigureOp(tvPtr, interp, objc, objv)
4124 TreeView *tvPtr;
4125 Tcl_Interp *interp;
4126 int objc;
4127 Tcl_Obj *CONST *objv;
4128 {
4129 TreeViewStyle *stylePtr;
4130
4131 if (Blt_TreeViewGetStyleMake(interp, tvPtr, Tcl_GetString(objv[3]), &stylePtr,
4132 NULL, NULL, NULL) != TCL_OK) {
4133 return TCL_ERROR;
4134 }
4135 stylePtr->refCount--;
4136
4137 Blt_TreeViewOptsInit(tvPtr);
4138 if (objc == 4) {
4139 return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin,
4140 stylePtr->classPtr->specsPtr, (char *)stylePtr, (Tcl_Obj *)NULL, 0);
4141 } else if (objc == 5) {
4142 return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin,
4143 stylePtr->classPtr->specsPtr, (char *)stylePtr, objv[4], 0);
4144 }
4145 if (Blt_ConfigureWidgetFromObj(interp, tvPtr->tkwin,
4146 stylePtr->classPtr->specsPtr, objc - 4, objv + 4, (char *)stylePtr,
4147 BLT_CONFIG_OBJV_ONLY, NULL) != TCL_OK) {
4148 return TCL_ERROR;
4149 }
4150 if (stylePtr->tile != NULL) {
4151 Blt_SetTileChangedProc(stylePtr->tile, Blt_TreeViewTileChangedProc, tvPtr);
4152 }
4153 if (stylePtr->fillTile != NULL) {
4154 Blt_SetTileChangedProc(stylePtr->fillTile, Blt_TreeViewTileChangedProc, tvPtr);
4155 }
4156 (*stylePtr->classPtr->configProc)(tvPtr, stylePtr);
4157 Blt_TreeViewMakeStyleDirty(tvPtr);
4158 Blt_TreeViewEventuallyRedraw(tvPtr);
4159 return TCL_OK;
4160 }
4161
4162 /*
4163 *----------------------------------------------------------------------
4164 *
4165 * StyleForgetOp --
4166 *
4167 * Eliminates one or more style names whose
4168 * reference count is zero (i.e. no one else is using it).
4169 *
4170 * .t style forget "styleName"...
4171 *
4172 * Results:
4173 * A standard Tcl result. If TCL_ERROR is returned, then
4174 * interp->result contains an error message.
4175 *
4176 *----------------------------------------------------------------------
4177 */
4178 static int
4179 StyleForgetOp(tvPtr, interp, objc, objv)
4180 TreeView *tvPtr;
4181
4182 Tcl_Interp *interp;
4183 int objc;
4184 Tcl_Obj *CONST *objv;
4185 {
4186 TreeViewStyle *stylePtr;
4187 int i;
4188
4189 for (i = 3; i < objc; i++) {
4190 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[i]));
4191 if (stylePtr == NULL) {
4192 return TCL_ERROR;
4193 }
4194 if (stylePtr->refCount > 1 || stylePtr == tvPtr->stylePtr) {
4195 continue;
4196 }
4197 if (stylePtr->hashPtr != NULL) {
4198 Blt_DeleteHashEntry(&tvPtr->styleTable, stylePtr->hashPtr);
4199 stylePtr->hashPtr = NULL;
4200 }
4201 stylePtr->refCount--;
4202 stylePtr->flags &= ~STYLE_USER;
4203 Blt_TreeViewFreeStyle(tvPtr, stylePtr);
4204 }
4205 Blt_TreeViewEventuallyRedraw(tvPtr);
4206 return TCL_OK;
4207 }
4208
4209 static int
4210 StyleUseOp(tvPtr, interp, objc, objv)
4211 TreeView *tvPtr;
4212
4213 Tcl_Interp *interp;
4214 int objc;
4215 Tcl_Obj *CONST *objv;
4216 {
4217 TreeViewStyle *stylePtr;
4218
4219 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4220 if (stylePtr == NULL) {
4221 return TCL_ERROR;
4222 }
4223 Tcl_SetObjResult(interp, Tcl_NewIntObj(stylePtr->refCount-1));
4224 return TCL_OK;
4225 }
4226
4227
4228 static int StyleLookup(char *string) {
4229 if (!strcmp(string, "combobox")) {
4230 return STYLE_COMBOBOX;
4231 }
4232 if (!strcmp(string, "textbox")) {
4233 return STYLE_TEXTBOX;
4234 }
4235 if (!strcmp(string, "barbox")) {
4236 return STYLE_BARBOX;
4237 }
4238 if (!strcmp(string, "windowbox")) {
4239 return STYLE_WINDOWBOX;
4240 }
4241 if (!strcmp(string, "checkbox")) {
4242 return STYLE_CHECKBOX;
4243 }
4244 return -1;
4245 }
4246
4247 /*
4248 *----------------------------------------------------------------------
4249 *
4250 * StyleTypeOp --
4251 *
4252 * Return the type of a style.
4253 *
4254 * .t style type "styleName"...
4255 *
4256 * Results:
4257 * A standard Tcl result. If TCL_ERROR is returned, then
4258 * interp->result contains an error message.
4259 *
4260 *----------------------------------------------------------------------
4261 */
4262 static int
4263 StyleTypeOp(tvPtr, interp, objc, objv)
4264 TreeView *tvPtr;
4265
4266 Tcl_Interp *interp;
4267 int objc;
4268 Tcl_Obj *CONST *objv;
4269 {
4270 TreeViewStyle *stylePtr, *newStylePtr;
4271 TreeViewAllStyles all;
4272 const char *cp;
4273 char *newType;
4274 int nType;
4275
4276 if (objc == 3) {
4277 cp = "textbox combobox checkbox barbox windowbox";
4278 Tcl_AppendResult(interp, cp, 0);
4279 return TCL_OK;
4280 }
4281 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4282 if (stylePtr == NULL) {
4283 return TCL_ERROR;
4284 }
4285 if (stylePtr->flags & STYLE_CHECKBOX) {
4286 cp = "checkbox";
4287 } else if (stylePtr->flags & STYLE_COMBOBOX) {
4288 cp = "combobox";
4289 } else if (stylePtr->flags & STYLE_WINDOWBOX) {
4290 cp = "windowbox";
4291 } else if (stylePtr->flags & STYLE_BARBOX) {
4292 cp = "barbox";
4293 } else {
4294 cp = "textbox";
4295 }
4296
4297 if (objc == 4) {
4298 Tcl_AppendResult(interp, cp, 0);
4299 return TCL_OK;
4300 }
4301 if (!strcmp(stylePtr->name, "text")) {
4302 Tcl_AppendResult(interp, "can not change type of style \"text\"", 0);
4303 return TCL_ERROR;
4304 }
4305 newType = Tcl_GetString(objv[4]);
4306 nType = StyleLookup( newType );
4307 if (nType<0) {
4308 Tcl_AppendResult(interp, "unknown type: ", newType, 0);
4309 return TCL_ERROR;
4310 }
4311 /* if (!strcmp(newType, cp)) {
4312 return TCL_OK;
4313 }*/
4314 /* Change the style */
4315 newStylePtr = CreateStyle(interp, tvPtr, nType, "__%%StyleTypeSet%%_", 0, 0, 0);
4316 if (newStylePtr == NULL) {
4317 return TCL_ERROR;
4318 }
4319 newStylePtr->flags |= STYLE_USER;
4320 memcpy(&all, stylePtr, sizeof(all));
4321 memcpy(stylePtr, newStylePtr, sizeof(all));
4322 memcpy(newStylePtr, &all, sizeof(all));
4323 newStylePtr->refCount = stylePtr->refCount;
4324 stylePtr->refCount = all.tb.refCount ;
4325 newStylePtr->hashPtr = stylePtr->hashPtr;
4326 stylePtr->hashPtr = all.tb.hashPtr ;
4327 newStylePtr->name = stylePtr->name;
4328 stylePtr->name = all.tb.name ;
4329
4330 newStylePtr->flags &= ~STYLE_USER;
4331 Blt_TreeViewFreeStyle(tvPtr, newStylePtr);
4332 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4333 tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_UPDATE);
4334 Blt_TreeViewMakeStyleDirty(tvPtr);
4335 Blt_TreeViewEventuallyRedraw(tvPtr);
4336 return TCL_OK;
4337 }
4338
4339 /*
4340 *----------------------------------------------------------------------
4341 *
4342 * StyleHighlightOp --
4343 *
4344 * Turns on/off highlighting for a particular style.
4345 *
4346 * .t style highlight styleName ?on|off?
4347 *
4348 * Results:
4349 * A standard Tcl result. If TCL_ERROR is returned, then
4350 * interp->result contains an error message.
4351 *
4352 *----------------------------------------------------------------------
4353 */
4354 /*ARGSUSED*/
4355 static int
4356 StyleHighlightOp(tvPtr, interp, objc, objv)
4357 TreeView *tvPtr;
4358
4359 Tcl_Interp *interp;
4360 int objc; /* Not used. */
4361 Tcl_Obj *CONST *objv;
4362 {
4363 TreeViewStyle *stylePtr;
4364 int bool, oldBool;
4365
4366 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4367 if (stylePtr == NULL) {
4368 return TCL_ERROR;
4369 }
4370 oldBool = ((stylePtr->flags & STYLE_HIGHLIGHT) != 0);
4371 if (objc<=4) {
4372 Tcl_SetObjResult(interp, Tcl_NewIntObj(oldBool));
4373 return TCL_OK;
4374 }
4375 if (Tcl_GetBooleanFromObj(interp, objv[4], &bool) != TCL_OK) {
4376 return TCL_ERROR;
4377 }
4378 if (oldBool != bool) {
4379 if (bool) {
4380 stylePtr->flags |= STYLE_HIGHLIGHT;
4381 } else {
4382 stylePtr->flags &= ~STYLE_HIGHLIGHT;
4383 }
4384 Blt_TreeViewEventuallyRedraw(tvPtr);
4385 }
4386 return TCL_OK;
4387 }
4388
4389 /*
4390 *----------------------------------------------------------------------
4391 *
4392 * StyleNamesOp --
4393 *
4394 * Lists the names of all the current styles in the treeview widget.
4395 *
4396 * .t style names
4397 *
4398 * Results:
4399 * Always TCL_OK.
4400 *
4401 *----------------------------------------------------------------------
4402 */
4403 /*ARGSUSED*/
4404 static int
4405 StyleNamesOp(tvPtr, interp, objc, objv)
4406 TreeView *tvPtr;
4407
4408 Tcl_Interp *interp;
4409 int objc; /* Not used. */
4410 Tcl_Obj *CONST *objv; /* Not used. */
4411 {
4412 Blt_HashEntry *hPtr;
4413 Blt_HashSearch cursor;
4414 Tcl_Obj *listObjPtr, *objPtr;
4415 TreeViewStyle *stylePtr;
4416
4417 listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
4418 for (hPtr = Blt_FirstHashEntry(&tvPtr->styleTable, &cursor); hPtr != NULL;
4419 hPtr = Blt_NextHashEntry(&cursor)) {
4420 stylePtr = Blt_GetHashValue(hPtr);
4421 objPtr = Tcl_NewStringObj(stylePtr->name, -1);
4422 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4423 }
4424 Tcl_SetObjResult(interp, listObjPtr);
4425 return TCL_OK;
4426 }
4427
4428 static int
4429 StyleSlavesOp(tvPtr, interp, objc, objv)
4430 TreeView *tvPtr;
4431
4432 Tcl_Interp *interp;
4433 int objc;
4434 Tcl_Obj *CONST *objv;
4435 {
4436 Blt_HashEntry *hPtr;
4437 Blt_HashSearch cursor;
4438 char *name, *window = NULL;
4439 Tcl_DString dStr;
4440 TreeViewColumn *columnPtr = NULL;
4441 TreeViewEntry *entryPtr = NULL;
4442 TreeViewStyle *stylePtr = NULL;
4443 int visible;
4444 WindowCell *wcPtr;
4445 int sub = 0, chkVis = 0;
4446
4447 if (!(objc%2)) {
4448 goto argerr;
4449 }
4450 while (objc>3) {
4451 char *string;
4452
4453 string = Tcl_GetString(objv[3]);
4454 if (string[0] != '-') {
4455 argerr:
4456 Tcl_AppendResult(interp, "expected -col, -id, -style, -visible, or -info", 0);
4457 return TCL_ERROR;
4458 }
4459 if ((strcmp(string, "-col") == 0)) {
4460 if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr)
4461 != TCL_OK) {
4462 return TCL_ERROR;
4463 }
4464 } else if ((strcmp(string, "-info") == 0)) {
4465
4466 window = Tcl_GetString(objv[4]);
4467
4468 } else if ((strcmp(string, "-id") == 0)) {
4469 if (Blt_TreeViewGetEntry(tvPtr, objv[4], &entryPtr)
4470 != TCL_OK) {
4471 return TCL_ERROR;
4472 }
4473 } else if ((strcmp(string, "-visible") == 0)) {
4474 if (Tcl_GetBooleanFromObj(interp, objv[4], &visible) != TCL_OK) {
4475 return TCL_ERROR;
4476 }
4477 chkVis = 1;
4478 } else if ((strcmp(string, "-style") == 0)) {
4479 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[4]));
4480 if (stylePtr == NULL) {
4481 return TCL_ERROR;
4482 }
4483 } else break;
4484
4485 objc -= 2;
4486 objv += 2;
4487 sub++;
4488 }
4489 if (objc != 3) {
4490 goto argerr;
4491 }
4492
4493
4494 Tcl_DStringInit(&dStr);
4495 for (hPtr = Blt_FirstHashEntry(&tvPtr->winTable, &cursor); hPtr != NULL;
4496 hPtr = Blt_NextHashEntry(&cursor)) {
4497 name = (char*)Blt_GetHashKey(&tvPtr->winTable, hPtr);
4498 if (sub) {
4499 wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
4500 if (wcPtr == NULL) continue;
4501 if (columnPtr && columnPtr != wcPtr->columnPtr) continue;
4502 if (entryPtr && entryPtr != wcPtr->entryPtr) continue;
4503 if (stylePtr && stylePtr != (TreeViewStyle*)wcPtr->stylePtr) continue;
4504 if (chkVis) {
4505 if (wcPtr->flags&TV_WINDOW_DRAW) {
4506 if (!visible) continue;
4507 } else {
4508 if (visible) continue;
4509 }
4510 }
4511 if (window) {
4512 if (wcPtr->tkwin == NULL) continue;
4513 if (strcmp(window,Tk_PathName(wcPtr->tkwin))) continue;
4514 Tcl_DStringAppendElement(&dStr, "-style");
4515 Tcl_DStringAppendElement(&dStr, wcPtr->stylePtr->name);
4516 Tcl_DStringAppendElement(&dStr, "-col");
4517 Tcl_DStringAppendElement(&dStr, wcPtr->columnPtr->key);
4518 Tcl_DStringAppendElement(&dStr, "-id");
4519 Tcl_DStringAppendElement(&dStr, Blt_Itoa(Blt_TreeNodeId(wcPtr->entryPtr->node)));
4520 Tcl_DStringAppendElement(&dStr, "-visible");
4521 Tcl_DStringAppendElement(&dStr, (wcPtr->flags&TV_WINDOW_DRAW)?"True":"False");
4522 Tcl_DStringResult(interp, &dStr);
4523 return TCL_OK;
4524 }
4525 }
4526 if (name != NULL) {
4527 Tcl_DStringAppendElement(&dStr, name);
4528 }
4529 }
4530 Tcl_DStringResult(interp, &dStr);
4531 return TCL_OK;
4532 }
4533
4534 /*
4535 *----------------------------------------------------------------------
4536 *
4537 * StyleSetOp --
4538 *
4539 * Sets a style for a given key for all the ids given.
4540 *
4541 * .t style set styleName column node...
4542 *
4543 * Results:
4544 * A standard Tcl result. If TCL_ERROR is returned, then
4545 * interp->result contains an error message.
4546 *
4547 *----------------------------------------------------------------------
4548 */
4549 static int
4550 StyleSetOp(tvPtr, interp, objc, objv)
4551 TreeView *tvPtr;
4552
4553 Tcl_Interp *interp;
4554 int objc;
4555 Tcl_Obj *CONST *objv;
4556 {
4557 TreeViewColumn *columnPtr;
4558 TreeViewEntry *entryPtr;
4559 TreeViewStyle *stylePtr = NULL, *oldStylePtr;
4560 TreeViewTagInfo info = {0};
4561 char *string;
4562 int i, count;
4563
4564 count = 0;
4565 if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr) != TCL_OK) {
4566 return TCL_ERROR;
4567 }
4568 string = Tcl_GetString(objv[3]);
4569 if (string[0]) {
4570 if (Blt_TreeViewGetStyleMake(interp, tvPtr, string, &stylePtr, columnPtr,
4571 NULL, NULL) != TCL_OK) {
4572 return TCL_ERROR;
4573 }
4574 stylePtr->refCount--;
4575 }
4576 if (stylePtr) {
4577 stylePtr->flags |= STYLE_LAYOUT;
4578 }
4579 for (i = 5; i < objc; i++) {
4580 if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[i], &info) != TCL_OK) {
4581 return TCL_ERROR;
4582 }
4583 for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL;
4584 entryPtr = Blt_TreeViewNextTaggedEntry(&info)) {
4585 register TreeViewValue *valuePtr;
4586
4587 if (columnPtr == &tvPtr->treeColumn) {
4588 if (stylePtr == entryPtr->realStylePtr) continue;
4589 if (stylePtr) stylePtr->refCount++;
4590 oldStylePtr = entryPtr->realStylePtr;
4591 entryPtr->realStylePtr = stylePtr;
4592 if (stylePtr) stylePtr->refCount++;
4593 if (oldStylePtr != NULL) {
4594 Blt_TreeViewFreeStyle(tvPtr, oldStylePtr);
4595 }
4596 count++;
4597 continue;
4598 }
4599
4600 for (valuePtr = entryPtr->values; valuePtr != NULL;
4601 valuePtr = valuePtr->nextPtr) {
4602 if (valuePtr->columnPtr == columnPtr) {
4603 if (stylePtr == valuePtr->stylePtr) break;
4604 if (stylePtr) stylePtr->refCount++;
4605 oldStylePtr = valuePtr->stylePtr;
4606 valuePtr->stylePtr = stylePtr;
4607 if (stylePtr) stylePtr->refCount++;
4608 if (oldStylePtr != NULL) {
4609 Blt_TreeViewFreeStyle(tvPtr, oldStylePtr);
4610 }
4611 count++;
4612 break;
4613 }
4614 }
4615 }
4616 Blt_TreeViewDoneTaggedEntries(&info);
4617 }
4618 tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_UPDATE);
4619 Blt_TreeViewMakeStyleDirty(tvPtr);
4620 Blt_TreeViewEventuallyRedraw(tvPtr);
4621 Tcl_SetObjResult(interp, Tcl_NewIntObj(count));
4622 return TCL_OK;
4623 }
4624
4625 /*
4626 *----------------------------------------------------------------------
4627 *
4628 * StyleFindOp --
4629 *
4630 * Find all entries with the given style.
4631 * If a column is given, find entries with the given style in that column.
4632 *
4633 * .t style find styleName ?tagorid? ?column?
4634 *
4635 * Results:
4636 * A standard Tcl result. If TCL_ERROR is returned, then
4637 * interp->result contains an error message.
4638 *
4639 *----------------------------------------------------------------------
4640 */
4641 static int
4642 StyleFindOp(tvPtr, interp, objc, objv)
4643 TreeView *tvPtr;
4644
4645 Tcl_Interp *interp;
4646 int objc;
4647 Tcl_Obj *CONST *objv;
4648 {
4649 TreeViewEntry *entryPtr;
4650 TreeViewStyle *stylePtr;
4651 TreeViewTagInfo info = {0};
4652 TreeViewColumn *columnPtr = NULL;
4653 Tcl_Obj *listObjPtr, *objPtr;
4654
4655 if (tvPtr->styleCmd == NULL || strcmp(tvPtr->styleCmd, "%W style create textbox %V")) {
4656 stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4657 if (stylePtr == NULL) {
4658 return TCL_ERROR;
4659 }
4660 } else {
4661 stylePtr = GetStyle(NULL, tvPtr, Tcl_GetString(objv[3]));
4662 if (stylePtr == NULL) {
4663 return TCL_OK;
4664 }
4665 }
4666 if (objc>5) {
4667 if (Blt_TreeViewGetColumn(interp, tvPtr, objv[5], &columnPtr) != TCL_OK) {
4668 return TCL_ERROR;
4669 }
4670 }
4671 if (objc>4) {
4672 if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[4], &info) != TCL_OK) {
4673 return TCL_ERROR;
4674 }
4675 } else {
4676 objPtr = Tcl_NewStringObj("all", -1);
4677 if (Blt_TreeViewFindTaggedEntries(tvPtr, objPtr, &info) != TCL_OK) {
4678 Tcl_DecrRefCount(objPtr);
4679 return TCL_ERROR;
4680 }
4681 Tcl_DecrRefCount(objPtr);
4682 }
4683
4684 listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
4685 for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL;
4686 entryPtr = Blt_TreeViewNextTaggedEntry(&info)) {
4687 register TreeViewValue *valuePtr;
4688
4689 if (columnPtr == NULL || columnPtr == &tvPtr->treeColumn) {
4690 if (entryPtr->realStylePtr == stylePtr) {
4691 objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node));
4692 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4693 continue;
4694 }
4695 }
4696
4697 for (valuePtr = entryPtr->values; valuePtr != NULL;
4698 valuePtr = valuePtr->nextPtr) {
4699 if (columnPtr && valuePtr->columnPtr != columnPtr) continue;
4700 if (valuePtr->stylePtr != stylePtr) continue;
4701 objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node));
4702 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4703 break;
4704 }
4705 }
4706 Blt_TreeViewDoneTaggedEntries(&info);
4707 Tcl_SetObjResult(interp, listObjPtr);
4708 return TCL_OK;
4709 }
4710
4711 /*
4712 *----------------------------------------------------------------------
4713 *
4714 * StyleTextBoxOp --
4715 *
4716 * .t style textbox "styleName" -background blue
4717 *
4718 *----------------------------------------------------------------------
4719 */
4720 /*ARGSUSED*/
4721 static int
4722 StyleTextBoxOp(tvPtr, interp, objc, objv)
4723 TreeView *tvPtr;
4724 Tcl_Interp *interp;
4725 int objc; /* Not used. */
4726 Tcl_Obj *CONST *objv;
4727 {
4728 TreeViewStyle *stylePtr;
4729
4730 stylePtr = CreateStyle(interp, tvPtr, STYLE_TEXTBOX,
4731 Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4732 if (stylePtr == NULL) {
4733 return TCL_ERROR;
4734 }
4735 stylePtr->refCount = 0;
4736 stylePtr->flags |= STYLE_USER;
4737 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4738 Tcl_SetObjResult(interp, objv[3]);
4739 return TCL_OK;
4740 }
4741
4742 /*
4743 *----------------------------------------------------------------------
4744 *
4745 * StyleWindowBoxOp --
4746 *
4747 * .t style window "styleName"
4748 *
4749 *----------------------------------------------------------------------
4750 */
4751 /*ARGSUSED*/
4752 static int
4753 StyleWindowBoxOp(tvPtr, interp, objc, objv)
4754 TreeView *tvPtr;
4755 Tcl_Interp *interp;
4756 int objc; /* Not used. */
4757 Tcl_Obj *CONST *objv;
4758 {
4759 TreeViewStyle *stylePtr;
4760
4761 stylePtr = CreateStyle(interp, tvPtr, STYLE_WINDOWBOX,
4762 Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4763 if (stylePtr == NULL) {
4764 return TCL_ERROR;
4765 }
4766 stylePtr->refCount = 0;
4767 stylePtr->flags |= STYLE_USER;
4768 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4769 Tcl_SetObjResult(interp, objv[3]);
4770 return TCL_OK;
4771 }
4772 /*
4773 *----------------------------------------------------------------------
4774 *
4775 * StyleBarBoxOp --
4776 *
4777 * .t style textbox "styleName" -background blue
4778 *
4779 *----------------------------------------------------------------------
4780 */
4781 /*ARGSUSED*/
4782 static int
4783 StyleBarBoxOp(tvPtr, interp, objc, objv)
4784 TreeView *tvPtr;
4785 Tcl_Interp *interp;
4786 int objc; /* Not used. */
4787 Tcl_Obj *CONST *objv;
4788 {
4789 TreeViewStyle *stylePtr;
4790
4791 stylePtr = CreateStyle(interp, tvPtr, STYLE_BARBOX,
4792 Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4793 if (stylePtr == NULL) {
4794 return TCL_ERROR;
4795 }
4796 stylePtr->refCount = 0;
4797 stylePtr->flags |= STYLE_USER;
4798 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4799 Tcl_SetObjResult(interp, objv[3]);
4800 return TCL_OK;
4801 }
4802
4803
4804 /*
4805 *----------------------------------------------------------------------
4806 *
4807 * StyleGetOp --
4808 *
4809 * Get style set for each given key for the id given.
4810 *
4811 * .t style get column tagorid
4812 *
4813 * Results:
4814 * A standard Tcl result. If TCL_ERROR is returned, then
4815 * interp->result contains an error message.
4816 *
4817 *----------------------------------------------------------------------
4818 */
4819 static int
4820 StyleGetOp(tvPtr, interp, objc, objv)
4821 TreeView *tvPtr;
4822 Tcl_Interp *interp;
4823 int objc;
4824 Tcl_Obj *CONST *objv;
4825 {
4826 TreeViewColumn *columnPtr;
4827 TreeViewEntry *entryPtr;
4828 TreeViewTagInfo info = {0};
4829 Tcl_Obj *listObjPtr, *objPtr;
4830
4831 if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr) != TCL_OK) {
4832 return TCL_ERROR;
4833 }
4834
4835 if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[4], &info) != TCL_OK) {
4836 return TCL_ERROR;
4837 }
4838 listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
4839 for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL;
4840 entryPtr = Blt_TreeViewNextTaggedEntry(&info)) {
4841 register TreeViewValue *valuePtr;
4842
4843 if (columnPtr == &tvPtr->treeColumn) {
4844 if (entryPtr->realStylePtr != NULL) {
4845 objPtr = Tcl_NewStringObj(entryPtr->realStylePtr->name, -1);
4846 } else {
4847 objPtr = Tcl_NewStringObj("",0);
4848 }
4849 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4850 continue;
4851 }
4852
4853 for (valuePtr = entryPtr->values; valuePtr != NULL;
4854 valuePtr = valuePtr->nextPtr) {
4855 if (valuePtr->columnPtr == columnPtr) {
4856 if (valuePtr->stylePtr != NULL) {
4857 objPtr = Tcl_NewStringObj(valuePtr->stylePtr->name, -1);
4858 } else {
4859 objPtr = Tcl_NewStringObj("",0);
4860 }
4861 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4862 break;
4863 }
4864 }
4865 }
4866 Blt_TreeViewDoneTaggedEntries(&info);
4867 Tcl_SetObjResult(interp, listObjPtr);
4868 return TCL_OK;
4869 }
4870
4871 #if 0
4872 /*
4873 *----------------------------------------------------------------------
4874 *
4875 * StylePriorityOp --
4876 *
4877 * Get style with highest priority for given key for the id given.
4878 *
4879 * .t style priority column tagorid
4880 *
4881 * Results:
4882 * A standard Tcl result. If TCL_ERROR is returned, then
4883 * interp->result contains an error message.
4884 *
4885 *----------------------------------------------------------------------
4886 */
4887 static int
4888 StylePriorityOp(tvPtr, interp, objc, objv)
4889 TreeView *tvPtr;
4890 Tcl_Interp *interp;
4891 int objc;
4892 Tcl_Obj *CONST *objv;
4893 {
4894 TreeViewColumn *columnPtr;
4895 TreeViewEntry *entryPtr;
4896 TreeViewValue *valuePtr;
4897 TreeViewStyle *s[4];
4898 int i, h = -1, p = -1;
4899
4900 s[3] = tvPtr->stylePtr;
4901
4902 if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr) != TCL_OK) {
4903 return TCL_ERROR;
4904 }
4905
4906 if (Blt_TreeViewGetEntry(tvPtr, objv[4], &entryPtr) != TCL_OK) {
4907 return TCL_ERROR;
4908 }
4909
4910 if (columnPtr == &tvPtr->treeColumn) {
4911 s[0] = entryPtr->realStylePtr;
4912 } else {
4913 s[0] = NULL;
4914 for (valuePtr = entryPtr->values; valuePtr != NULL;
4915 valuePtr = valuePtr->nextPtr) {
4916 if (valuePtr->columnPtr == columnPtr) {
4917 s[0] = valuePtr->stylePtr;
4918 break;
4919 }
4920 }
4921 }
4922 s[1] = entryPtr->stylePtr;
4923 s[2] = columnPtr->stylePtr;
4924 for (i=0; i<4; i++) {
4925 if (s[i]==0) continue;
4926 if (h<0) { h = i; }
4927 if (s[i]->priority > p) {
4928 h = i;
4929 p = s[i]->priority;
4930 }
4931 }
4932 Tcl_SetObjResult(interp, Tcl_NewStringObj(s[h]->name, -1));
4933 return TCL_OK;
4934 }
4935 #endif
4936 /*
4937 *----------------------------------------------------------------------
4938 *
4939 * StyleCreateOp --
4940 *
4941 * .t style create "styleType" "styleName" -background blue
4942 *
4943 *----------------------------------------------------------------------
4944 */
4945 /*ARGSUSED*/
4946 static int
4947 StyleCreateOp(tvPtr, interp, objc, objv)
4948 TreeView *tvPtr;
4949 Tcl_Interp *interp;
4950 int objc; /* Not used. */
4951 Tcl_Obj *CONST *objv;
4952 {
4953 char *string;
4954
4955 string = Tcl_GetString(objv[3]);
4956 if (!strcmp(string, "combobox")) {
4957 return StyleComboBoxOp(tvPtr, interp, objc-1, objv+1);
4958 }
4959 if (!strcmp(string, "textbox")) {
4960 return StyleTextBoxOp(tvPtr, interp, objc-1, objv+1);
4961 }
4962 if (!strcmp(string, "barbox")) {
4963 return StyleBarBoxOp(tvPtr, interp, objc-1, objv+1);
4964 }
4965 if (!strcmp(string, "windowbox")) {
4966 return StyleWindowBoxOp(tvPtr, interp, objc-1, objv+1);
4967 }
4968 if (!strcmp(string, "checkbox")) {
4969 return StyleCheckBoxOp(tvPtr, interp, objc-1, objv+1);
4970 }
4971 Tcl_AppendResult(interp, "bad style type \"", string, "\", should be one of: textbox, barbox, checkbox, combobox, or windowbox", 0);
4972 return TCL_ERROR;
4973 }
4974
4975 /*
4976 *----------------------------------------------------------------------
4977 *
4978 * StyleOp --
4979 *
4980 * .t style activate $node $column
4981 * .t style activate
4982 * .t style cget "highlight" -foreground
4983 * .t style configure "highlight" -fg blue -bg green
4984 * .t style checkbox "highlight"
4985 * .t style highlight "highlight" on|off
4986 * .t style combobox "highlight"
4987 * .t style text "highlight"
4988 * .t style forget "highlight"
4989 * .t style get "mtime" $node
4990 * .t style names
4991 * .t style set "highlight" "mtime" all
4992 * .t style unset "mtime" all
4993 *
4994 *----------------------------------------------------------------------
4995 */
4996 static Blt_OpSpec styleOps[] = {
4997 {"activate", 1, (Blt_Op)StyleActivateOp, 3, 5,"?entry column?",},
4998 /*{"barbox", 2, (Blt_Op)StyleBarBoxOp, 4, 0, "styleName options...",},*/
4999 {"cget", 2, (Blt_Op)StyleCgetOp, 5, 5, "styleName option",},
5000 /*{"checkbox", 2, (Blt_Op)StyleCheckBoxOp, 4, 0, "styleName options...",},
5001 {"combobox", 3, (Blt_Op)StyleComboBoxOp, 4, 0, "styleName options...",},*/
5002 {"configure", 3, (Blt_Op)StyleConfigureOp, 4, 0, "styleName options...",},
5003 {"create", 2, (Blt_Op)StyleCreateOp, 5, 0, "type styleName options...",},
5004 {"find", 2, (Blt_Op)StyleFindOp, 4, 6, "styleName ?tagOrId? ?column?",},
5005 {"forget", 2, (Blt_Op)StyleForgetOp, 3, 0, "styleName...",},
5006 {"get", 1, (Blt_Op)StyleGetOp, 5, 5, "column tagOrId",},
5007 {"highlight", 1, (Blt_Op)StyleHighlightOp, 4, 5, "styleName ?boolean?",},
5008 {"names", 1, (Blt_Op)StyleNamesOp, 3, 3, "",},
5009 /*{"priority", 1, (Blt_Op)StylePriorityOp, 5, 5, "column tagOrId",}, */
5010 {"set", 2, (Blt_Op)StyleSetOp, 6, 0, "styleName column tagOrId ...",},
5011 {"slaves", 2, (Blt_Op)StyleSlavesOp, 3, 0, "?-col col? ?-entry id? ?-style name? ?-visible bool? ?-info win?",},
5012 /*{"textbox", 2, (Blt_Op)StyleTextBoxOp, 4, 0, "styleName options...",}, */
5013 {"type", 2, (Blt_Op)StyleTypeOp, 3, 5, "?styleName? ?newType?",},
5014 {"use", 2, (Blt_Op)StyleUseOp, 4, 4, "styleName",},
5015 /*{"windowbox", 2, (Blt_Op)StyleWindowBoxOp, 4, 0, "styleName options...",},*/
5016 };
5017
5018 static int nStyleOps = sizeof(styleOps) / sizeof(Blt_OpSpec);
5019
5020 int
5021 Blt_TreeViewStyleOp(tvPtr, interp, objc, objv)
5022 TreeView *tvPtr;
5023 Tcl_Interp *interp;
5024 int objc;
5025 Tcl_Obj *CONST *objv;
5026 {
5027 Blt_Op proc;
5028 int result;
5029
5030 proc = Blt_GetOpFromObj(interp, nStyleOps, styleOps, BLT_OP_ARG2, objc,
5031 objv, 0);
5032 if (proc == NULL) {
5033 return TCL_ERROR;
5034 }
5035 result = (*proc)(tvPtr, interp, objc, objv);
5036 return result;
5037 }
5038 #endif /* NO_TREEVIEW */
5039