[175] | 1 |
|
---|
| 2 | /*
|
---|
| 3 | * bltTreeViewColumn.c --
|
---|
| 4 | *
|
---|
| 5 | * This module implements an hierarchy widget for the BLT toolkit.
|
---|
| 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 | */
|
---|
| 29 |
|
---|
| 30 | /*
|
---|
| 31 | * TODO:
|
---|
| 32 | *
|
---|
| 33 | * BUGS:
|
---|
| 34 | * 1. "open" operation should change scroll offset so that as many
|
---|
| 35 | * new entries (up to half a screen) can be seen.
|
---|
| 36 | * 2. "open" needs to adjust the scrolloffset so that the same entry
|
---|
| 37 | * is seen at the same place.
|
---|
| 38 | */
|
---|
| 39 | #include "bltInt.h"
|
---|
| 40 |
|
---|
| 41 | #ifndef NO_TREEVIEW
|
---|
| 42 |
|
---|
| 43 | #include "bltTreeView.h"
|
---|
| 44 | #include <X11/Xutil.h>
|
---|
| 45 |
|
---|
| 46 | #define RULE_AREA (8)
|
---|
| 47 |
|
---|
| 48 | static Blt_OptionParseProc ObjToColumn;
|
---|
| 49 | static Blt_OptionPrintProc ColumnToObj;
|
---|
| 50 | static Blt_OptionParseProc ObjToData;
|
---|
| 51 | static Blt_OptionPrintProc DataToObj;
|
---|
| 52 |
|
---|
| 53 | static char *sortTypeStrings[] = {
|
---|
| 54 | "dictionary", "ascii", "integer", "real", "command", "none", NULL
|
---|
| 55 | };
|
---|
| 56 |
|
---|
| 57 | enum SortTypeValues {
|
---|
| 58 | SORT_TYPE_DICTIONARY, SORT_TYPE_ASCII, SORT_TYPE_INTEGER,
|
---|
| 59 | SORT_TYPE_REAL, SORT_TYPE_COMMAND, SORT_TYPE_NONE
|
---|
| 60 | };
|
---|
| 61 |
|
---|
| 62 | #define DEF_SORT_COLUMN (char *)NULL
|
---|
| 63 | #define DEF_SORT_COMMAND (char *)NULL
|
---|
| 64 | #define DEF_SORT_DECREASING "no"
|
---|
| 65 | #define DEF_SORT_TYPE "dictionary"
|
---|
| 66 |
|
---|
| 67 | #ifdef WIN32
|
---|
| 68 | #define DEF_COLUMN_ACTIVE_TITLE_BG RGB_GREY85
|
---|
| 69 | #else
|
---|
| 70 | #define DEF_COLUMN_ACTIVE_TITLE_BG RGB_GREY90
|
---|
| 71 | #endif
|
---|
| 72 | #define DEF_COLUMN_ACTIVE_TITLE_FG STD_ACTIVE_FOREGROUND
|
---|
| 73 | #define DEF_COLUMN_BACKGROUND (char *)NULL
|
---|
| 74 | #define DEF_COLUMN_BIND_TAGS "all"
|
---|
| 75 | #define DEF_COLUMN_BORDERWIDTH STD_BORDERWIDTH
|
---|
| 76 | #define DEF_COLUMN_COLOR RGB_BLACK
|
---|
| 77 | #define DEF_COLUMN_EDIT "yes"
|
---|
| 78 | #define DEF_COLUMN_FONT STD_FONT
|
---|
| 79 | #define DEF_COLUMN_COMMAND (char *)NULL
|
---|
| 80 | #define DEF_COLUMN_FORMAT_COMMAND (char *)NULL
|
---|
| 81 | #define DEF_COLUMN_HIDE "no"
|
---|
| 82 | #define DEF_COLUMN_JUSTIFY "center"
|
---|
| 83 | #define DEF_COLUMN_MAX "0"
|
---|
| 84 | #define DEF_COLUMN_MIN "0"
|
---|
| 85 | #define DEF_COLUMN_PAD "2"
|
---|
| 86 | #define DEF_COLUMN_RELIEF "flat"
|
---|
| 87 | #define DEF_COLUMN_STATE "normal"
|
---|
| 88 | #define DEF_COLUMN_STYLE "text"
|
---|
| 89 | #define DEF_COLUMN_TITLE_BACKGROUND STD_NORMAL_BACKGROUND
|
---|
| 90 | #define DEF_COLUMN_TITLE_BORDERWIDTH STD_BORDERWIDTH
|
---|
| 91 | #define DEF_COLUMN_TITLE_FONT STD_FONT
|
---|
| 92 | #define DEF_COLUMN_TITLE_FOREGROUND STD_NORMAL_FOREGROUND
|
---|
| 93 | #define DEF_COLUMN_TITLE_RELIEF "raised"
|
---|
| 94 | #define DEF_COLUMN_WEIGHT "1.0"
|
---|
| 95 | #define DEF_COLUMN_WIDTH "0"
|
---|
| 96 | #define DEF_COLUMN_RULE_DASHES "dot"
|
---|
| 97 |
|
---|
| 98 | extern Blt_OptionParseProc Blt_ObjToEnum;
|
---|
| 99 | extern Blt_OptionPrintProc Blt_EnumToObj;
|
---|
| 100 |
|
---|
| 101 | static Blt_CustomOption typeOption =
|
---|
| 102 | {
|
---|
| 103 | Blt_ObjToEnum, Blt_EnumToObj, NULL, (ClientData)sortTypeStrings
|
---|
| 104 | };
|
---|
| 105 |
|
---|
| 106 | static Blt_CustomOption columnOption =
|
---|
| 107 | {
|
---|
| 108 | ObjToColumn, ColumnToObj, NULL, (ClientData)0
|
---|
| 109 | };
|
---|
| 110 |
|
---|
| 111 | Blt_CustomOption bltTreeViewDataOption =
|
---|
| 112 | {
|
---|
| 113 | ObjToData, DataToObj, NULL, (ClientData)0,
|
---|
| 114 | };
|
---|
| 115 |
|
---|
| 116 | static Blt_OptionParseProc ObjToStyle;
|
---|
| 117 | static Blt_OptionPrintProc StyleToObj;
|
---|
| 118 | static Blt_OptionFreeProc FreeStyle;
|
---|
| 119 | static Blt_CustomOption styleOption =
|
---|
| 120 | {
|
---|
| 121 | /* Contains a pointer to the widget that's currently being
|
---|
| 122 | * configured. This is used in the custom configuration parse
|
---|
| 123 | * routine for icons. */
|
---|
| 124 | ObjToStyle, StyleToObj, FreeStyle, NULL,
|
---|
| 125 | };
|
---|
| 126 |
|
---|
| 127 | extern Blt_CustomOption bltTreeViewUidOption;
|
---|
| 128 | extern Blt_CustomOption bltTreeViewIconOption;
|
---|
| 129 | static Blt_TreeApplyProc SortApplyProc;
|
---|
| 130 |
|
---|
| 131 | static Blt_ConfigSpec columnSpecs[] =
|
---|
| 132 | {
|
---|
| 133 | {BLT_CONFIG_BORDER, "-activetitlebackground", "activeTitleBackground",
|
---|
| 134 | "Background", DEF_COLUMN_ACTIVE_TITLE_BG,
|
---|
| 135 | Blt_Offset(TreeViewColumn, activeTitleBorder), 0},
|
---|
| 136 | {BLT_CONFIG_COLOR, "-activetitleforeground", "activeTitleForeground",
|
---|
| 137 | "Foreground", DEF_COLUMN_ACTIVE_TITLE_FG,
|
---|
| 138 | Blt_Offset(TreeViewColumn, activeTitleFgColor), 0},
|
---|
| 139 | {BLT_CONFIG_BORDER, "-background", "background", "Background",
|
---|
| 140 | DEF_COLUMN_BACKGROUND, Blt_Offset(TreeViewColumn, border),
|
---|
| 141 | BLT_CONFIG_NULL_OK},
|
---|
| 142 | {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL,
|
---|
| 143 | 0, 0},
|
---|
| 144 | {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL,
|
---|
| 145 | 0, 0},
|
---|
| 146 | {BLT_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags",
|
---|
| 147 | DEF_COLUMN_BIND_TAGS, Blt_Offset(TreeViewColumn, tagsUid),
|
---|
| 148 | BLT_CONFIG_NULL_OK, &bltTreeViewUidOption},
|
---|
| 149 | {BLT_CONFIG_DISTANCE, "-borderwidth", "borderWidth", "BorderWidth",
|
---|
| 150 | DEF_COLUMN_BORDERWIDTH, Blt_Offset(TreeViewColumn, borderWidth),
|
---|
| 151 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 152 | {BLT_CONFIG_STRING, "-command", "command", "Command",
|
---|
| 153 | DEF_COLUMN_COMMAND, Blt_Offset(TreeViewColumn, titleCmd),
|
---|
| 154 | BLT_CONFIG_DONT_SET_DEFAULT | BLT_CONFIG_NULL_OK},
|
---|
| 155 | {BLT_CONFIG_BOOLEAN, "-edit", "edit", "Edit",
|
---|
| 156 | DEF_COLUMN_STATE, Blt_Offset(TreeViewColumn, editable),
|
---|
| 157 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 158 | {BLT_CONFIG_BOOLEAN, "-hide", "hide", "Hide",
|
---|
| 159 | DEF_COLUMN_HIDE, Blt_Offset(TreeViewColumn, hidden),
|
---|
| 160 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 161 | {BLT_CONFIG_CUSTOM, "-icon", "icon", "icon",
|
---|
| 162 | (char *)NULL, Blt_Offset(TreeViewColumn, titleIcon),
|
---|
| 163 | BLT_CONFIG_DONT_SET_DEFAULT, &bltTreeViewIconOption},
|
---|
| 164 | {BLT_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
|
---|
| 165 | DEF_COLUMN_JUSTIFY, Blt_Offset(TreeViewColumn, justify),
|
---|
| 166 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 167 | {BLT_CONFIG_DISTANCE, "-max", "max", "Max",
|
---|
| 168 | DEF_COLUMN_MAX, Blt_Offset(TreeViewColumn, reqMax),
|
---|
| 169 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 170 | {BLT_CONFIG_DISTANCE, "-min", "min", "Min",
|
---|
| 171 | DEF_COLUMN_MIN, Blt_Offset(TreeViewColumn, reqMin),
|
---|
| 172 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 173 | {BLT_CONFIG_PAD, "-pad", "pad", "Pad",
|
---|
| 174 | DEF_COLUMN_PAD, Blt_Offset(TreeViewColumn, pad),
|
---|
| 175 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 176 | {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief",
|
---|
| 177 | DEF_COLUMN_RELIEF, Blt_Offset(TreeViewColumn, relief),
|
---|
| 178 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 179 | {BLT_CONFIG_DASHES, "-ruledashes", "ruleDashes", "RuleDashes",
|
---|
| 180 | DEF_COLUMN_RULE_DASHES, Blt_Offset(TreeViewColumn, ruleDashes),
|
---|
| 181 | BLT_CONFIG_NULL_OK},
|
---|
| 182 | {BLT_CONFIG_STRING, "-sortcommand", "sortCommand", "SortCommand",
|
---|
| 183 | DEF_SORT_COMMAND, Blt_Offset(TreeViewColumn, sortCmd),
|
---|
| 184 | BLT_CONFIG_NULL_OK},
|
---|
| 185 | {BLT_CONFIG_STATE, "-state", "state", "State",
|
---|
| 186 | DEF_COLUMN_STATE, Blt_Offset(TreeViewColumn, state),
|
---|
| 187 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 188 | {BLT_CONFIG_CUSTOM, "-style", "style", "Style",
|
---|
| 189 | DEF_COLUMN_STYLE, Blt_Offset(TreeViewColumn, stylePtr),
|
---|
| 190 | 0, &styleOption},
|
---|
| 191 | {BLT_CONFIG_STRING, "-text", "text", "Text",
|
---|
| 192 | (char *)NULL, Blt_Offset(TreeViewColumn, title), 0},
|
---|
| 193 | {BLT_CONFIG_STRING, "-title", "title", "Title",
|
---|
| 194 | (char *)NULL, Blt_Offset(TreeViewColumn, title), 0},
|
---|
| 195 | {BLT_CONFIG_BORDER, "-titlebackground", "titleBackground",
|
---|
| 196 | "TitleBackground", DEF_COLUMN_TITLE_BACKGROUND,
|
---|
| 197 | Blt_Offset(TreeViewColumn, titleBorder),0},
|
---|
| 198 | {BLT_CONFIG_DISTANCE, "-titleborderwidth", "BorderWidth",
|
---|
| 199 | "TitleBorderWidth", DEF_COLUMN_TITLE_BORDERWIDTH,
|
---|
| 200 | Blt_Offset(TreeViewColumn, titleBorderWidth),
|
---|
| 201 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 202 | {BLT_CONFIG_FONT, "-titlefont", "titleFont", "Font",
|
---|
| 203 | DEF_COLUMN_TITLE_FONT, Blt_Offset(TreeViewColumn, titleFont), 0},
|
---|
| 204 | {BLT_CONFIG_COLOR, "-titleforeground", "titleForeground", "TitleForeground",
|
---|
| 205 | DEF_COLUMN_TITLE_FOREGROUND,
|
---|
| 206 | Blt_Offset(TreeViewColumn, titleFgColor), 0},
|
---|
| 207 | {BLT_CONFIG_RELIEF, "-titlerelief", "titleRelief", "TitleRelief",
|
---|
| 208 | DEF_COLUMN_TITLE_RELIEF, Blt_Offset(TreeViewColumn, titleRelief),
|
---|
| 209 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 210 | {BLT_CONFIG_SHADOW, "-titleshadow", "titleShadow", "TitleShadow",
|
---|
| 211 | (char *)NULL, Blt_Offset(TreeViewColumn, titleShadow), 0},
|
---|
| 212 | {BLT_CONFIG_DOUBLE, "-weight", (char *)NULL, (char *)NULL,
|
---|
| 213 | DEF_COLUMN_WEIGHT, Blt_Offset(TreeViewColumn, weight),
|
---|
| 214 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 215 | {BLT_CONFIG_DISTANCE, "-width", "width", "Width",
|
---|
| 216 | DEF_COLUMN_WIDTH, Blt_Offset(TreeViewColumn, reqWidth),
|
---|
| 217 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 218 | {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
|
---|
| 219 | (char *)NULL, 0, 0}
|
---|
| 220 | };
|
---|
| 221 |
|
---|
| 222 | static Blt_ConfigSpec sortSpecs[] =
|
---|
| 223 | {
|
---|
| 224 | {BLT_CONFIG_STRING, "-command", "command", "Command",
|
---|
| 225 | DEF_SORT_COMMAND, Blt_Offset(TreeView, sortCmd),
|
---|
| 226 | BLT_CONFIG_DONT_SET_DEFAULT | BLT_CONFIG_NULL_OK},
|
---|
| 227 | {BLT_CONFIG_CUSTOM, "-column", "column", "Column",
|
---|
| 228 | DEF_SORT_COLUMN, Blt_Offset(TreeView, sortColumnPtr),
|
---|
| 229 | BLT_CONFIG_DONT_SET_DEFAULT, &columnOption},
|
---|
| 230 | {BLT_CONFIG_BOOLEAN, "-decreasing", "decreasing", "Decreasing",
|
---|
| 231 | DEF_SORT_DECREASING, Blt_Offset(TreeView, sortDecreasing),
|
---|
| 232 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 233 | {BLT_CONFIG_CUSTOM, "-mode", "mode", "Mode",
|
---|
| 234 | DEF_SORT_TYPE, Blt_Offset(TreeView, sortType), 0, &typeOption},
|
---|
| 235 | {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
|
---|
| 236 | (char *)NULL, 0, 0}
|
---|
| 237 | };
|
---|
| 238 |
|
---|
| 239 | static Blt_TreeCompareNodesProc CompareNodes;
|
---|
| 240 | static Blt_TreeApplyProc SortApplyProc;
|
---|
| 241 |
|
---|
| 242 | /*
|
---|
| 243 | *----------------------------------------------------------------------
|
---|
| 244 | *
|
---|
| 245 | * ObjToColumn --
|
---|
| 246 | *
|
---|
| 247 | * Convert the string reprsenting a scroll mode, to its numeric
|
---|
| 248 | * form.
|
---|
| 249 | *
|
---|
| 250 | * Results:
|
---|
| 251 | * If the string is successfully converted, TCL_OK is returned.
|
---|
| 252 | * Otherwise, TCL_ERROR is returned and an error message is left
|
---|
| 253 | * in interpreter's result field.
|
---|
| 254 | *
|
---|
| 255 | *----------------------------------------------------------------------
|
---|
| 256 | */
|
---|
| 257 | /*ARGSUSED*/
|
---|
| 258 | static int
|
---|
| 259 | ObjToColumn(clientData, interp, tkwin, objPtr, widgRec, offset)
|
---|
| 260 | ClientData clientData; /* Not used. */
|
---|
| 261 | Tcl_Interp *interp; /* Interpreter to send results back to */
|
---|
| 262 | Tk_Window tkwin; /* Not used. */
|
---|
| 263 | Tcl_Obj *objPtr; /* New legend position string */
|
---|
| 264 | char *widgRec;
|
---|
| 265 | int offset;
|
---|
| 266 | {
|
---|
| 267 | TreeViewColumn **columnPtrPtr = (TreeViewColumn **)(widgRec + offset);
|
---|
| 268 | char *string;
|
---|
| 269 |
|
---|
| 270 | string = Tcl_GetString(objPtr);
|
---|
| 271 | if (*string == '\0') {
|
---|
| 272 | *columnPtrPtr = NULL;
|
---|
| 273 | } else {
|
---|
| 274 | TreeView *tvPtr = (TreeView *)widgRec;
|
---|
| 275 |
|
---|
| 276 | if (Blt_TreeViewGetColumn(interp, tvPtr, objPtr, columnPtrPtr)
|
---|
| 277 | != TCL_OK) {
|
---|
| 278 | return TCL_ERROR;
|
---|
| 279 | }
|
---|
| 280 | }
|
---|
| 281 | return TCL_OK;
|
---|
| 282 | }
|
---|
| 283 |
|
---|
| 284 | /*
|
---|
| 285 | *----------------------------------------------------------------------
|
---|
| 286 | *
|
---|
| 287 | * ColumnToString --
|
---|
| 288 | *
|
---|
| 289 | * Results:
|
---|
| 290 | * The string representation of the button boolean is returned.
|
---|
| 291 | *
|
---|
| 292 | *----------------------------------------------------------------------
|
---|
| 293 | */
|
---|
| 294 | /*ARGSUSED*/
|
---|
| 295 | static Tcl_Obj *
|
---|
| 296 | ColumnToObj(clientData, interp, tkwin, widgRec, offset)
|
---|
| 297 | ClientData clientData; /* Not used. */
|
---|
| 298 | Tcl_Interp *interp;
|
---|
| 299 | Tk_Window tkwin; /* Not used. */
|
---|
| 300 | char *widgRec;
|
---|
| 301 | int offset;
|
---|
| 302 | {
|
---|
| 303 | TreeViewColumn *columnPtr = *(TreeViewColumn **)(widgRec + offset);
|
---|
| 304 |
|
---|
| 305 | if (columnPtr == NULL) {
|
---|
| 306 | return bltEmptyStringObjPtr;
|
---|
| 307 | }
|
---|
| 308 | return Tcl_NewStringObj(columnPtr->key, -1);
|
---|
| 309 | }
|
---|
| 310 |
|
---|
| 311 | /*
|
---|
| 312 | *----------------------------------------------------------------------
|
---|
| 313 | *
|
---|
| 314 | * ObjToData --
|
---|
| 315 | *
|
---|
| 316 | * Convert the string reprsenting a scroll mode, to its numeric
|
---|
| 317 | * form.
|
---|
| 318 | *
|
---|
| 319 | * Results:
|
---|
| 320 | * If the string is successfully converted, TCL_OK is returned.
|
---|
| 321 | * Otherwise, TCL_ERROR is returned and an error message is left
|
---|
| 322 | * in interpreter's result field.
|
---|
| 323 | *
|
---|
| 324 | *----------------------------------------------------------------------
|
---|
| 325 | */
|
---|
| 326 | /*ARGSUSED*/
|
---|
| 327 | static int
|
---|
| 328 | ObjToData(clientData, interp, tkwin, objPtr, widgRec, offset)
|
---|
| 329 | ClientData clientData; /* Node of entry. */
|
---|
| 330 | Tcl_Interp *interp; /* Interpreter to send results back to */
|
---|
| 331 | Tk_Window tkwin; /* Not used. */
|
---|
| 332 | Tcl_Obj *objPtr; /* Tcl_Obj representing new data. */
|
---|
| 333 | char *widgRec;
|
---|
| 334 | int offset;
|
---|
| 335 | {
|
---|
| 336 | Tcl_Obj **objv;
|
---|
| 337 | TreeViewColumn *columnPtr;
|
---|
| 338 | TreeViewEntry *entryPtr = (TreeViewEntry *)widgRec;
|
---|
| 339 | char *string;
|
---|
| 340 | int objc;
|
---|
| 341 | register int i;
|
---|
| 342 |
|
---|
| 343 | string = Tcl_GetString(objPtr);
|
---|
| 344 | if (*string == '\0') {
|
---|
| 345 | return TCL_OK;
|
---|
| 346 | }
|
---|
| 347 | if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
|
---|
| 348 | return TCL_ERROR;
|
---|
| 349 | }
|
---|
| 350 | if (objc == 0) {
|
---|
| 351 | return TCL_OK;
|
---|
| 352 | }
|
---|
| 353 | if (objc & 0x1) {
|
---|
| 354 | Tcl_AppendResult(interp, "data \"", string,
|
---|
| 355 | "\" must be in even name-value pairs", (char *)NULL);
|
---|
| 356 | return TCL_ERROR;
|
---|
| 357 | }
|
---|
| 358 | for (i = 0; i < objc; i += 2) {
|
---|
| 359 | TreeView *tvPtr = entryPtr->tvPtr;
|
---|
| 360 |
|
---|
| 361 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[i], &columnPtr)
|
---|
| 362 | != TCL_OK) {
|
---|
| 363 | return TCL_ERROR;
|
---|
| 364 | }
|
---|
| 365 | if (Blt_TreeSetValueByKey(tvPtr->interp, tvPtr->tree, entryPtr->node,
|
---|
| 366 | columnPtr->key, objv[i + 1]) != TCL_OK) {
|
---|
| 367 | return TCL_ERROR;
|
---|
| 368 | }
|
---|
| 369 | Blt_TreeViewAddValue(entryPtr, columnPtr);
|
---|
| 370 | }
|
---|
| 371 | return TCL_OK;
|
---|
| 372 | }
|
---|
| 373 |
|
---|
| 374 | /*
|
---|
| 375 | *----------------------------------------------------------------------
|
---|
| 376 | *
|
---|
| 377 | * DataToObj --
|
---|
| 378 | *
|
---|
| 379 | * Results:
|
---|
| 380 | * The string representation of the data is returned.
|
---|
| 381 | *
|
---|
| 382 | *----------------------------------------------------------------------
|
---|
| 383 | */
|
---|
| 384 | /*ARGSUSED*/
|
---|
| 385 | static Tcl_Obj *
|
---|
| 386 | DataToObj(clientData, interp, tkwin, widgRec, offset)
|
---|
| 387 | ClientData clientData; /* Not used. */
|
---|
| 388 | Tcl_Interp *interp;
|
---|
| 389 | Tk_Window tkwin; /* Not used. */
|
---|
| 390 | char *widgRec;
|
---|
| 391 | int offset;
|
---|
| 392 | {
|
---|
| 393 | Tcl_Obj *listObjPtr, *objPtr;
|
---|
| 394 | TreeViewEntry *entryPtr = (TreeViewEntry *)widgRec;
|
---|
| 395 | TreeViewValue *valuePtr;
|
---|
| 396 |
|
---|
| 397 | /* Add the key-value pairs to a new Tcl_Obj */
|
---|
| 398 | listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
|
---|
| 399 | for (valuePtr = entryPtr->values; valuePtr != NULL;
|
---|
| 400 | valuePtr = valuePtr->nextPtr) {
|
---|
| 401 | objPtr = Tcl_NewStringObj(valuePtr->columnPtr->key, -1);
|
---|
| 402 | Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
|
---|
| 403 | if (Blt_TreeViewGetData(entryPtr, valuePtr->columnPtr->key, &objPtr)
|
---|
| 404 | != TCL_OK) {
|
---|
| 405 | objPtr = bltEmptyStringObjPtr;
|
---|
| 406 | }
|
---|
| 407 | Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
|
---|
| 408 | }
|
---|
| 409 | return listObjPtr;
|
---|
| 410 | }
|
---|
| 411 |
|
---|
| 412 | int
|
---|
| 413 | Blt_TreeViewGetColumn(interp, tvPtr, objPtr, columnPtrPtr)
|
---|
| 414 | Tcl_Interp *interp;
|
---|
| 415 | TreeView *tvPtr;
|
---|
| 416 | Tcl_Obj *objPtr;
|
---|
| 417 | TreeViewColumn **columnPtrPtr;
|
---|
| 418 | {
|
---|
| 419 | char *string;
|
---|
| 420 |
|
---|
| 421 | string = Tcl_GetString(objPtr);
|
---|
| 422 | if (strcmp(string, "treeView") == 0) {
|
---|
| 423 | *columnPtrPtr = &tvPtr->treeColumn;
|
---|
| 424 | } else {
|
---|
| 425 | Blt_HashEntry *hPtr;
|
---|
| 426 |
|
---|
| 427 | hPtr = Blt_FindHashEntry(&tvPtr->columnTable, Blt_TreeGetKey(string));
|
---|
| 428 | if (hPtr == NULL) {
|
---|
| 429 | if (interp != NULL) {
|
---|
| 430 | Tcl_AppendResult(interp, "can't find column \"", string,
|
---|
| 431 | "\" in \"", Tk_PathName(tvPtr->tkwin), "\"",
|
---|
| 432 | (char *)NULL);
|
---|
| 433 | }
|
---|
| 434 | return TCL_ERROR;
|
---|
| 435 | }
|
---|
| 436 | *columnPtrPtr = Blt_GetHashValue(hPtr);
|
---|
| 437 | }
|
---|
| 438 | return TCL_OK;
|
---|
| 439 | }
|
---|
| 440 |
|
---|
| 441 |
|
---|
| 442 | /*
|
---|
| 443 | *----------------------------------------------------------------------
|
---|
| 444 | *
|
---|
| 445 | * ObjToStyle --
|
---|
| 446 | *
|
---|
| 447 | * Convert the name of an icon into a treeview style.
|
---|
| 448 | *
|
---|
| 449 | * Results:
|
---|
| 450 | * If the string is successfully converted, TCL_OK is returned.
|
---|
| 451 | * Otherwise, TCL_ERROR is returned and an error message is left in
|
---|
| 452 | * interpreter's result field.
|
---|
| 453 | *
|
---|
| 454 | *----------------------------------------------------------------------
|
---|
| 455 | */
|
---|
| 456 | /*ARGSUSED*/
|
---|
| 457 | static int
|
---|
| 458 | ObjToStyle(clientData, interp, tkwin, objPtr, widgRec, offset)
|
---|
| 459 | ClientData clientData; /* Not used. */
|
---|
| 460 | Tcl_Interp *interp; /* Interpreter to send results back to */
|
---|
| 461 | Tk_Window tkwin; /* Not used. */
|
---|
| 462 | Tcl_Obj *objPtr; /* Tcl_Obj representing the new value. */
|
---|
| 463 | char *widgRec;
|
---|
| 464 | int offset;
|
---|
| 465 | {
|
---|
| 466 | TreeView *tvPtr = clientData;
|
---|
| 467 | TreeViewStyle **stylePtrPtr = (TreeViewStyle **)(widgRec + offset);
|
---|
| 468 | TreeViewStyle *stylePtr;
|
---|
| 469 |
|
---|
| 470 | if (Blt_TreeViewGetStyle(interp, tvPtr, Tcl_GetString(objPtr),
|
---|
| 471 | &stylePtr) != TCL_OK) {
|
---|
| 472 | return TCL_ERROR;
|
---|
| 473 | }
|
---|
| 474 | stylePtr->flags |= STYLE_DIRTY;
|
---|
| 475 | tvPtr->flags |= (TV_LAYOUT | TV_DIRTY);
|
---|
| 476 | *stylePtrPtr = stylePtr;
|
---|
| 477 | return TCL_OK;
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | /*
|
---|
| 481 | *----------------------------------------------------------------------
|
---|
| 482 | *
|
---|
| 483 | * IconToObj --
|
---|
| 484 | *
|
---|
| 485 | * Converts the icon into its string representation (its name).
|
---|
| 486 | *
|
---|
| 487 | * Results:
|
---|
| 488 | * The name of the icon is returned.
|
---|
| 489 | *
|
---|
| 490 | *----------------------------------------------------------------------
|
---|
| 491 | */
|
---|
| 492 | /*ARGSUSED*/
|
---|
| 493 | static Tcl_Obj *
|
---|
| 494 | StyleToObj(clientData, interp, tkwin, widgRec, offset)
|
---|
| 495 | ClientData clientData; /* Not used. */
|
---|
| 496 | Tcl_Interp *interp;
|
---|
| 497 | Tk_Window tkwin; /* Not used. */
|
---|
| 498 | char *widgRec;
|
---|
| 499 | int offset;
|
---|
| 500 | {
|
---|
| 501 | TreeViewStyle *stylePtr = *(TreeViewStyle **)(widgRec + offset);
|
---|
| 502 |
|
---|
| 503 | if (stylePtr == NULL) {
|
---|
| 504 | return bltEmptyStringObjPtr;
|
---|
| 505 | }
|
---|
| 506 | return Tcl_NewStringObj(stylePtr->name, -1);
|
---|
| 507 | }
|
---|
| 508 |
|
---|
| 509 | /*ARGSUSED*/
|
---|
| 510 | static void
|
---|
| 511 | FreeStyle(clientData, display, widgRec, offset)
|
---|
| 512 | ClientData clientData;
|
---|
| 513 | Display *display; /* Not used. */
|
---|
| 514 | char *widgRec;
|
---|
| 515 | int offset;
|
---|
| 516 | {
|
---|
| 517 | TreeView *tvPtr = clientData;
|
---|
| 518 | TreeViewStyle *stylePtr = *(TreeViewStyle **)(widgRec + offset);
|
---|
| 519 |
|
---|
| 520 | Blt_TreeViewFreeStyle(tvPtr, stylePtr);
|
---|
| 521 | }
|
---|
| 522 |
|
---|
| 523 | void
|
---|
| 524 | Blt_TreeViewUpdateColumnGCs(tvPtr, columnPtr)
|
---|
| 525 | TreeView *tvPtr;
|
---|
| 526 | TreeViewColumn *columnPtr;
|
---|
| 527 | {
|
---|
| 528 | Drawable drawable;
|
---|
| 529 | GC newGC;
|
---|
| 530 | Tk_3DBorder border;
|
---|
| 531 | XGCValues gcValues;
|
---|
| 532 | int ruleDrawn;
|
---|
| 533 | unsigned long gcMask;
|
---|
| 534 | int iconWidth, iconHeight;
|
---|
| 535 | int textWidth, textHeight;
|
---|
| 536 |
|
---|
| 537 | gcMask = GCForeground | GCFont;
|
---|
| 538 | gcValues.font = Tk_FontId(columnPtr->titleFont);
|
---|
| 539 |
|
---|
| 540 | /* Normal title text */
|
---|
| 541 | gcValues.foreground = columnPtr->titleFgColor->pixel;
|
---|
| 542 | newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
|
---|
| 543 | if (columnPtr->titleGC != NULL) {
|
---|
| 544 | Tk_FreeGC(tvPtr->display, columnPtr->titleGC);
|
---|
| 545 | }
|
---|
| 546 | columnPtr->titleGC = newGC;
|
---|
| 547 |
|
---|
| 548 | /* Active title text */
|
---|
| 549 | gcValues.foreground = columnPtr->activeTitleFgColor->pixel;
|
---|
| 550 | newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
|
---|
| 551 | if (columnPtr->activeTitleGC != NULL) {
|
---|
| 552 | Tk_FreeGC(tvPtr->display, columnPtr->activeTitleGC);
|
---|
| 553 | }
|
---|
| 554 | columnPtr->activeTitleGC = newGC;
|
---|
| 555 |
|
---|
| 556 | columnPtr->titleWidth = 0;
|
---|
| 557 | iconWidth = iconHeight = 0;
|
---|
| 558 | if (columnPtr->titleIcon != NULL) {
|
---|
| 559 | iconWidth = TreeViewIconWidth(columnPtr->titleIcon);
|
---|
| 560 | iconHeight = TreeViewIconHeight(columnPtr->titleIcon);
|
---|
| 561 | columnPtr->titleWidth += iconWidth;
|
---|
| 562 | }
|
---|
| 563 | if (columnPtr->titleTextPtr != NULL) {
|
---|
| 564 | Blt_Free(columnPtr->titleTextPtr);
|
---|
| 565 | columnPtr->titleTextPtr = NULL;
|
---|
| 566 | }
|
---|
| 567 | textWidth = textHeight = 0;
|
---|
| 568 | if (columnPtr->title != NULL) {
|
---|
| 569 | TextStyle ts;
|
---|
| 570 |
|
---|
| 571 | memset(&ts, 0, sizeof(TextStyle));
|
---|
| 572 | ts.font = columnPtr->titleFont;
|
---|
| 573 | ts.justify = TK_JUSTIFY_LEFT;
|
---|
| 574 | ts.shadow.offset = columnPtr->titleShadow.offset;
|
---|
| 575 | columnPtr->titleTextPtr = Blt_GetTextLayout(columnPtr->title, &ts);
|
---|
| 576 | textHeight = columnPtr->titleTextPtr->height;
|
---|
| 577 | textWidth = columnPtr->titleTextPtr->width;
|
---|
| 578 | columnPtr->titleWidth += textWidth;
|
---|
| 579 | }
|
---|
| 580 | if ((iconWidth > 0) && (textWidth > 0)) {
|
---|
| 581 | columnPtr->titleWidth += 8;
|
---|
| 582 | }
|
---|
| 583 | columnPtr->titleWidth += STD_ARROW_HEIGHT;
|
---|
| 584 | columnPtr->titleHeight = MAX(iconHeight, textHeight);
|
---|
| 585 |
|
---|
| 586 | gcMask = (GCFunction | GCLineWidth | GCLineStyle | GCForeground);
|
---|
| 587 |
|
---|
| 588 | /*
|
---|
| 589 | * If the rule is active, turn it off (i.e. draw again to erase
|
---|
| 590 | * it) before changing the GC. If the color changes, we won't be
|
---|
| 591 | * able to erase the old line, since it will no longer be
|
---|
| 592 | * correctly XOR-ed with the background.
|
---|
| 593 | */
|
---|
| 594 | drawable = Tk_WindowId(tvPtr->tkwin);
|
---|
| 595 | ruleDrawn = ((tvPtr->flags & TV_RULE_ACTIVE) &&
|
---|
| 596 | (tvPtr->activeTitleColumnPtr == columnPtr) &&
|
---|
| 597 | (drawable != None));
|
---|
| 598 | if (ruleDrawn) {
|
---|
| 599 | Blt_TreeViewDrawRule(tvPtr, columnPtr, drawable);
|
---|
| 600 | }
|
---|
| 601 | /* XOR-ed rule column divider */
|
---|
| 602 | gcValues.line_width = LineWidth(columnPtr->ruleLineWidth);
|
---|
| 603 | gcValues.foreground =
|
---|
| 604 | Blt_TreeViewGetStyleFg(tvPtr, columnPtr->stylePtr)->pixel;
|
---|
| 605 | if (LineIsDashed(columnPtr->ruleDashes)) {
|
---|
| 606 | gcValues.line_style = LineOnOffDash;
|
---|
| 607 | } else {
|
---|
| 608 | gcValues.line_style = LineSolid;
|
---|
| 609 | }
|
---|
| 610 | gcValues.function = GXxor;
|
---|
| 611 |
|
---|
| 612 | border = CHOOSE(tvPtr->border, columnPtr->border);
|
---|
| 613 | gcValues.foreground ^= Tk_3DBorderColor(border)->pixel;
|
---|
| 614 | newGC = Blt_GetPrivateGC(tvPtr->tkwin, gcMask, &gcValues);
|
---|
| 615 | if (columnPtr->ruleGC != NULL) {
|
---|
| 616 | Blt_FreePrivateGC(tvPtr->display, columnPtr->ruleGC);
|
---|
| 617 | }
|
---|
| 618 | if (LineIsDashed(columnPtr->ruleDashes)) {
|
---|
| 619 | Blt_SetDashes(tvPtr->display, newGC, &columnPtr->ruleDashes);
|
---|
| 620 | }
|
---|
| 621 | columnPtr->ruleGC = newGC;
|
---|
| 622 | if (ruleDrawn) {
|
---|
| 623 | Blt_TreeViewDrawRule(tvPtr, columnPtr, drawable);
|
---|
| 624 | }
|
---|
| 625 | columnPtr->flags |= COLUMN_DIRTY;
|
---|
| 626 | tvPtr->flags |= TV_UPDATE;
|
---|
| 627 | }
|
---|
| 628 |
|
---|
| 629 | static void
|
---|
| 630 | DestroyColumn(tvPtr, columnPtr)
|
---|
| 631 | TreeView *tvPtr;
|
---|
| 632 | TreeViewColumn *columnPtr;
|
---|
| 633 | {
|
---|
| 634 | Blt_HashEntry *hPtr;
|
---|
| 635 |
|
---|
| 636 | bltTreeViewUidOption.clientData = tvPtr;
|
---|
| 637 | bltTreeViewIconOption.clientData = tvPtr;
|
---|
| 638 | styleOption.clientData = tvPtr;
|
---|
| 639 | Blt_FreeObjOptions(columnSpecs, (char *)columnPtr, tvPtr->display, 0);
|
---|
| 640 |
|
---|
| 641 | if (columnPtr->titleGC != NULL) {
|
---|
| 642 | Tk_FreeGC(tvPtr->display, columnPtr->titleGC);
|
---|
| 643 | }
|
---|
| 644 | if (columnPtr->ruleGC != NULL) {
|
---|
| 645 | Blt_FreePrivateGC(tvPtr->display, columnPtr->ruleGC);
|
---|
| 646 | }
|
---|
| 647 | hPtr = Blt_FindHashEntry(&tvPtr->columnTable, columnPtr->key);
|
---|
| 648 | if (hPtr != NULL) {
|
---|
| 649 | Blt_DeleteHashEntry(&tvPtr->columnTable, hPtr);
|
---|
| 650 | }
|
---|
| 651 | if (columnPtr->linkPtr != NULL) {
|
---|
| 652 | Blt_ChainDeleteLink(tvPtr->colChainPtr, columnPtr->linkPtr);
|
---|
| 653 | }
|
---|
| 654 | if (columnPtr->title != NULL) {
|
---|
| 655 | Blt_Free(columnPtr->title);
|
---|
| 656 | }
|
---|
| 657 | if (columnPtr->titleTextPtr != NULL) {
|
---|
| 658 | Blt_Free(columnPtr->titleTextPtr);
|
---|
| 659 | }
|
---|
| 660 | if (columnPtr->stylePtr != NULL) {
|
---|
| 661 | Blt_TreeViewFreeStyle(tvPtr, columnPtr->stylePtr);
|
---|
| 662 | }
|
---|
| 663 | if (columnPtr != &tvPtr->treeColumn) {
|
---|
| 664 | Blt_Free(columnPtr);
|
---|
| 665 | }
|
---|
| 666 | }
|
---|
| 667 |
|
---|
| 668 | void
|
---|
| 669 | Blt_TreeViewDestroyColumns(tvPtr)
|
---|
| 670 | TreeView *tvPtr;
|
---|
| 671 | {
|
---|
| 672 | if (tvPtr->colChainPtr != NULL) {
|
---|
| 673 | Blt_ChainLink *linkPtr;
|
---|
| 674 | TreeViewColumn *columnPtr;
|
---|
| 675 |
|
---|
| 676 | for (linkPtr = Blt_ChainFirstLink(tvPtr->colChainPtr); linkPtr != NULL;
|
---|
| 677 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
| 678 | columnPtr = Blt_ChainGetValue(linkPtr);
|
---|
| 679 | columnPtr->linkPtr = NULL;
|
---|
| 680 | DestroyColumn(tvPtr, columnPtr);
|
---|
| 681 | }
|
---|
| 682 | Blt_ChainDestroy(tvPtr->colChainPtr);
|
---|
| 683 | tvPtr->colChainPtr = NULL;
|
---|
| 684 | }
|
---|
| 685 | Blt_DeleteHashTable(&tvPtr->columnTable);
|
---|
| 686 | }
|
---|
| 687 |
|
---|
| 688 | int
|
---|
| 689 | Blt_TreeViewCreateColumn(tvPtr, columnPtr, name, defTitle)
|
---|
| 690 | TreeView *tvPtr;
|
---|
| 691 | TreeViewColumn *columnPtr;
|
---|
| 692 | char *name, *defTitle;
|
---|
| 693 | {
|
---|
| 694 | Blt_HashEntry *hPtr;
|
---|
| 695 | int isNew;
|
---|
| 696 |
|
---|
| 697 | columnPtr->key = Blt_TreeGetKey(name);
|
---|
| 698 | columnPtr->title = Blt_Strdup(defTitle);
|
---|
| 699 | columnPtr->justify = TK_JUSTIFY_CENTER;
|
---|
| 700 | columnPtr->relief = TK_RELIEF_FLAT;
|
---|
| 701 | columnPtr->borderWidth = 1;
|
---|
| 702 | columnPtr->pad.side1 = columnPtr->pad.side2 = 2;
|
---|
| 703 | columnPtr->state = STATE_NORMAL;
|
---|
| 704 | columnPtr->weight = 1.0;
|
---|
| 705 | columnPtr->editable = FALSE;
|
---|
| 706 | columnPtr->ruleLineWidth = 1;
|
---|
| 707 | columnPtr->titleBorderWidth = 2;
|
---|
| 708 | columnPtr->titleRelief = TK_RELIEF_RAISED;
|
---|
| 709 | columnPtr->titleIcon = NULL;
|
---|
| 710 | hPtr = Blt_CreateHashEntry(&tvPtr->columnTable, columnPtr->key, &isNew);
|
---|
| 711 | Blt_SetHashValue(hPtr, columnPtr);
|
---|
| 712 |
|
---|
| 713 | bltTreeViewUidOption.clientData = tvPtr;
|
---|
| 714 | bltTreeViewIconOption.clientData = tvPtr;
|
---|
| 715 | styleOption.clientData = tvPtr;
|
---|
| 716 | if (Blt_ConfigureComponentFromObj(tvPtr->interp, tvPtr->tkwin, name,
|
---|
| 717 | "Column", columnSpecs, 0, (Tcl_Obj **)NULL, (char *)columnPtr, 0)
|
---|
| 718 | != TCL_OK) {
|
---|
| 719 | DestroyColumn(tvPtr, columnPtr);
|
---|
| 720 | return TCL_ERROR;
|
---|
| 721 | }
|
---|
| 722 | return TCL_OK;
|
---|
| 723 | }
|
---|
| 724 |
|
---|
| 725 | static TreeViewColumn *
|
---|
| 726 | CreateColumn(tvPtr, nameObjPtr, objc, objv)
|
---|
| 727 | TreeView *tvPtr;
|
---|
| 728 | Tcl_Obj *nameObjPtr;
|
---|
| 729 | int objc;
|
---|
| 730 | Tcl_Obj *CONST *objv;
|
---|
| 731 | {
|
---|
| 732 | TreeViewColumn *columnPtr;
|
---|
| 733 |
|
---|
| 734 | columnPtr = Blt_Calloc(1, sizeof(TreeViewColumn));
|
---|
| 735 | assert(columnPtr);
|
---|
| 736 | if (Blt_TreeViewCreateColumn(tvPtr, columnPtr, Tcl_GetString(nameObjPtr),
|
---|
| 737 | Tcl_GetString(nameObjPtr)) != TCL_OK) {
|
---|
| 738 | return NULL;
|
---|
| 739 | }
|
---|
| 740 | bltTreeViewUidOption.clientData = tvPtr;
|
---|
| 741 | bltTreeViewIconOption.clientData = tvPtr;
|
---|
| 742 | styleOption.clientData = tvPtr;
|
---|
| 743 | if (Blt_ConfigureComponentFromObj(tvPtr->interp, tvPtr->tkwin,
|
---|
| 744 | columnPtr->key, "Column", columnSpecs, objc, objv, (char *)columnPtr,
|
---|
| 745 | BLT_CONFIG_OBJV_ONLY) != TCL_OK) {
|
---|
| 746 | DestroyColumn(tvPtr, columnPtr);
|
---|
| 747 | return NULL;
|
---|
| 748 | }
|
---|
| 749 | Blt_TreeViewUpdateColumnGCs(tvPtr, columnPtr);
|
---|
| 750 | return columnPtr;
|
---|
| 751 | }
|
---|
| 752 |
|
---|
| 753 | TreeViewColumn *
|
---|
| 754 | Blt_TreeViewNearestColumn(tvPtr, x, y, contextPtr)
|
---|
| 755 | TreeView *tvPtr;
|
---|
| 756 | int x, y;
|
---|
| 757 | ClientData *contextPtr;
|
---|
| 758 | {
|
---|
| 759 | if (tvPtr->nVisible > 0) {
|
---|
| 760 | Blt_ChainLink *linkPtr;
|
---|
| 761 | TreeViewColumn *columnPtr;
|
---|
| 762 | int right;
|
---|
| 763 |
|
---|
| 764 | /*
|
---|
| 765 | * Determine if the pointer is over the rightmost portion of the
|
---|
| 766 | * column. This activates the rule.
|
---|
| 767 | */
|
---|
| 768 | x = WORLDX(tvPtr, x);
|
---|
| 769 | for(linkPtr = Blt_ChainFirstLink(tvPtr->colChainPtr); linkPtr != NULL;
|
---|
| 770 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
| 771 | columnPtr = Blt_ChainGetValue(linkPtr);
|
---|
| 772 | right = columnPtr->worldX + columnPtr->width;
|
---|
| 773 | if ((x >= columnPtr->worldX) && (x <= right)) {
|
---|
| 774 | if (contextPtr != NULL) {
|
---|
| 775 | *contextPtr = NULL;
|
---|
| 776 | if ((tvPtr->flags & TV_SHOW_COLUMN_TITLES) &&
|
---|
| 777 | (y >= tvPtr->inset) &&
|
---|
| 778 | (y < (tvPtr->titleHeight + tvPtr->inset))) {
|
---|
| 779 | *contextPtr = (x >= (right - RULE_AREA))
|
---|
| 780 | ? ITEM_COLUMN_RULE : ITEM_COLUMN_TITLE;
|
---|
| 781 | }
|
---|
| 782 | }
|
---|
| 783 | return columnPtr;
|
---|
| 784 | }
|
---|
| 785 | }
|
---|
| 786 | }
|
---|
| 787 | return NULL;
|
---|
| 788 | }
|
---|
| 789 |
|
---|
| 790 | /*
|
---|
| 791 | *----------------------------------------------------------------------
|
---|
| 792 | *
|
---|
| 793 | * ColumnActivateOp --
|
---|
| 794 | *
|
---|
| 795 | * Selects the button to appear active.
|
---|
| 796 | *
|
---|
| 797 | *----------------------------------------------------------------------
|
---|
| 798 | */
|
---|
| 799 | /*ARGSUSED*/
|
---|
| 800 | static int
|
---|
| 801 | ColumnActivateOp(tvPtr, interp, objc, objv)
|
---|
| 802 | TreeView *tvPtr;
|
---|
| 803 | Tcl_Interp *interp;
|
---|
| 804 | int objc; /* Not used. */
|
---|
| 805 | Tcl_Obj *CONST *objv;
|
---|
| 806 | {
|
---|
| 807 | if (objc == 4) {
|
---|
| 808 | Drawable drawable;
|
---|
| 809 | TreeViewColumn *columnPtr;
|
---|
| 810 | char *string;
|
---|
| 811 |
|
---|
| 812 | string = Tcl_GetString(objv[3]);
|
---|
| 813 | if (string[0] == '\0') {
|
---|
| 814 | columnPtr = NULL;
|
---|
| 815 | } else {
|
---|
| 816 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr)
|
---|
| 817 | != TCL_OK) {
|
---|
| 818 | return TCL_ERROR;
|
---|
| 819 | }
|
---|
| 820 | if (((tvPtr->flags & TV_SHOW_COLUMN_TITLES) == 0) ||
|
---|
| 821 | (columnPtr->hidden) || (columnPtr->state == STATE_DISABLED)) {
|
---|
| 822 | columnPtr = NULL;
|
---|
| 823 | }
|
---|
| 824 | }
|
---|
| 825 | tvPtr->activeTitleColumnPtr = tvPtr->activeColumnPtr = columnPtr;
|
---|
| 826 | drawable = Tk_WindowId(tvPtr->tkwin);
|
---|
| 827 | if (drawable != None) {
|
---|
| 828 | Blt_TreeViewDrawHeadings(tvPtr, drawable);
|
---|
| 829 | Blt_TreeViewDrawOuterBorders(tvPtr, drawable);
|
---|
| 830 | }
|
---|
| 831 | }
|
---|
| 832 | if (tvPtr->activeTitleColumnPtr != NULL) {
|
---|
| 833 | Tcl_SetResult(interp, tvPtr->activeTitleColumnPtr->key, TCL_VOLATILE);
|
---|
| 834 | }
|
---|
| 835 | return TCL_OK;
|
---|
| 836 | }
|
---|
| 837 |
|
---|
| 838 | /*
|
---|
| 839 | *----------------------------------------------------------------------
|
---|
| 840 | *
|
---|
| 841 | * ColumnBindOp --
|
---|
| 842 | *
|
---|
| 843 | * .t bind tag sequence command
|
---|
| 844 | *
|
---|
| 845 | *----------------------------------------------------------------------
|
---|
| 846 | */
|
---|
| 847 | /*ARGSUSED*/
|
---|
| 848 | static int
|
---|
| 849 | ColumnBindOp(tvPtr, interp, objc, objv)
|
---|
| 850 | TreeView *tvPtr;
|
---|
| 851 | Tcl_Interp *interp;
|
---|
| 852 | int objc; /* Not used. */
|
---|
| 853 | Tcl_Obj *CONST *objv;
|
---|
| 854 | {
|
---|
| 855 | ClientData object;
|
---|
| 856 | TreeViewColumn *columnPtr;
|
---|
| 857 |
|
---|
| 858 | if (Blt_TreeViewGetColumn(NULL, tvPtr, objv[3], &columnPtr) == TCL_OK) {
|
---|
| 859 | object = Blt_TreeViewColumnTag(tvPtr, columnPtr->key);
|
---|
| 860 | } else {
|
---|
| 861 | object = Blt_TreeViewColumnTag(tvPtr, Tcl_GetString(objv[3]));
|
---|
| 862 | }
|
---|
| 863 | return Blt_ConfigureBindingsFromObj(interp, tvPtr->bindTable, object,
|
---|
| 864 | objc - 4, objv + 4);
|
---|
| 865 | }
|
---|
| 866 |
|
---|
| 867 |
|
---|
| 868 | /*
|
---|
| 869 | *----------------------------------------------------------------------
|
---|
| 870 | *
|
---|
| 871 | * ColumnCgetOp --
|
---|
| 872 | *
|
---|
| 873 | *----------------------------------------------------------------------
|
---|
| 874 | */
|
---|
| 875 | /*ARGSUSED*/
|
---|
| 876 | static int
|
---|
| 877 | ColumnCgetOp(tvPtr, interp, objc, objv)
|
---|
| 878 | TreeView *tvPtr;
|
---|
| 879 | Tcl_Interp *interp;
|
---|
| 880 | int objc; /* Not used. */
|
---|
| 881 | Tcl_Obj *CONST *objv;
|
---|
| 882 | {
|
---|
| 883 | TreeViewColumn *columnPtr;
|
---|
| 884 |
|
---|
| 885 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr) != TCL_OK) {
|
---|
| 886 | return TCL_ERROR;
|
---|
| 887 | }
|
---|
| 888 | return Blt_ConfigureValueFromObj(interp, tvPtr->tkwin, columnSpecs,
|
---|
| 889 | (char *)columnPtr, objv[4], 0);
|
---|
| 890 | }
|
---|
| 891 |
|
---|
| 892 | /*
|
---|
| 893 | *----------------------------------------------------------------------
|
---|
| 894 | *
|
---|
| 895 | * ColumnConfigureOp --
|
---|
| 896 | *
|
---|
| 897 | * This procedure is called to process a list of configuration
|
---|
| 898 | * options database, in order to reconfigure the one of more
|
---|
| 899 | * entries in the widget.
|
---|
| 900 | *
|
---|
| 901 | * .h entryconfigure node node node node option value
|
---|
| 902 | *
|
---|
| 903 | * Results:
|
---|
| 904 | * A standard Tcl result. If TCL_ERROR is returned, then
|
---|
| 905 | * interp->result contains an error message.
|
---|
| 906 | *
|
---|
| 907 | * Side effects:
|
---|
| 908 | * Configuration information, such as text string, colors, font,
|
---|
| 909 | * etc. get set for tvPtr; old resources get freed, if there
|
---|
| 910 | * were any. The hypertext is redisplayed.
|
---|
| 911 | *
|
---|
| 912 | *----------------------------------------------------------------------
|
---|
| 913 | */
|
---|
| 914 | static int
|
---|
| 915 | ColumnConfigureOp(tvPtr, interp, objc, objv)
|
---|
| 916 | TreeView *tvPtr;
|
---|
| 917 | Tcl_Interp *interp;
|
---|
| 918 | int objc;
|
---|
| 919 | Tcl_Obj *CONST *objv;
|
---|
| 920 | {
|
---|
| 921 | TreeViewColumn *columnPtr;
|
---|
| 922 | int nOptions, start;
|
---|
| 923 | register int i;
|
---|
| 924 |
|
---|
| 925 | /* Figure out where the option value pairs begin */
|
---|
| 926 | for(i = 3; i < objc; i++) {
|
---|
| 927 | if (Blt_ObjIsOption(columnSpecs, objv[i], 0)) {
|
---|
| 928 | break;
|
---|
| 929 | }
|
---|
| 930 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[i], &columnPtr)
|
---|
| 931 | != TCL_OK) {
|
---|
| 932 | return TCL_ERROR;
|
---|
| 933 | }
|
---|
| 934 | }
|
---|
| 935 | start = i;
|
---|
| 936 | nOptions = objc - start;
|
---|
| 937 |
|
---|
| 938 | bltTreeViewUidOption.clientData = tvPtr;
|
---|
| 939 | bltTreeViewIconOption.clientData = tvPtr;
|
---|
| 940 | styleOption.clientData = tvPtr;
|
---|
| 941 | for (i = 3; i < start; i++) {
|
---|
| 942 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[i], &columnPtr)
|
---|
| 943 | != TCL_OK) {
|
---|
| 944 | return TCL_ERROR;
|
---|
| 945 | }
|
---|
| 946 | if (nOptions == 0) {
|
---|
| 947 | return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, columnSpecs,
|
---|
| 948 | (char *)columnPtr, (Tcl_Obj *)NULL, 0);
|
---|
| 949 | } else if (nOptions == 1) {
|
---|
| 950 | return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, columnSpecs,
|
---|
| 951 | (char *)columnPtr, objv[start], 0);
|
---|
| 952 | }
|
---|
| 953 | if (Blt_ConfigureWidgetFromObj(tvPtr->interp, tvPtr->tkwin,
|
---|
| 954 | columnSpecs, nOptions, objv + start, (char *)columnPtr,
|
---|
| 955 | BLT_CONFIG_OBJV_ONLY) != TCL_OK) {
|
---|
| 956 | return TCL_ERROR;
|
---|
| 957 | }
|
---|
| 958 | Blt_TreeViewUpdateColumnGCs(tvPtr, columnPtr);
|
---|
| 959 | }
|
---|
| 960 | /*FIXME: Makes every change redo everything. */
|
---|
| 961 | tvPtr->flags |= (TV_LAYOUT | TV_DIRTY);
|
---|
| 962 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 963 | return TCL_OK;
|
---|
| 964 | }
|
---|
| 965 |
|
---|
| 966 | /*
|
---|
| 967 | *----------------------------------------------------------------------
|
---|
| 968 | *
|
---|
| 969 | * ColumnDeleteOp --
|
---|
| 970 | *
|
---|
| 971 | *----------------------------------------------------------------------
|
---|
| 972 | */
|
---|
| 973 | /*ARGSUSED*/
|
---|
| 974 | static int
|
---|
| 975 | ColumnDeleteOp(tvPtr, interp, objc, objv)
|
---|
| 976 | TreeView *tvPtr;
|
---|
| 977 | Tcl_Interp *interp; /* Not used. */
|
---|
| 978 | int objc;
|
---|
| 979 | Tcl_Obj *CONST *objv;
|
---|
| 980 | {
|
---|
| 981 | TreeViewColumn *columnPtr;
|
---|
| 982 | TreeViewEntry *entryPtr;
|
---|
| 983 | register int i;
|
---|
| 984 |
|
---|
| 985 | for(i = 3; i < objc; i++) {
|
---|
| 986 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[i], &columnPtr)
|
---|
| 987 | != TCL_OK) {
|
---|
| 988 | return TCL_ERROR;
|
---|
| 989 | }
|
---|
| 990 | /* Traverse the tree deleting values associated with the column. */
|
---|
| 991 | for(entryPtr = tvPtr->rootPtr; entryPtr != NULL;
|
---|
| 992 | entryPtr = Blt_TreeViewNextEntry(entryPtr, 0)) {
|
---|
| 993 | if (entryPtr != NULL) {
|
---|
| 994 | TreeViewValue *valuePtr, *lastPtr, *nextPtr;
|
---|
| 995 |
|
---|
| 996 | lastPtr = NULL;
|
---|
| 997 | for (valuePtr = entryPtr->values; valuePtr != NULL;
|
---|
| 998 | valuePtr = nextPtr) {
|
---|
| 999 | nextPtr = valuePtr->nextPtr;
|
---|
| 1000 | if (valuePtr->columnPtr == columnPtr) {
|
---|
| 1001 | Blt_TreeViewDestroyValue(tvPtr, valuePtr);
|
---|
| 1002 | if (lastPtr == NULL) {
|
---|
| 1003 | entryPtr->values = nextPtr;
|
---|
| 1004 | } else {
|
---|
| 1005 | lastPtr->nextPtr = nextPtr;
|
---|
| 1006 | }
|
---|
| 1007 | break;
|
---|
| 1008 | }
|
---|
| 1009 | lastPtr = valuePtr;
|
---|
| 1010 | }
|
---|
| 1011 | }
|
---|
| 1012 | }
|
---|
| 1013 | DestroyColumn(tvPtr, columnPtr);
|
---|
| 1014 | }
|
---|
| 1015 | /* Deleting a column may affect the height of an entry. */
|
---|
| 1016 | tvPtr->flags |= (TV_LAYOUT | TV_DIRTY | TV_RESORT);
|
---|
| 1017 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 1018 | return TCL_OK;
|
---|
| 1019 | }
|
---|
| 1020 |
|
---|
| 1021 | /*
|
---|
| 1022 | *----------------------------------------------------------------------
|
---|
| 1023 | *
|
---|
| 1024 | * ColumnInsertOp --
|
---|
| 1025 | *
|
---|
| 1026 | * Add new columns to the tree.
|
---|
| 1027 | *
|
---|
| 1028 | *----------------------------------------------------------------------
|
---|
| 1029 | */
|
---|
| 1030 | /*ARGSUSED*/
|
---|
| 1031 | static int
|
---|
| 1032 | ColumnInsertOp(tvPtr, interp, objc, objv)
|
---|
| 1033 | TreeView *tvPtr;
|
---|
| 1034 | Tcl_Interp *interp;
|
---|
| 1035 | int objc;
|
---|
| 1036 | Tcl_Obj *CONST *objv;
|
---|
| 1037 | {
|
---|
| 1038 | Blt_ChainLink *beforePtr;
|
---|
| 1039 | Tcl_Obj *CONST *options;
|
---|
| 1040 | TreeViewColumn *columnPtr;
|
---|
| 1041 | TreeViewEntry *entryPtr;
|
---|
| 1042 | int insertPos;
|
---|
| 1043 | int nOptions;
|
---|
| 1044 | int start;
|
---|
| 1045 | register int i;
|
---|
| 1046 |
|
---|
| 1047 | if (Blt_GetPositionFromObj(tvPtr->interp, objv[3], &insertPos) != TCL_OK) {
|
---|
| 1048 | return TCL_ERROR;
|
---|
| 1049 | }
|
---|
| 1050 | if ((insertPos == -1) ||
|
---|
| 1051 | (insertPos >= Blt_ChainGetLength(tvPtr->colChainPtr))) {
|
---|
| 1052 | beforePtr = NULL;
|
---|
| 1053 | } else {
|
---|
| 1054 | beforePtr = Blt_ChainGetNthLink(tvPtr->colChainPtr, insertPos);
|
---|
| 1055 | }
|
---|
| 1056 | /*
|
---|
| 1057 | * Count the column names that follow. Count the arguments until we
|
---|
| 1058 | * spot one that looks like a configuration option (i.e. starts
|
---|
| 1059 | * with a minus ("-")).
|
---|
| 1060 | */
|
---|
| 1061 | for (i = 4; i < objc; i++) {
|
---|
| 1062 | if (Blt_ObjIsOption(columnSpecs, objv[i], 0)) {
|
---|
| 1063 | break;
|
---|
| 1064 | }
|
---|
| 1065 | }
|
---|
| 1066 | start = i;
|
---|
| 1067 | nOptions = objc - i;
|
---|
| 1068 | options = objv + start;
|
---|
| 1069 |
|
---|
| 1070 | for (i = 4; i < start; i++) {
|
---|
| 1071 | if (Blt_TreeViewGetColumn(NULL, tvPtr, objv[i], &columnPtr) == TCL_OK) {
|
---|
| 1072 | Tcl_AppendResult(interp, "column \"", Tcl_GetString(objv[i]),
|
---|
| 1073 | "\" already exists", (char *)NULL);
|
---|
| 1074 | return TCL_ERROR;
|
---|
| 1075 | }
|
---|
| 1076 | columnPtr = CreateColumn(tvPtr, objv[i], nOptions, options);
|
---|
| 1077 | if (columnPtr == NULL) {
|
---|
| 1078 | return TCL_ERROR;
|
---|
| 1079 | }
|
---|
| 1080 | if (beforePtr == NULL) {
|
---|
| 1081 | columnPtr->linkPtr = Blt_ChainAppend(tvPtr->colChainPtr, columnPtr);
|
---|
| 1082 | } else {
|
---|
| 1083 | columnPtr->linkPtr = Blt_ChainNewLink();
|
---|
| 1084 | Blt_ChainSetValue(columnPtr->linkPtr, columnPtr);
|
---|
| 1085 | Blt_ChainLinkBefore(tvPtr->colChainPtr, columnPtr->linkPtr,
|
---|
| 1086 | beforePtr);
|
---|
| 1087 | }
|
---|
| 1088 | /*
|
---|
| 1089 | * Traverse the tree adding column entries where needed.
|
---|
| 1090 | */
|
---|
| 1091 | for(entryPtr = tvPtr->rootPtr; entryPtr != NULL;
|
---|
| 1092 | entryPtr = Blt_TreeViewNextEntry(entryPtr, 0)) {
|
---|
| 1093 | Blt_TreeViewAddValue(entryPtr, columnPtr);
|
---|
| 1094 | }
|
---|
| 1095 | Blt_TreeViewTraceColumn(tvPtr, columnPtr);
|
---|
| 1096 | }
|
---|
| 1097 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 1098 | return TCL_OK;
|
---|
| 1099 | }
|
---|
| 1100 |
|
---|
| 1101 |
|
---|
| 1102 |
|
---|
| 1103 | /*
|
---|
| 1104 | *----------------------------------------------------------------------
|
---|
| 1105 | *
|
---|
| 1106 | * ColumnCurrentOp --
|
---|
| 1107 | *
|
---|
| 1108 | * Make the rule to appear active.
|
---|
| 1109 | *
|
---|
| 1110 | *----------------------------------------------------------------------
|
---|
| 1111 | */
|
---|
| 1112 | /*ARGSUSED*/
|
---|
| 1113 | static int
|
---|
| 1114 | ColumnCurrentOp(tvPtr, interp, objc, objv)
|
---|
| 1115 | TreeView *tvPtr;
|
---|
| 1116 | Tcl_Interp *interp;
|
---|
| 1117 | int objc; /* Not used. */
|
---|
| 1118 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1119 | {
|
---|
| 1120 | ClientData context;
|
---|
| 1121 | TreeViewColumn *columnPtr;
|
---|
| 1122 |
|
---|
| 1123 | columnPtr = NULL;
|
---|
| 1124 | context = Blt_GetCurrentContext(tvPtr->bindTable);
|
---|
| 1125 | if ((context == ITEM_COLUMN_TITLE) || (context == ITEM_COLUMN_RULE)) {
|
---|
| 1126 | columnPtr = Blt_GetCurrentItem(tvPtr->bindTable);
|
---|
| 1127 | }
|
---|
| 1128 | if (context >= ITEM_STYLE) {
|
---|
| 1129 | TreeViewValue *valuePtr = context;
|
---|
| 1130 |
|
---|
| 1131 | columnPtr = valuePtr->columnPtr;
|
---|
| 1132 | }
|
---|
| 1133 | if (columnPtr != NULL) {
|
---|
| 1134 | Tcl_SetResult(interp, columnPtr->key, TCL_VOLATILE);
|
---|
| 1135 | }
|
---|
| 1136 | return TCL_OK;
|
---|
| 1137 | }
|
---|
| 1138 |
|
---|
| 1139 | /*
|
---|
| 1140 | *----------------------------------------------------------------------
|
---|
| 1141 | *
|
---|
| 1142 | * ColumnInvokeOp --
|
---|
| 1143 | *
|
---|
| 1144 | * This procedure is called to invoke a column command.
|
---|
| 1145 | *
|
---|
| 1146 | * .h column invoke columnName
|
---|
| 1147 | *
|
---|
| 1148 | * Results:
|
---|
| 1149 | * A standard Tcl result. If TCL_ERROR is returned, then
|
---|
| 1150 | * interp->result contains an error message.
|
---|
| 1151 | *
|
---|
| 1152 | *----------------------------------------------------------------------
|
---|
| 1153 | */
|
---|
| 1154 | /*ARGSUSED*/
|
---|
| 1155 | static int
|
---|
| 1156 | ColumnInvokeOp(tvPtr, interp, objc, objv)
|
---|
| 1157 | TreeView *tvPtr;
|
---|
| 1158 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1159 | int objc;
|
---|
| 1160 | Tcl_Obj *CONST *objv;
|
---|
| 1161 | {
|
---|
| 1162 | TreeViewColumn *columnPtr;
|
---|
| 1163 | char *string;
|
---|
| 1164 |
|
---|
| 1165 | string = Tcl_GetString(objv[3]);
|
---|
| 1166 | if (string[0] == '\0') {
|
---|
| 1167 | return TCL_OK;
|
---|
| 1168 | }
|
---|
| 1169 | if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr) != TCL_OK) {
|
---|
| 1170 | return TCL_ERROR;
|
---|
| 1171 | }
|
---|
| 1172 | if ((columnPtr->state == STATE_NORMAL) && (columnPtr->titleCmd != NULL)) {
|
---|
| 1173 | int result;
|
---|
| 1174 |
|
---|
| 1175 | Tcl_Preserve(tvPtr);
|
---|
| 1176 | Tcl_Preserve(columnPtr);
|
---|
| 1177 | result = Tcl_GlobalEval(interp, columnPtr->titleCmd);
|
---|
| 1178 | Tcl_Release(columnPtr);
|
---|
| 1179 | Tcl_Release(tvPtr);
|
---|
| 1180 | return result;
|
---|
| 1181 | }
|
---|
| 1182 | return TCL_OK;
|
---|
| 1183 | }
|
---|
| 1184 |
|
---|
| 1185 | /*
|
---|
| 1186 | *----------------------------------------------------------------------
|
---|
| 1187 | *
|
---|
| 1188 | * ColumnMoveOp --
|
---|
| 1189 | *
|
---|
| 1190 | * Move a column.
|
---|
| 1191 | *
|
---|
| 1192 | * .h column move field1 position
|
---|
| 1193 | *----------------------------------------------------------------------
|
---|
| 1194 | */
|
---|
| 1195 |
|
---|
| 1196 | /*
|
---|
| 1197 | *----------------------------------------------------------------------
|
---|
| 1198 | *
|
---|
| 1199 | * ColumnNamesOp --
|
---|
| 1200 | *
|
---|
| 1201 | *----------------------------------------------------------------------
|
---|
| 1202 | */
|
---|
| 1203 | /*ARGSUSED*/
|
---|
| 1204 | static int
|
---|
| 1205 | ColumnNamesOp(tvPtr, interp, objc, objv)
|
---|
| 1206 | TreeView *tvPtr;
|
---|
| 1207 | Tcl_Interp *interp;
|
---|
| 1208 | int objc; /* Not used. */
|
---|
| 1209 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1210 | {
|
---|
| 1211 | Blt_ChainLink *linkPtr;
|
---|
| 1212 | Tcl_Obj *listObjPtr, *objPtr;
|
---|
| 1213 | TreeViewColumn *columnPtr;
|
---|
| 1214 |
|
---|
| 1215 | listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
|
---|
| 1216 | for(linkPtr = Blt_ChainFirstLink(tvPtr->colChainPtr); linkPtr != NULL;
|
---|
| 1217 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
| 1218 | columnPtr = Blt_ChainGetValue(linkPtr);
|
---|
| 1219 | objPtr = Tcl_NewStringObj(columnPtr->key, -1);
|
---|
| 1220 | Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
|
---|
| 1221 | }
|
---|
| 1222 | Tcl_SetObjResult(interp, listObjPtr);
|
---|
| 1223 | return TCL_OK;
|
---|
| 1224 | }
|
---|
| 1225 |
|
---|
| 1226 | /*ARGSUSED*/
|
---|
| 1227 | static int
|
---|
| 1228 | ColumnNearestOp(tvPtr, interp, objc, objv)
|
---|
| 1229 | TreeView *tvPtr;
|
---|
| 1230 | Tcl_Interp *interp;
|
---|
| 1231 | int objc; /* Not used. */
|
---|
| 1232 | Tcl_Obj *CONST *objv;
|
---|
| 1233 | {
|
---|
| 1234 | int x, y; /* Screen coordinates of the test point. */
|
---|
| 1235 | TreeViewColumn *columnPtr;
|
---|
| 1236 | ClientData context;
|
---|
| 1237 | int checkTitle;
|
---|
| 1238 | #ifdef notdef
|
---|
| 1239 | int isRoot;
|
---|
| 1240 |
|
---|
| 1241 | isRoot = FALSE;
|
---|
| 1242 | string = Tcl_GetString(objv[3]);
|
---|
| 1243 |
|
---|
| 1244 | if (strcmp("-root", string) == 0) {
|
---|
| 1245 | isRoot = TRUE;
|
---|
| 1246 | objv++, objc--;
|
---|
| 1247 | }
|
---|
| 1248 | if (objc != 5) {
|
---|
| 1249 | Tcl_AppendResult(interp, "wrong # args: should be \"",
|
---|
| 1250 | Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]),
|
---|
| 1251 | Tcl_GetString(objv[2]), " ?-root? x y\"", (char *)NULL);
|
---|
| 1252 | return TCL_ERROR;
|
---|
| 1253 |
|
---|
| 1254 | }
|
---|
| 1255 | #endif
|
---|
| 1256 | if (Tk_GetPixelsFromObj(interp, tvPtr->tkwin, objv[3], &x) != TCL_OK) {
|
---|
| 1257 | return TCL_ERROR;
|
---|
| 1258 | }
|
---|
| 1259 | y = 0;
|
---|
| 1260 | checkTitle = FALSE;
|
---|
| 1261 | if (objc == 5) {
|
---|
| 1262 | if (Tk_GetPixelsFromObj(interp, tvPtr->tkwin, objv[4], &y) != TCL_OK) {
|
---|
| 1263 | return TCL_ERROR;
|
---|
| 1264 | }
|
---|
| 1265 | checkTitle = TRUE;
|
---|
| 1266 | }
|
---|
| 1267 | columnPtr = Blt_TreeViewNearestColumn(tvPtr, x, y, &context);
|
---|
| 1268 | if ((checkTitle) && (context == NULL)) {
|
---|
| 1269 | columnPtr = NULL;
|
---|
| 1270 | }
|
---|
| 1271 | if (columnPtr != NULL) {
|
---|
| 1272 | Tcl_SetResult(interp, columnPtr->key, TCL_VOLATILE);
|
---|
| 1273 | }
|
---|
| 1274 | return TCL_OK;
|
---|
| 1275 | }
|
---|
| 1276 |
|
---|
| 1277 | static void
|
---|
| 1278 | UpdateMark(tvPtr, newMark)
|
---|
| 1279 | TreeView *tvPtr;
|
---|
| 1280 | int newMark;
|
---|
| 1281 | {
|
---|
| 1282 | Drawable drawable;
|
---|
| 1283 | TreeViewColumn *columnPtr;
|
---|
| 1284 | int dx;
|
---|
| 1285 | int width;
|
---|
| 1286 |
|
---|
| 1287 | columnPtr = tvPtr->resizeColumnPtr;
|
---|
| 1288 | if (columnPtr == NULL) {
|
---|
| 1289 | return;
|
---|
| 1290 | }
|
---|
| 1291 | drawable = Tk_WindowId(tvPtr->tkwin);
|
---|
| 1292 | if (drawable == None) {
|
---|
| 1293 | return;
|
---|
| 1294 | }
|
---|
| 1295 |
|
---|
| 1296 | /* Erase any existing rule. */
|
---|
| 1297 | if (tvPtr->flags & TV_RULE_ACTIVE) {
|
---|
| 1298 | Blt_TreeViewDrawRule(tvPtr, columnPtr, drawable);
|
---|
| 1299 | }
|
---|
| 1300 |
|
---|
| 1301 | dx = newMark - tvPtr->ruleAnchor;
|
---|
| 1302 | width = columnPtr->width -
|
---|
| 1303 | (PADDING(columnPtr->pad) + 2 * columnPtr->borderWidth);
|
---|
| 1304 | if ((columnPtr->reqMin > 0) && ((width + dx) < columnPtr->reqMin)) {
|
---|
| 1305 | dx = columnPtr->reqMin - width;
|
---|
| 1306 | }
|
---|
| 1307 | if ((columnPtr->reqMax > 0) && ((width + dx) > columnPtr->reqMax)) {
|
---|
| 1308 | dx = columnPtr->reqMax - width;
|
---|
| 1309 | }
|
---|
| 1310 | if ((width + dx) < 4) {
|
---|
| 1311 | dx = 4 - width;
|
---|
| 1312 | }
|
---|
| 1313 | tvPtr->ruleMark = tvPtr->ruleAnchor + dx;
|
---|
| 1314 |
|
---|
| 1315 | /* Redraw the rule if required. */
|
---|
| 1316 | if (tvPtr->flags & TV_RULE_NEEDED) {
|
---|
| 1317 | Blt_TreeViewDrawRule(tvPtr, columnPtr, drawable);
|
---|
| 1318 | }
|
---|
| 1319 | }
|
---|
| 1320 |
|
---|
| 1321 | /*
|
---|
| 1322 | *----------------------------------------------------------------------
|
---|
| 1323 | *
|
---|
| 1324 | * ResizeActivateOp --
|
---|
| 1325 | *
|
---|
| 1326 | * Turns on/off the resize cursor.
|
---|
| 1327 | *
|
---|
| 1328 | *----------------------------------------------------------------------
|
---|
| 1329 | */
|
---|
| 1330 | /*ARGSUSED*/
|
---|
| 1331 | static int
|
---|
| 1332 | ResizeActivateOp(tvPtr, interp, objc, objv)
|
---|
| 1333 | TreeView *tvPtr;
|
---|
| 1334 | Tcl_Interp *interp;
|
---|
| 1335 | int objc; /* Not used. */
|
---|
| 1336 | Tcl_Obj *CONST *objv;
|
---|
| 1337 | {
|
---|
| 1338 | TreeViewColumn *columnPtr;
|
---|
| 1339 | char *string;
|
---|
| 1340 |
|
---|
| 1341 | string = Tcl_GetString(objv[4]);
|
---|
| 1342 | if (string[0] == '\0') {
|
---|
| 1343 | if (tvPtr->cursor != None) {
|
---|
| 1344 | Tk_DefineCursor(tvPtr->tkwin, tvPtr->cursor);
|
---|
| 1345 | } else {
|
---|
| 1346 | Tk_UndefineCursor(tvPtr->tkwin);
|
---|
| 1347 | }
|
---|
| 1348 | tvPtr->resizeColumnPtr = NULL;
|
---|
| 1349 | } else if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr)
|
---|
| 1350 | == TCL_OK) {
|
---|
| 1351 | if (tvPtr->resizeCursor != None) {
|
---|
| 1352 | Tk_DefineCursor(tvPtr->tkwin, tvPtr->resizeCursor);
|
---|
| 1353 | }
|
---|
| 1354 | tvPtr->resizeColumnPtr = columnPtr;
|
---|
| 1355 | } else {
|
---|
| 1356 | return TCL_ERROR;
|
---|
| 1357 | }
|
---|
| 1358 | return TCL_OK;
|
---|
| 1359 | }
|
---|
| 1360 |
|
---|
| 1361 | /*
|
---|
| 1362 | *----------------------------------------------------------------------
|
---|
| 1363 | *
|
---|
| 1364 | * ResizeAnchorOp --
|
---|
| 1365 | *
|
---|
| 1366 | * Set the anchor for the resize.
|
---|
| 1367 | *
|
---|
| 1368 | *----------------------------------------------------------------------
|
---|
| 1369 | */
|
---|
| 1370 | /*ARGSUSED*/
|
---|
| 1371 | static int
|
---|
| 1372 | ResizeAnchorOp(tvPtr, interp, objc, objv)
|
---|
| 1373 | TreeView *tvPtr;
|
---|
| 1374 | Tcl_Interp *interp;
|
---|
| 1375 | int objc; /* Not used. */
|
---|
| 1376 | Tcl_Obj *CONST *objv;
|
---|
| 1377 | {
|
---|
| 1378 | int x;
|
---|
| 1379 |
|
---|
| 1380 | if (Tcl_GetIntFromObj(NULL, objv[4], &x) != TCL_OK) {
|
---|
| 1381 | return TCL_ERROR;
|
---|
| 1382 | }
|
---|
| 1383 | tvPtr->ruleAnchor = x;
|
---|
| 1384 | tvPtr->flags |= TV_RULE_NEEDED;
|
---|
| 1385 | UpdateMark(tvPtr, x);
|
---|
| 1386 | return TCL_OK;
|
---|
| 1387 | }
|
---|
| 1388 |
|
---|
| 1389 | /*
|
---|
| 1390 | *----------------------------------------------------------------------
|
---|
| 1391 | *
|
---|
| 1392 | * ResizeMarkOp --
|
---|
| 1393 | *
|
---|
| 1394 | * Sets the resize mark. The distance between the mark and the anchor
|
---|
| 1395 | * is the delta to change the width of the active column.
|
---|
| 1396 | *
|
---|
| 1397 | *----------------------------------------------------------------------
|
---|
| 1398 | */
|
---|
| 1399 | /*ARGSUSED*/
|
---|
| 1400 | static int
|
---|
| 1401 | ResizeMarkOp(tvPtr, interp, objc, objv)
|
---|
| 1402 | TreeView *tvPtr;
|
---|
| 1403 | Tcl_Interp *interp;
|
---|
| 1404 | int objc; /* Not used. */
|
---|
| 1405 | Tcl_Obj *CONST *objv;
|
---|
| 1406 | {
|
---|
| 1407 | int x;
|
---|
| 1408 |
|
---|
| 1409 | if (Tcl_GetIntFromObj(NULL, objv[4], &x) != TCL_OK) {
|
---|
| 1410 | return TCL_ERROR;
|
---|
| 1411 | }
|
---|
| 1412 | tvPtr->flags |= TV_RULE_NEEDED;
|
---|
| 1413 | UpdateMark(tvPtr, x);
|
---|
| 1414 | return TCL_OK;
|
---|
| 1415 | }
|
---|
| 1416 |
|
---|
| 1417 | /*
|
---|
| 1418 | *----------------------------------------------------------------------
|
---|
| 1419 | *
|
---|
| 1420 | * ResizeSetOp --
|
---|
| 1421 | *
|
---|
| 1422 | * Returns the new width of the column including the resize delta.
|
---|
| 1423 | *
|
---|
| 1424 | *----------------------------------------------------------------------
|
---|
| 1425 | */
|
---|
| 1426 | /*ARGSUSED*/
|
---|
| 1427 | static int
|
---|
| 1428 | ResizeSetOp(tvPtr, interp, objc, objv)
|
---|
| 1429 | TreeView *tvPtr;
|
---|
| 1430 | Tcl_Interp *interp;
|
---|
| 1431 | int objc; /* Not used. */
|
---|
| 1432 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1433 | {
|
---|
| 1434 | tvPtr->flags &= ~TV_RULE_NEEDED;
|
---|
| 1435 | UpdateMark(tvPtr, tvPtr->ruleMark);
|
---|
| 1436 | if (tvPtr->resizeColumnPtr != NULL) {
|
---|
| 1437 | int width, delta;
|
---|
| 1438 | TreeViewColumn *columnPtr;
|
---|
| 1439 |
|
---|
| 1440 | columnPtr = tvPtr->resizeColumnPtr;
|
---|
| 1441 | delta = (tvPtr->ruleMark - tvPtr->ruleAnchor);
|
---|
| 1442 | width = tvPtr->resizeColumnPtr->width + delta -
|
---|
| 1443 | (PADDING(columnPtr->pad) + 2 * columnPtr->borderWidth) - 1;
|
---|
| 1444 | Tcl_SetObjResult(interp, Tcl_NewIntObj(width));
|
---|
| 1445 | }
|
---|
| 1446 | return TCL_OK;
|
---|
| 1447 | }
|
---|
| 1448 |
|
---|
| 1449 | static Blt_OpSpec resizeOps[] =
|
---|
| 1450 | {
|
---|
| 1451 | {"activate", 2, (Blt_Op)ResizeActivateOp, 5, 5, "column"},
|
---|
| 1452 | {"anchor", 2, (Blt_Op)ResizeAnchorOp, 5, 5, "x"},
|
---|
| 1453 | {"mark", 1, (Blt_Op)ResizeMarkOp, 5, 5, "x"},
|
---|
| 1454 | {"set", 1, (Blt_Op)ResizeSetOp, 4, 4, "",},
|
---|
| 1455 | };
|
---|
| 1456 |
|
---|
| 1457 | static int nResizeOps = sizeof(resizeOps) / sizeof(Blt_OpSpec);
|
---|
| 1458 |
|
---|
| 1459 | /*
|
---|
| 1460 | *----------------------------------------------------------------------
|
---|
| 1461 | *
|
---|
| 1462 | * ColumnResizeOp --
|
---|
| 1463 | *
|
---|
| 1464 | *----------------------------------------------------------------------
|
---|
| 1465 | */
|
---|
| 1466 | static int
|
---|
| 1467 | ColumnResizeOp(tvPtr, interp, objc, objv)
|
---|
| 1468 | TreeView *tvPtr;
|
---|
| 1469 | Tcl_Interp *interp;
|
---|
| 1470 | int objc;
|
---|
| 1471 | Tcl_Obj *CONST *objv;
|
---|
| 1472 | {
|
---|
| 1473 | Blt_Op proc;
|
---|
| 1474 | int result;
|
---|
| 1475 |
|
---|
| 1476 | proc = Blt_GetOpFromObj(interp, nResizeOps, resizeOps, BLT_OP_ARG3,
|
---|
| 1477 | objc, objv,0);
|
---|
| 1478 | if (proc == NULL) {
|
---|
| 1479 | return TCL_ERROR;
|
---|
| 1480 | }
|
---|
| 1481 | result = (*proc) (tvPtr, interp, objc, objv);
|
---|
| 1482 | return result;
|
---|
| 1483 | }
|
---|
| 1484 |
|
---|
| 1485 |
|
---|
| 1486 | static Blt_OpSpec columnOps[] =
|
---|
| 1487 | {
|
---|
| 1488 | {"activate", 1, (Blt_Op)ColumnActivateOp, 3, 4, "?field?",},
|
---|
| 1489 | {"bind", 1, (Blt_Op)ColumnBindOp, 4, 6, "tagName ?sequence command?",},
|
---|
| 1490 | {"cget", 2, (Blt_Op)ColumnCgetOp, 5, 5, "field option",},
|
---|
| 1491 | {"configure", 2, (Blt_Op)ColumnConfigureOp, 4, 0,
|
---|
| 1492 | "field ?option value?...",},
|
---|
| 1493 | {"current", 2, (Blt_Op)ColumnCurrentOp, 3, 3, "",},
|
---|
| 1494 | {"delete", 1, (Blt_Op)ColumnDeleteOp, 3, 0, "?field...?",},
|
---|
| 1495 | {"highlight", 1, (Blt_Op)ColumnActivateOp, 3, 4, "?field?",},
|
---|
| 1496 | {"insert", 3, (Blt_Op)ColumnInsertOp, 5, 0,
|
---|
| 1497 | "position field ?field...? ?option value?...",},
|
---|
| 1498 | {"invoke", 3, (Blt_Op)ColumnInvokeOp, 4, 4, "field",},
|
---|
| 1499 | {"names", 2, (Blt_Op)ColumnNamesOp, 3, 3, "",},
|
---|
| 1500 | {"nearest", 2, (Blt_Op)ColumnNearestOp, 4, 5, "x ?y?",},
|
---|
| 1501 | {"resize", 1, (Blt_Op)ColumnResizeOp, 3, 0, "arg",},
|
---|
| 1502 | };
|
---|
| 1503 | static int nColumnOps = sizeof(columnOps) / sizeof(Blt_OpSpec);
|
---|
| 1504 |
|
---|
| 1505 | /*
|
---|
| 1506 | *----------------------------------------------------------------------
|
---|
| 1507 | *
|
---|
| 1508 | * Blt_TreeViewColumnOp --
|
---|
| 1509 | *
|
---|
| 1510 | *----------------------------------------------------------------------
|
---|
| 1511 | */
|
---|
| 1512 | int
|
---|
| 1513 | Blt_TreeViewColumnOp(tvPtr, interp, objc, objv)
|
---|
| 1514 | TreeView *tvPtr;
|
---|
| 1515 | Tcl_Interp *interp;
|
---|
| 1516 | int objc;
|
---|
| 1517 | Tcl_Obj *CONST *objv;
|
---|
| 1518 | {
|
---|
| 1519 | Blt_Op proc;
|
---|
| 1520 | int result;
|
---|
| 1521 |
|
---|
| 1522 | proc = Blt_GetOpFromObj(interp, nColumnOps, columnOps, BLT_OP_ARG2,
|
---|
| 1523 | objc, objv,0);
|
---|
| 1524 | if (proc == NULL) {
|
---|
| 1525 | return TCL_ERROR;
|
---|
| 1526 | }
|
---|
| 1527 | result = (*proc) (tvPtr, interp, objc, objv);
|
---|
| 1528 | return result;
|
---|
| 1529 | }
|
---|
| 1530 |
|
---|
| 1531 |
|
---|
| 1532 | static int
|
---|
| 1533 | InvokeCompare(tvPtr, e1Ptr, e2Ptr, command)
|
---|
| 1534 | TreeView *tvPtr;
|
---|
| 1535 | TreeViewEntry *e1Ptr, *e2Ptr;
|
---|
| 1536 | char *command;
|
---|
| 1537 | {
|
---|
| 1538 | int result;
|
---|
| 1539 | Tcl_Obj *objv[8];
|
---|
| 1540 | int i;
|
---|
| 1541 |
|
---|
| 1542 | objv[0] = Tcl_NewStringObj(command, -1);
|
---|
| 1543 | objv[1] = Tcl_NewStringObj(Tk_PathName(tvPtr->tkwin), -1);
|
---|
| 1544 | objv[2] = Tcl_NewIntObj(Blt_TreeNodeId(e1Ptr->node));
|
---|
| 1545 | objv[3] = Tcl_NewIntObj(Blt_TreeNodeId(e2Ptr->node));
|
---|
| 1546 | objv[4] = Tcl_NewStringObj(tvPtr->sortColumnPtr->key, -1);
|
---|
| 1547 |
|
---|
| 1548 | if (tvPtr->flatView) {
|
---|
| 1549 | objv[5] = Tcl_NewStringObj(e1Ptr->fullName, -1);
|
---|
| 1550 | objv[6] = Tcl_NewStringObj(e2Ptr->fullName, -1);
|
---|
| 1551 | } else {
|
---|
| 1552 | objv[5] = Tcl_NewStringObj(GETLABEL(e1Ptr), -1);
|
---|
| 1553 | objv[6] = Tcl_NewStringObj(GETLABEL(e2Ptr), -1);
|
---|
| 1554 | }
|
---|
| 1555 | for(i = 0; i < 7; i++) {
|
---|
| 1556 | Tcl_IncrRefCount(objv[i]);
|
---|
| 1557 | }
|
---|
| 1558 | objv[7] = NULL;
|
---|
| 1559 | result = Tcl_EvalObjv(tvPtr->interp, 7, objv, TCL_EVAL_GLOBAL);
|
---|
| 1560 | if ((result != TCL_OK) ||
|
---|
| 1561 | (Tcl_GetIntFromObj(tvPtr->interp, Tcl_GetObjResult(tvPtr->interp),
|
---|
| 1562 | &result) != TCL_OK)) {
|
---|
| 1563 | Tcl_BackgroundError(tvPtr->interp);
|
---|
| 1564 | }
|
---|
| 1565 | for(i = 0; i < 7; i++) {
|
---|
| 1566 | Tcl_DecrRefCount(objv[i]);
|
---|
| 1567 | }
|
---|
| 1568 | Tcl_ResetResult(tvPtr->interp);
|
---|
| 1569 | return result;
|
---|
| 1570 | }
|
---|
| 1571 |
|
---|
| 1572 | static TreeView *treeViewInstance;
|
---|
| 1573 |
|
---|
| 1574 | static int
|
---|
| 1575 | CompareEntries(a, b)
|
---|
| 1576 | CONST void *a, *b;
|
---|
| 1577 | {
|
---|
| 1578 | TreeView *tvPtr;
|
---|
| 1579 | TreeViewEntry **e1PtrPtr = (TreeViewEntry **)a;
|
---|
| 1580 | TreeViewEntry **e2PtrPtr = (TreeViewEntry **)b;
|
---|
| 1581 | Tcl_Obj *obj1, *obj2;
|
---|
| 1582 | char *s1, *s2;
|
---|
| 1583 | int result;
|
---|
| 1584 |
|
---|
| 1585 | tvPtr = (*e1PtrPtr)->tvPtr;
|
---|
| 1586 | obj1 = (*e1PtrPtr)->dataObjPtr;
|
---|
| 1587 | obj2 = (*e2PtrPtr)->dataObjPtr;
|
---|
| 1588 | s1 = Tcl_GetString(obj1);
|
---|
| 1589 | s2 = Tcl_GetString(obj2);
|
---|
| 1590 | result = 0;
|
---|
| 1591 | switch (tvPtr->sortType) {
|
---|
| 1592 | case SORT_TYPE_ASCII:
|
---|
| 1593 | result = strcmp(s1, s2);
|
---|
| 1594 | break;
|
---|
| 1595 |
|
---|
| 1596 | case SORT_TYPE_COMMAND:
|
---|
| 1597 | {
|
---|
| 1598 | char *cmd;
|
---|
| 1599 |
|
---|
| 1600 | cmd = tvPtr->sortColumnPtr->sortCmd;
|
---|
| 1601 | if (cmd == NULL) {
|
---|
| 1602 | cmd = tvPtr->sortCmd;
|
---|
| 1603 | }
|
---|
| 1604 | if (cmd == NULL) {
|
---|
| 1605 | result = Blt_DictionaryCompare(s1, s2);
|
---|
| 1606 | } else {
|
---|
| 1607 | result = InvokeCompare(tvPtr, *e1PtrPtr, *e2PtrPtr, cmd);
|
---|
| 1608 | }
|
---|
| 1609 | }
|
---|
| 1610 | break;
|
---|
| 1611 |
|
---|
| 1612 | case SORT_TYPE_DICTIONARY:
|
---|
| 1613 | result = Blt_DictionaryCompare(s1, s2);
|
---|
| 1614 | break;
|
---|
| 1615 |
|
---|
| 1616 | case SORT_TYPE_INTEGER:
|
---|
| 1617 | {
|
---|
| 1618 | int i1, i2;
|
---|
| 1619 |
|
---|
| 1620 | if (Tcl_GetIntFromObj(NULL, obj1, &i1)==TCL_OK) {
|
---|
| 1621 | if (Tcl_GetIntFromObj(NULL, obj2, &i2) == TCL_OK) {
|
---|
| 1622 | result = i1 - i2;
|
---|
| 1623 | } else {
|
---|
| 1624 | result = -1;
|
---|
| 1625 | }
|
---|
| 1626 | } else if (Tcl_GetIntFromObj(NULL, obj2, &i2) == TCL_OK) {
|
---|
| 1627 | result = 1;
|
---|
| 1628 | } else {
|
---|
| 1629 | result = Blt_DictionaryCompare(s1, s2);
|
---|
| 1630 | }
|
---|
| 1631 | }
|
---|
| 1632 | break;
|
---|
| 1633 |
|
---|
| 1634 | case SORT_TYPE_REAL:
|
---|
| 1635 | {
|
---|
| 1636 | double r1, r2;
|
---|
| 1637 |
|
---|
| 1638 | if (Tcl_GetDoubleFromObj(NULL, obj1, &r1) == TCL_OK) {
|
---|
| 1639 | if (Tcl_GetDoubleFromObj(NULL, obj2, &r2) == TCL_OK) {
|
---|
| 1640 | result = (r1 < r2) ? -1 : (r1 > r2) ? 1 : 0;
|
---|
| 1641 | } else {
|
---|
| 1642 | result = -1;
|
---|
| 1643 | }
|
---|
| 1644 | } else if (Tcl_GetDoubleFromObj(NULL, obj2, &r2) == TCL_OK) {
|
---|
| 1645 | result = 1;
|
---|
| 1646 | } else {
|
---|
| 1647 | result = Blt_DictionaryCompare(s1, s2);
|
---|
| 1648 | }
|
---|
| 1649 | }
|
---|
| 1650 | break;
|
---|
| 1651 | }
|
---|
| 1652 | if (tvPtr->sortDecreasing) {
|
---|
| 1653 | return -result;
|
---|
| 1654 | }
|
---|
| 1655 | return result;
|
---|
| 1656 | }
|
---|
| 1657 |
|
---|
| 1658 |
|
---|
| 1659 | /*
|
---|
| 1660 | *----------------------------------------------------------------------
|
---|
| 1661 | *
|
---|
| 1662 | * CompareNodes --
|
---|
| 1663 | *
|
---|
| 1664 | * Comparison routine (used by qsort) to sort a chain of subnodes.
|
---|
| 1665 | *
|
---|
| 1666 | * Results:
|
---|
| 1667 | * 1 is the first is greater, -1 is the second is greater, 0
|
---|
| 1668 | * if equal.
|
---|
| 1669 | *
|
---|
| 1670 | *----------------------------------------------------------------------
|
---|
| 1671 | */
|
---|
| 1672 | static int
|
---|
| 1673 | CompareNodes(n1Ptr, n2Ptr)
|
---|
| 1674 | Blt_TreeNode *n1Ptr, *n2Ptr;
|
---|
| 1675 | {
|
---|
| 1676 | TreeView *tvPtr = treeViewInstance;
|
---|
| 1677 | TreeViewEntry *e1Ptr, *e2Ptr;
|
---|
| 1678 |
|
---|
| 1679 | e1Ptr = Blt_NodeToEntry(tvPtr, *n1Ptr);
|
---|
| 1680 | e2Ptr = Blt_NodeToEntry(tvPtr, *n2Ptr);
|
---|
| 1681 |
|
---|
| 1682 | /* Fetch the data for sorting. */
|
---|
| 1683 | if (tvPtr->sortType == SORT_TYPE_COMMAND) {
|
---|
| 1684 | e1Ptr->dataObjPtr = Tcl_NewIntObj(Blt_TreeNodeId(*n1Ptr));
|
---|
| 1685 | e2Ptr->dataObjPtr = Tcl_NewIntObj(Blt_TreeNodeId(*n2Ptr));
|
---|
| 1686 | } else if (tvPtr->sortColumnPtr == &tvPtr->treeColumn) {
|
---|
| 1687 | Tcl_DString dString;
|
---|
| 1688 |
|
---|
| 1689 | Tcl_DStringInit(&dString);
|
---|
| 1690 | if (e1Ptr->fullName == NULL) {
|
---|
| 1691 | Blt_TreeViewGetFullName(tvPtr, e1Ptr, TRUE, &dString);
|
---|
| 1692 | e1Ptr->fullName = Blt_Strdup(Tcl_DStringValue(&dString));
|
---|
| 1693 | }
|
---|
| 1694 | e1Ptr->dataObjPtr = Tcl_NewStringObj(e1Ptr->fullName, -1);
|
---|
| 1695 | if (e2Ptr->fullName == NULL) {
|
---|
| 1696 | Blt_TreeViewGetFullName(tvPtr, e2Ptr, TRUE, &dString);
|
---|
| 1697 | e2Ptr->fullName = Blt_Strdup(Tcl_DStringValue(&dString));
|
---|
| 1698 | }
|
---|
| 1699 | e2Ptr->dataObjPtr = Tcl_NewStringObj(e2Ptr->fullName, -1);
|
---|
| 1700 | Tcl_DStringFree(&dString);
|
---|
| 1701 | } else {
|
---|
| 1702 | Blt_TreeKey key;
|
---|
| 1703 | Tcl_Obj *objPtr;
|
---|
| 1704 |
|
---|
| 1705 | key = tvPtr->sortColumnPtr->key;
|
---|
| 1706 | if (Blt_TreeViewGetData(e1Ptr, key, &objPtr) != TCL_OK) {
|
---|
| 1707 | e1Ptr->dataObjPtr = bltEmptyStringObjPtr;
|
---|
| 1708 | } else {
|
---|
| 1709 | e1Ptr->dataObjPtr = objPtr;
|
---|
| 1710 | }
|
---|
| 1711 | if (Blt_TreeViewGetData(e2Ptr, key, &objPtr) != TCL_OK) {
|
---|
| 1712 | e2Ptr->dataObjPtr = bltEmptyStringObjPtr;
|
---|
| 1713 | } else {
|
---|
| 1714 | e2Ptr->dataObjPtr = objPtr;
|
---|
| 1715 | }
|
---|
| 1716 | }
|
---|
| 1717 | return CompareEntries(&e1Ptr, &e2Ptr);
|
---|
| 1718 | }
|
---|
| 1719 |
|
---|
| 1720 | static int
|
---|
| 1721 | SortAutoOp(tvPtr, interp, objc, objv)
|
---|
| 1722 | TreeView *tvPtr;
|
---|
| 1723 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1724 | int objc;
|
---|
| 1725 | Tcl_Obj *CONST *objv;
|
---|
| 1726 | {
|
---|
| 1727 |
|
---|
| 1728 | if (objc == 4) {
|
---|
| 1729 | int bool;
|
---|
| 1730 | int isAuto;
|
---|
| 1731 |
|
---|
| 1732 | isAuto = ((tvPtr->flags & TV_SORT_AUTO) != 0);
|
---|
| 1733 | if (Tcl_GetBooleanFromObj(interp, objv[3], &bool) != TCL_OK) {
|
---|
| 1734 | return TCL_ERROR;
|
---|
| 1735 | }
|
---|
| 1736 | if (isAuto != bool) {
|
---|
| 1737 | tvPtr->flags |= (TV_LAYOUT | TV_DIRTY | TV_RESORT);
|
---|
| 1738 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 1739 | }
|
---|
| 1740 | if (bool) {
|
---|
| 1741 | tvPtr->flags |= TV_SORT_AUTO;
|
---|
| 1742 | } else {
|
---|
| 1743 | tvPtr->flags &= ~TV_SORT_AUTO;
|
---|
| 1744 | }
|
---|
| 1745 | }
|
---|
| 1746 | Tcl_SetObjResult(interp, Tcl_NewBooleanObj(tvPtr->flags & TV_SORT_AUTO));
|
---|
| 1747 | return TCL_OK;
|
---|
| 1748 | }
|
---|
| 1749 |
|
---|
| 1750 | /*
|
---|
| 1751 | *----------------------------------------------------------------------
|
---|
| 1752 | *
|
---|
| 1753 | * SortCgetOp --
|
---|
| 1754 | *
|
---|
| 1755 | *----------------------------------------------------------------------
|
---|
| 1756 | */
|
---|
| 1757 | /*ARGSUSED*/
|
---|
| 1758 | static int
|
---|
| 1759 | SortCgetOp(tvPtr, interp, objc, objv)
|
---|
| 1760 | TreeView *tvPtr;
|
---|
| 1761 | Tcl_Interp *interp;
|
---|
| 1762 | int objc; /* Not used. */
|
---|
| 1763 | Tcl_Obj *CONST *objv;
|
---|
| 1764 | {
|
---|
| 1765 | return Blt_ConfigureValueFromObj(interp, tvPtr->tkwin, sortSpecs,
|
---|
| 1766 | (char *)tvPtr, objv[3], 0);
|
---|
| 1767 | }
|
---|
| 1768 |
|
---|
| 1769 | /*
|
---|
| 1770 | *----------------------------------------------------------------------
|
---|
| 1771 | *
|
---|
| 1772 | * SortConfigureOp --
|
---|
| 1773 | *
|
---|
| 1774 | * This procedure is called to process a list of configuration
|
---|
| 1775 | * options database, in order to reconfigure the one of more
|
---|
| 1776 | * entries in the widget.
|
---|
| 1777 | *
|
---|
| 1778 | * .h sort configure option value
|
---|
| 1779 | *
|
---|
| 1780 | * Results:
|
---|
| 1781 | * A standard Tcl result. If TCL_ERROR is returned, then
|
---|
| 1782 | * interp->result contains an error message.
|
---|
| 1783 | *
|
---|
| 1784 | * Side effects:
|
---|
| 1785 | * Configuration information, such as text string, colors, font,
|
---|
| 1786 | * etc. get set for tvPtr; old resources get freed, if there
|
---|
| 1787 | * were any. The hypertext is redisplayed.
|
---|
| 1788 | *
|
---|
| 1789 | *----------------------------------------------------------------------
|
---|
| 1790 | */
|
---|
| 1791 | static int
|
---|
| 1792 | SortConfigureOp(tvPtr, interp, objc, objv)
|
---|
| 1793 | TreeView *tvPtr;
|
---|
| 1794 | Tcl_Interp *interp;
|
---|
| 1795 | int objc;
|
---|
| 1796 | Tcl_Obj *CONST *objv;
|
---|
| 1797 | {
|
---|
| 1798 | int oldType;
|
---|
| 1799 | char *oldCommand;
|
---|
| 1800 | TreeViewColumn *oldColumn;
|
---|
| 1801 |
|
---|
| 1802 | if (objc == 3) {
|
---|
| 1803 | return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, sortSpecs,
|
---|
| 1804 | (char *)tvPtr, (Tcl_Obj *)NULL, 0);
|
---|
| 1805 | } else if (objc == 4) {
|
---|
| 1806 | return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, sortSpecs,
|
---|
| 1807 | (char *)tvPtr, objv[3], 0);
|
---|
| 1808 | }
|
---|
| 1809 | oldColumn = tvPtr->sortColumnPtr;
|
---|
| 1810 | oldType = tvPtr->sortType;
|
---|
| 1811 | oldCommand = tvPtr->sortCmd;
|
---|
| 1812 | if (Blt_ConfigureWidgetFromObj(interp, tvPtr->tkwin, sortSpecs,
|
---|
| 1813 | objc - 3, objv + 3, (char *)tvPtr, BLT_CONFIG_OBJV_ONLY) != TCL_OK) {
|
---|
| 1814 | return TCL_ERROR;
|
---|
| 1815 | }
|
---|
| 1816 | if ((oldColumn != tvPtr->sortColumnPtr) ||
|
---|
| 1817 | (oldType != tvPtr->sortType) ||
|
---|
| 1818 | (oldCommand != tvPtr->sortCmd)) {
|
---|
| 1819 | tvPtr->flags &= ~TV_SORTED;
|
---|
| 1820 | tvPtr->flags |= (TV_DIRTY | TV_RESORT);
|
---|
| 1821 | }
|
---|
| 1822 | if (tvPtr->flags & TV_SORT_AUTO) {
|
---|
| 1823 | tvPtr->flags |= TV_SORT_PENDING;
|
---|
| 1824 | }
|
---|
| 1825 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 1826 | return TCL_OK;
|
---|
| 1827 | }
|
---|
| 1828 |
|
---|
| 1829 | /*ARGSUSED*/
|
---|
| 1830 | static int
|
---|
| 1831 | SortOnceOp(tvPtr, interp, objc, objv)
|
---|
| 1832 | TreeView *tvPtr;
|
---|
| 1833 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1834 | int objc;
|
---|
| 1835 | Tcl_Obj *CONST *objv;
|
---|
| 1836 | {
|
---|
| 1837 | TreeViewEntry *entryPtr;
|
---|
| 1838 | int recurse, result;
|
---|
| 1839 | register int i;
|
---|
| 1840 |
|
---|
| 1841 | recurse = FALSE;
|
---|
| 1842 | if (objc > 3) {
|
---|
| 1843 | char *string;
|
---|
| 1844 | int length;
|
---|
| 1845 |
|
---|
| 1846 | string = Tcl_GetStringFromObj(objv[3], &length);
|
---|
| 1847 | if ((string[0] == '-') && (length > 1) &&
|
---|
| 1848 | (strncmp(string, "-recurse", length) == 0)) {
|
---|
| 1849 | objv++, objc--;
|
---|
| 1850 | recurse = TRUE;
|
---|
| 1851 | }
|
---|
| 1852 | }
|
---|
| 1853 | for (i = 3; i < objc; i++) {
|
---|
| 1854 | if (Blt_TreeViewGetEntry(tvPtr, objv[i], &entryPtr) != TCL_OK) {
|
---|
| 1855 | return TCL_ERROR;
|
---|
| 1856 | }
|
---|
| 1857 | if (recurse) {
|
---|
| 1858 | result = Blt_TreeApply(entryPtr->node, SortApplyProc, tvPtr);
|
---|
| 1859 | } else {
|
---|
| 1860 | result = SortApplyProc(entryPtr->node, tvPtr, TREE_PREORDER);
|
---|
| 1861 | }
|
---|
| 1862 | if (result != TCL_OK) {
|
---|
| 1863 | return TCL_ERROR;
|
---|
| 1864 | }
|
---|
| 1865 | }
|
---|
| 1866 | tvPtr->flags |= TV_LAYOUT;
|
---|
| 1867 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 1868 | return TCL_OK;
|
---|
| 1869 | }
|
---|
| 1870 |
|
---|
| 1871 | /*
|
---|
| 1872 | *----------------------------------------------------------------------
|
---|
| 1873 | *
|
---|
| 1874 | * Blt_TreeViewSortOp --
|
---|
| 1875 | *
|
---|
| 1876 | * Comparison routine (used by qsort) to sort a chain of subnodes.
|
---|
| 1877 | * A simple string comparison is performed on each node name.
|
---|
| 1878 | *
|
---|
| 1879 | * .h sort auto
|
---|
| 1880 | * .h sort once -recurse root
|
---|
| 1881 | *
|
---|
| 1882 | * Results:
|
---|
| 1883 | * 1 is the first is greater, -1 is the second is greater, 0
|
---|
| 1884 | * if equal.
|
---|
| 1885 | *
|
---|
| 1886 | *----------------------------------------------------------------------
|
---|
| 1887 | */
|
---|
| 1888 | static Blt_OpSpec sortOps[] =
|
---|
| 1889 | {
|
---|
| 1890 | {"auto", 1, (Blt_Op)SortAutoOp, 3, 4, "?boolean?",},
|
---|
| 1891 | {"cget", 2, (Blt_Op)SortCgetOp, 4, 4, "option",},
|
---|
| 1892 | {"configure", 2, (Blt_Op)SortConfigureOp, 3, 0, "?option value?...",},
|
---|
| 1893 | {"once", 1, (Blt_Op)SortOnceOp, 3, 0, "?-recurse? node...",},
|
---|
| 1894 | };
|
---|
| 1895 | static int nSortOps = sizeof(sortOps) / sizeof(Blt_OpSpec);
|
---|
| 1896 |
|
---|
| 1897 | /*ARGSUSED*/
|
---|
| 1898 | int
|
---|
| 1899 | Blt_TreeViewSortOp(tvPtr, interp, objc, objv)
|
---|
| 1900 | TreeView *tvPtr;
|
---|
| 1901 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1902 | int objc;
|
---|
| 1903 | Tcl_Obj *CONST *objv;
|
---|
| 1904 | {
|
---|
| 1905 | Blt_Op proc;
|
---|
| 1906 | int result;
|
---|
| 1907 |
|
---|
| 1908 | proc = Blt_GetOpFromObj(interp, nSortOps, sortOps, BLT_OP_ARG2, objc,
|
---|
| 1909 | objv, 0);
|
---|
| 1910 | if (proc == NULL) {
|
---|
| 1911 | return TCL_ERROR;
|
---|
| 1912 | }
|
---|
| 1913 | result = (*proc) (tvPtr, interp, objc, objv);
|
---|
| 1914 | return result;
|
---|
| 1915 | }
|
---|
| 1916 |
|
---|
| 1917 | /*
|
---|
| 1918 | *----------------------------------------------------------------------
|
---|
| 1919 | *
|
---|
| 1920 | * SortApplyProc --
|
---|
| 1921 | *
|
---|
| 1922 | * Sorts the subnodes at a given node.
|
---|
| 1923 | *
|
---|
| 1924 | * Results:
|
---|
| 1925 | * Always returns TCL_OK.
|
---|
| 1926 | *
|
---|
| 1927 | *----------------------------------------------------------------------
|
---|
| 1928 | */
|
---|
| 1929 | /*ARGSUSED*/
|
---|
| 1930 | static int
|
---|
| 1931 | SortApplyProc(node, clientData, order)
|
---|
| 1932 | Blt_TreeNode node;
|
---|
| 1933 | ClientData clientData;
|
---|
| 1934 | int order; /* Not used. */
|
---|
| 1935 | {
|
---|
| 1936 | TreeView *tvPtr = clientData;
|
---|
| 1937 |
|
---|
| 1938 | if (!Blt_TreeIsLeaf(node)) {
|
---|
| 1939 | Blt_TreeSortNode(tvPtr->tree, node, CompareNodes);
|
---|
| 1940 | }
|
---|
| 1941 | return TCL_OK;
|
---|
| 1942 | }
|
---|
| 1943 |
|
---|
| 1944 | /*
|
---|
| 1945 | *----------------------------------------------------------------------
|
---|
| 1946 | *
|
---|
| 1947 | * Blt_TreeViewSortFlatView --
|
---|
| 1948 | *
|
---|
| 1949 | * Sorts the flatten array of entries.
|
---|
| 1950 | *
|
---|
| 1951 | *----------------------------------------------------------------------
|
---|
| 1952 | */
|
---|
| 1953 | void
|
---|
| 1954 | Blt_TreeViewSortFlatView(tvPtr)
|
---|
| 1955 | TreeView *tvPtr;
|
---|
| 1956 | {
|
---|
| 1957 | TreeViewEntry *entryPtr, **p;
|
---|
| 1958 |
|
---|
| 1959 | tvPtr->flags &= ~TV_SORT_PENDING;
|
---|
| 1960 | if ((tvPtr->sortType == SORT_TYPE_NONE) || (tvPtr->sortColumnPtr == NULL) ||
|
---|
| 1961 | (tvPtr->nEntries == 1)) {
|
---|
| 1962 | return;
|
---|
| 1963 | }
|
---|
| 1964 | if (tvPtr->flags & TV_SORTED) {
|
---|
| 1965 | int first, last;
|
---|
| 1966 | TreeViewEntry *hold;
|
---|
| 1967 |
|
---|
| 1968 | if (tvPtr->sortDecreasing == tvPtr->viewIsDecreasing) {
|
---|
| 1969 | return;
|
---|
| 1970 | }
|
---|
| 1971 |
|
---|
| 1972 | /*
|
---|
| 1973 | * The view is already sorted but in the wrong direction.
|
---|
| 1974 | * Reverse the entries in the array.
|
---|
| 1975 | */
|
---|
| 1976 | for (first = 0, last = tvPtr->nEntries - 1; last > first;
|
---|
| 1977 | first++, last--) {
|
---|
| 1978 | hold = tvPtr->flatArr[first];
|
---|
| 1979 | tvPtr->flatArr[first] = tvPtr->flatArr[last];
|
---|
| 1980 | tvPtr->flatArr[last] = hold;
|
---|
| 1981 | }
|
---|
| 1982 | tvPtr->viewIsDecreasing = tvPtr->sortDecreasing;
|
---|
| 1983 | tvPtr->flags |= TV_SORTED | TV_LAYOUT;
|
---|
| 1984 | return;
|
---|
| 1985 | }
|
---|
| 1986 | /* Fetch each entry's data as Tcl_Objs for sorting. */
|
---|
| 1987 | if (tvPtr->sortColumnPtr == &tvPtr->treeColumn) {
|
---|
| 1988 | for(p = tvPtr->flatArr; *p != NULL; p++) {
|
---|
| 1989 | entryPtr = *p;
|
---|
| 1990 | if (entryPtr->fullName == NULL) {
|
---|
| 1991 | Tcl_DString dString;
|
---|
| 1992 |
|
---|
| 1993 | Blt_TreeViewGetFullName(tvPtr, entryPtr, TRUE, &dString);
|
---|
| 1994 | entryPtr->fullName = Blt_Strdup(Tcl_DStringValue(&dString));
|
---|
| 1995 | Tcl_DStringFree(&dString);
|
---|
| 1996 | }
|
---|
| 1997 | entryPtr->dataObjPtr = Tcl_NewStringObj(entryPtr->fullName, -1);
|
---|
| 1998 | Tcl_IncrRefCount(entryPtr->dataObjPtr);
|
---|
| 1999 | }
|
---|
| 2000 | } else {
|
---|
| 2001 | Blt_TreeKey key;
|
---|
| 2002 | Tcl_Obj *objPtr;
|
---|
| 2003 |
|
---|
| 2004 | key = tvPtr->sortColumnPtr->key;
|
---|
| 2005 | for(p = tvPtr->flatArr; *p != NULL; p++) {
|
---|
| 2006 | entryPtr = *p;
|
---|
| 2007 | if (Blt_TreeViewGetData(entryPtr, key, &objPtr) != TCL_OK) {
|
---|
| 2008 | objPtr = bltEmptyStringObjPtr;
|
---|
| 2009 | }
|
---|
| 2010 | entryPtr->dataObjPtr = objPtr;
|
---|
| 2011 | Tcl_IncrRefCount(entryPtr->dataObjPtr);
|
---|
| 2012 | }
|
---|
| 2013 | }
|
---|
| 2014 | qsort((char *)tvPtr->flatArr, tvPtr->nEntries, sizeof(TreeViewEntry *),
|
---|
| 2015 | (QSortCompareProc *)CompareEntries);
|
---|
| 2016 |
|
---|
| 2017 | /* Free all the Tcl_Objs used for comparison data. */
|
---|
| 2018 | for(p = tvPtr->flatArr; *p != NULL; p++) {
|
---|
| 2019 | Tcl_DecrRefCount((*p)->dataObjPtr);
|
---|
| 2020 | }
|
---|
| 2021 | tvPtr->viewIsDecreasing = tvPtr->sortDecreasing;
|
---|
| 2022 | tvPtr->flags |= TV_SORTED;
|
---|
| 2023 | }
|
---|
| 2024 |
|
---|
| 2025 | /*
|
---|
| 2026 | *----------------------------------------------------------------------
|
---|
| 2027 | *
|
---|
| 2028 | * Blt_TreeViewSortTreeView --
|
---|
| 2029 | *
|
---|
| 2030 | * Sorts the tree array of entries.
|
---|
| 2031 | *
|
---|
| 2032 | *----------------------------------------------------------------------
|
---|
| 2033 | */
|
---|
| 2034 | void
|
---|
| 2035 | Blt_TreeViewSortTreeView(tvPtr)
|
---|
| 2036 | TreeView *tvPtr;
|
---|
| 2037 | {
|
---|
| 2038 | tvPtr->flags &= ~TV_SORT_PENDING;
|
---|
| 2039 | if ((tvPtr->sortType != SORT_TYPE_NONE) && (tvPtr->sortColumnPtr != NULL)) {
|
---|
| 2040 | treeViewInstance = tvPtr;
|
---|
| 2041 | Blt_TreeApply(tvPtr->rootPtr->node, SortApplyProc, tvPtr);
|
---|
| 2042 | }
|
---|
| 2043 | tvPtr->viewIsDecreasing = tvPtr->sortDecreasing;
|
---|
| 2044 | }
|
---|
| 2045 |
|
---|
| 2046 |
|
---|
| 2047 | #endif /* NO_TREEVIEW */
|
---|