/* * bltTreeViewStyle.c -- * * This module implements styles for treeview widget cells. * * Copyright 1998-1999 Lucent Technologies, Inc. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and warranty * disclaimer appear in supporting documentation, and that the names * of Lucent Technologies or any of their entities not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. * * Lucent Technologies disclaims all warranties with regard to this * software, including all implied warranties of merchantability and * fitness. In no event shall Lucent Technologies be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether in * an action of contract, negligence or other tortuous action, arising * out of or in connection with the use or performance of this * software. * * The "treeview" widget was created by George A. Howlett. */ #include "bltInt.h" #ifndef NO_TREEVIEW #include "bltTreeView.h" #include "bltList.h" #include #include #define STYLE_GAP 2 static Blt_OptionParseProc ObjToIcon; static Blt_OptionPrintProc IconToObj; static Blt_OptionFreeProc FreeIcon; Blt_CustomOption bltTreeViewIconOption = { /* Contains a pointer to the widget that's currently being * configured. This is used in the custom configuration parse * routine for icons. */ ObjToIcon, IconToObj, FreeIcon, NULL, }; #define DEF_STYLE_HIGHLIGHT_BACKGROUND STD_NORMAL_BACKGROUND #define DEF_STYLE_HIGHLIGHT_FOREGROUND STD_NORMAL_FOREGROUND #ifdef WIN32 #define DEF_STYLE_ACTIVE_BACKGROUND RGB_GREY85 #else #define DEF_STYLE_ACTIVE_BACKGROUND RGB_GREY95 #endif #define DEF_STYLE_ACTIVE_FOREGROUND STD_ACTIVE_FOREGROUND #define DEF_STYLE_GAP "2" typedef struct { int refCount; /* Usage reference count. */ unsigned int flags; char *name; TreeViewStyleClass *classPtr; /* Class-specific routines to manage style. */ Blt_HashEntry *hashPtr; /* General style fields. */ Tk_Cursor cursor; /* X Cursor */ TreeViewIcon icon; /* If non-NULL, is a Tk_Image to be drawn * in the cell. */ int gap; /* # pixels gap between icon and text. */ Tk_Font font; XColor *fgColor; /* Normal foreground color of cell. */ Tk_3DBorder border; /* Normal background color of cell. */ XColor *highlightFgColor; /* Foreground color of cell when * highlighted. */ Tk_3DBorder highlightBorder;/* Background color of cell when * highlighted. */ XColor *activeFgColor; /* Foreground color of cell when active. */ Tk_3DBorder activeBorder; /* Background color of cell when active. */ /* TextBox-specific fields */ GC gc; GC highlightGC; GC activeGC; int side; /* Position of the text in relation to * the icon. */ Blt_TreeKey key; /* Actual data resides in this tree value. */ } TreeViewTextBox; #ifdef WIN32 #define DEF_TEXTBOX_CURSOR "arrow" #else #define DEF_TEXTBOX_CURSOR "hand2" #endif /*WIN32*/ #define DEF_TEXTBOX_SIDE "left" static Blt_ConfigSpec textBoxSpecs[] = { {BLT_CONFIG_BORDER, "-activebackground", "activeBackground", "ActiveBackground", DEF_STYLE_ACTIVE_BACKGROUND, Blt_Offset(TreeViewTextBox, activeBorder), 0}, {BLT_CONFIG_SYNONYM, "-activebg", "activeBackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-activefg", "activeFackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground", "ActiveForeground", DEF_STYLE_ACTIVE_FOREGROUND, Blt_Offset(TreeViewTextBox, activeFgColor), 0}, {BLT_CONFIG_BORDER, "-background", "background", "Background", (char *)NULL, Blt_Offset(TreeViewTextBox, border), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_CURSOR, "-cursor", "cursor", "Cursor", DEF_TEXTBOX_CURSOR, Blt_Offset(TreeViewTextBox, cursor), 0}, {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_FONT, "-font", "font", "Font", (char *)NULL, Blt_Offset(TreeViewTextBox, font), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground", (char *)NULL, Blt_Offset(TreeViewTextBox, fgColor),BLT_CONFIG_NULL_OK }, {BLT_CONFIG_DISTANCE, "-gap", "gap", "Gap", DEF_STYLE_GAP, Blt_Offset(TreeViewTextBox, gap), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_STYLE_HIGHLIGHT_BACKGROUND, Blt_Offset(TreeViewTextBox, highlightBorder), BLT_CONFIG_COLOR_ONLY}, {BLT_CONFIG_COLOR, "-highlightforeground", "highlightForeground", "HighlightForeground", DEF_STYLE_HIGHLIGHT_FOREGROUND, Blt_Offset(TreeViewTextBox, highlightFgColor), 0}, {BLT_CONFIG_SYNONYM, "-highlightbg", "highlightBackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-highlightfg", "highlightForeground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_CUSTOM, "-icon", "icon", "Icon", (char *)NULL, Blt_Offset(TreeViewTextBox, icon), BLT_CONFIG_NULL_OK, &bltTreeViewIconOption}, {BLT_CONFIG_STRING, "-key", "key", "key", (char *)NULL, Blt_Offset(TreeViewTextBox, key), BLT_CONFIG_NULL_OK, 0}, {BLT_CONFIG_SIDE, "-side", "side", "side", DEF_TEXTBOX_SIDE, Tk_Offset(TreeViewTextBox, side), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, 0, 0} }; typedef struct { int refCount; /* Usage reference count. */ unsigned int flags; /* Contains style type and update flags. */ char *name; /* Instance name. */ TreeViewStyleClass *classPtr; /* Class-specific routines to manage style. */ Blt_HashEntry *hashPtr; /* General style fields. */ Tk_Cursor cursor; /* X Cursor */ TreeViewIcon icon; /* If non-NULL, is a Tk_Image to be drawn * in the cell. */ int gap; /* # pixels gap between icon and text. */ Tk_Font font; XColor *fgColor; /* Normal foreground color of cell. */ Tk_3DBorder border; /* Normal background color of cell. */ XColor *highlightFgColor; /* Foreground color of cell when * highlighted. */ Tk_3DBorder highlightBorder;/* Background color of cell when * highlighted. */ XColor *activeFgColor; /* Foreground color of cell when active. */ Tk_3DBorder activeBorder; /* Background color of cell when active. */ /* Checkbox specific fields. */ GC gc; GC highlightGC; GC activeGC; Blt_TreeKey key; /* Actual data resides in this tree value. */ int size; /* Size of the checkbox. */ int showValue; /* If non-zero, display the on/off value. */ char *onValue; char *offValue; int lineWidth; /* Linewidth of the surrounding box. */ XColor *boxColor; /* Rectangle (box) color (grey). */ XColor *fillColor; /* Fill color (white) */ XColor *checkColor; /* Check color (red). */ GC boxGC; GC fillGC; /* Box fill GC */ GC checkGC; TextLayout *onPtr, *offPtr; } TreeViewCheckBox; #define DEF_CHECKBOX_BOX_COLOR "black" #define DEF_CHECKBOX_CHECK_COLOR "red" #define DEF_CHECKBOX_FILL_COLOR "white" #define DEF_CHECKBOX_OFFVALUE "0" #define DEF_CHECKBOX_ONVALUE "1" #define DEF_CHECKBOX_SHOWVALUE "yes" #define DEF_CHECKBOX_SIZE "11" #define DEF_CHECKBOX_LINEWIDTH "2" #define DEF_CHECKBOX_GAP "4" #ifdef WIN32 #define DEF_CHECKBOX_CURSOR "arrow" #else #define DEF_CHECKBOX_CURSOR "hand2" #endif /*WIN32*/ static Blt_ConfigSpec checkBoxSpecs[] = { {BLT_CONFIG_BORDER, "-activebackground", "activeBackground", "ActiveBackground", DEF_STYLE_ACTIVE_BACKGROUND, Blt_Offset(TreeViewCheckBox, activeBorder), 0}, {BLT_CONFIG_SYNONYM, "-activebg", "activeBackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-activefg", "activeFackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground", "ActiveForeground", DEF_STYLE_ACTIVE_FOREGROUND, Blt_Offset(TreeViewCheckBox, activeFgColor), 0}, {BLT_CONFIG_BORDER, "-background", "background", "Background", (char *)NULL, Blt_Offset(TreeViewCheckBox, border), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_POS_DISTANCE, "-boxsize", "boxSize", "BoxSize", DEF_CHECKBOX_SIZE, Blt_Offset(TreeViewCheckBox, size), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_CURSOR, "-cursor", "cursor", "Cursor", DEF_CHECKBOX_CURSOR, Blt_Offset(TreeViewTextBox, cursor), 0}, {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_FONT, "-font", "font", "Font", (char *)NULL, Blt_Offset(TreeViewCheckBox, font), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground", (char *)NULL, Blt_Offset(TreeViewCheckBox, fgColor), BLT_CONFIG_NULL_OK }, {BLT_CONFIG_DISTANCE, "-gap", "gap", "Gap", DEF_CHECKBOX_GAP, Blt_Offset(TreeViewCheckBox, gap), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_STYLE_HIGHLIGHT_BACKGROUND, Blt_Offset(TreeViewCheckBox, highlightBorder), BLT_CONFIG_COLOR_ONLY}, {BLT_CONFIG_COLOR, "-highlightforeground", "highlightForeground", "HighlightForeground", DEF_STYLE_HIGHLIGHT_FOREGROUND, Blt_Offset(TreeViewCheckBox, highlightFgColor), 0}, {BLT_CONFIG_SYNONYM, "-highlightbg", "highlightBackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-highlightfg", "highlightForeground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_CUSTOM, "-icon", "icon", "Icon", (char *)NULL, Blt_Offset(TreeViewCheckBox, icon), BLT_CONFIG_NULL_OK, &bltTreeViewIconOption}, {BLT_CONFIG_STRING, "-key", "key", "key", (char *)NULL, Blt_Offset(TreeViewCheckBox, key), BLT_CONFIG_NULL_OK, 0}, {BLT_CONFIG_DISTANCE, "-linewidth", "lineWidth", "LineWidth", DEF_CHECKBOX_LINEWIDTH, Blt_Offset(TreeViewCheckBox, lineWidth), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_COLOR, "-checkcolor", "checkColor", "CheckColor", DEF_CHECKBOX_CHECK_COLOR, Blt_Offset(TreeViewCheckBox, checkColor), 0}, {BLT_CONFIG_COLOR, "-boxcolor", "boxColor", "BoxColor", DEF_CHECKBOX_BOX_COLOR, Blt_Offset(TreeViewCheckBox, boxColor), 0}, {BLT_CONFIG_COLOR, "-fillcolor", "fillColor", "FillColor", DEF_CHECKBOX_FILL_COLOR, Blt_Offset(TreeViewCheckBox, fillColor), 0}, {BLT_CONFIG_STRING, "-offvalue", "offValue", "OffValue", DEF_CHECKBOX_OFFVALUE, Blt_Offset(TreeViewCheckBox, offValue), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_STRING, "-onvalue", "onValue", "OnValue", DEF_CHECKBOX_ONVALUE, Blt_Offset(TreeViewCheckBox, onValue), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_STRING, "-key", "key", "key", (char *)NULL, Blt_Offset(TreeViewCheckBox, key), BLT_CONFIG_NULL_OK, 0}, {BLT_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue", DEF_CHECKBOX_SHOWVALUE, Blt_Offset(TreeViewCheckBox, showValue), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, 0, 0} }; typedef struct { int refCount; /* Usage reference count. */ unsigned int flags; char *name; TreeViewStyleClass *classPtr;/* Class-specific style routines. */ Blt_HashEntry *hashPtr; /* General style fields. */ Tk_Cursor cursor; /* X Cursor */ TreeViewIcon icon; /* If non-NULL, is a Tk_Image to be drawn * in the cell. */ int gap; /* # pixels gap between icon and text. */ Tk_Font font; XColor *fgColor; /* Normal foreground color of cell. */ Tk_3DBorder border; /* Normal background color of cell. */ XColor *highlightFgColor; /* Foreground color of cell when * highlighted. */ Tk_3DBorder highlightBorder;/* Background color of cell when * highlighted. */ XColor *activeFgColor; /* Foreground color of cell when active. */ Tk_3DBorder activeBorder; /* Background color of cell when active. */ /* ComboBox-specific fields */ GC gc; GC highlightGC; GC activeGC; int borderWidth; /* Width of outer border surrounding * the entire box. */ int relief; /* Relief of outer border. */ Blt_TreeKey key; /* Actual data resides in this tree value. */ char *choices; /* List of available choices. */ char *choiceIcons; /* List of icons associated with choices. */ int scrollWidth; int button; int buttonWidth; int buttonBorderWidth; /* Border width of button. */ int buttonRelief; /* Normal relief of button. */ } TreeViewComboBox; #define DEF_COMBOBOX_BORDERWIDTH "1" #define DEF_COMBOBOX_BUTTON_BORDERWIDTH "1" #define DEF_COMBOBOX_BUTTON_RELIEF "raised" #define DEF_COMBOBOX_RELIEF "flat" #ifdef WIN32 #define DEF_COMBOBOX_CURSOR "arrow" #else #define DEF_COMBOBOX_CURSOR "hand2" #endif /*WIN32*/ static Blt_ConfigSpec comboBoxSpecs[] = { {BLT_CONFIG_BORDER, "-activebackground", "activeBackground", "ActiveBackground", DEF_STYLE_ACTIVE_BACKGROUND, Blt_Offset(TreeViewComboBox, activeBorder), 0}, {BLT_CONFIG_SYNONYM, "-activebg", "activeBackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-activefg", "activeFackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground", "ActiveForeground", DEF_STYLE_ACTIVE_FOREGROUND, Blt_Offset(TreeViewComboBox, activeFgColor), 0}, {BLT_CONFIG_BORDER, "-background", "background", "Background", (char *)NULL, Blt_Offset(TreeViewComboBox, border), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_DISTANCE, "-borderwidth", "borderWidth", "BorderWidth", DEF_COMBOBOX_BORDERWIDTH, Blt_Offset(TreeViewComboBox, borderWidth), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_RELIEF, "-buttonrelief", "buttonRelief", "ButtonRelief", DEF_COMBOBOX_BUTTON_RELIEF, Blt_Offset(TreeViewComboBox, buttonRelief), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_DISTANCE, "-buttonborderwidth", "buttonBorderWidth", "ButtonBorderWidth", DEF_COMBOBOX_BUTTON_BORDERWIDTH, Blt_Offset(TreeViewComboBox, buttonBorderWidth), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_CURSOR, "-cursor", "cursor", "Cursor", DEF_COMBOBOX_CURSOR, Blt_Offset(TreeViewTextBox, cursor), 0}, {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_FONT, "-font", "font", "Font", (char *)NULL, Blt_Offset(TreeViewComboBox, font), BLT_CONFIG_NULL_OK}, {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground", (char *)NULL, Blt_Offset(TreeViewComboBox, fgColor), BLT_CONFIG_NULL_OK }, {BLT_CONFIG_DISTANCE, "-gap", "gap", "Gap", DEF_STYLE_GAP, Blt_Offset(TreeViewComboBox, gap), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_STYLE_HIGHLIGHT_BACKGROUND, Blt_Offset(TreeViewComboBox, highlightBorder), BLT_CONFIG_COLOR_ONLY}, {BLT_CONFIG_COLOR, "-highlightforeground", "highlightForeground", "HighlightForeground", DEF_STYLE_HIGHLIGHT_FOREGROUND, Blt_Offset(TreeViewComboBox, highlightFgColor), 0}, {BLT_CONFIG_SYNONYM, "-highlightbg", "highlightBackground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_SYNONYM, "-highlightfg", "highlightForeground", (char *)NULL, (char *)NULL, 0, 0}, {BLT_CONFIG_CUSTOM, "-icon", "icon", "Icon", (char *)NULL, Blt_Offset(TreeViewComboBox, icon), BLT_CONFIG_NULL_OK, &bltTreeViewIconOption}, {BLT_CONFIG_STRING, "-key", "key", "key", (char *)NULL, Blt_Offset(TreeViewComboBox, key), BLT_CONFIG_NULL_OK, 0}, {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_COMBOBOX_RELIEF, Blt_Offset(TreeViewComboBox, relief), BLT_CONFIG_DONT_SET_DEFAULT}, {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, 0, 0} }; typedef TreeViewStyle *(StyleCreateProc) _ANSI_ARGS_((TreeView *tvPtr, Blt_HashEntry *hPtr)); static StyleConfigProc ConfigureTextBox, ConfigureCheckBox, ConfigureComboBox; static StyleCreateProc CreateTextBox, CreateCheckBox, CreateComboBox; static StyleDrawProc DrawTextBox, DrawCheckBox, DrawComboBox; static StyleEditProc EditTextBox, EditCheckBox, EditComboBox; static StyleFreeProc FreeTextBox, FreeCheckBox, FreeComboBox; static StyleMeasureProc MeasureTextBox, MeasureCheckBox, MeasureComboBox; static StylePickProc PickCheckBox, PickComboBox; /* *---------------------------------------------------------------------- * * ObjToIcon -- * * Convert the name of an icon into a Tk image. * * Results: * If the string is successfully converted, TCL_OK is returned. * Otherwise, TCL_ERROR is returned and an error message is left in * interpreter's result field. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int ObjToIcon(clientData, interp, tkwin, objPtr, widgRec, offset) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Interpreter to send results back to */ Tk_Window tkwin; /* Not used. */ Tcl_Obj *objPtr; /* Tcl_Obj representing the new value. */ char *widgRec; int offset; { TreeView *tvPtr = clientData; TreeViewIcon *iconPtr = (TreeViewIcon *)(widgRec + offset); TreeViewIcon icon; icon = Blt_TreeViewGetIcon(tvPtr, Tcl_GetString(objPtr)); if (icon == NULL) { return TCL_ERROR; } *iconPtr = icon; return TCL_OK; } /* *---------------------------------------------------------------------- * * IconToObj -- * * Converts the icon into its string representation (its name). * * Results: * The name of the icon is returned. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static Tcl_Obj * IconToObj(clientData, interp, tkwin, widgRec, offset) ClientData clientData; /* Not used. */ Tcl_Interp *interp; Tk_Window tkwin; /* Not used. */ char *widgRec; int offset; { TreeViewIcon icon = *(TreeViewIcon *)(widgRec + offset); if (icon == NULL) { return bltEmptyStringObjPtr; } return Tcl_NewStringObj(Blt_NameOfImage((icon)->tkImage), -1); } /*ARGSUSED*/ static void FreeIcon(clientData, display, widgRec, offset) ClientData clientData; Display *display; /* Not used. */ char *widgRec; int offset; { TreeViewIcon icon = *(TreeViewIcon *)(widgRec + offset); TreeView *tvPtr = clientData; Blt_TreeViewFreeIcon(tvPtr, icon); } static TreeViewStyleClass textBoxClass = { "TextBoxStyle", textBoxSpecs, ConfigureTextBox, MeasureTextBox, DrawTextBox, NULL, EditTextBox, FreeTextBox, }; static TreeViewStyleClass checkBoxClass = { "CheckBoxStyle", checkBoxSpecs, ConfigureCheckBox, MeasureCheckBox, DrawCheckBox, NULL, EditCheckBox, FreeCheckBox, }; static TreeViewStyleClass comboBoxClass = { "ComboBoxStyle", comboBoxSpecs, ConfigureComboBox, MeasureComboBox, DrawComboBox, PickComboBox, EditComboBox, FreeComboBox, }; /* *---------------------------------------------------------------------- * * CreateTextBox -- * * Creates a "textbox" style. * * Results: * A pointer to the new style structure. * *---------------------------------------------------------------------- */ static TreeViewStyle * CreateTextBox(tvPtr, hPtr) TreeView *tvPtr; Blt_HashEntry *hPtr; { TreeViewTextBox *tbPtr; tbPtr = Blt_Calloc(1, sizeof(TreeViewTextBox)); assert(tbPtr); tbPtr->classPtr = &textBoxClass; tbPtr->side = SIDE_LEFT; tbPtr->gap = STYLE_GAP; tbPtr->name = Blt_Strdup(Blt_GetHashKey(&tvPtr->styleTable, hPtr)); tbPtr->hashPtr = hPtr; tbPtr->flags = STYLE_TEXTBOX; tbPtr->refCount = 1; Blt_SetHashValue(hPtr, tbPtr); return (TreeViewStyle *)tbPtr; } /* *---------------------------------------------------------------------- * * ConfigureTextBox -- * * Configures a "textbox" style. This routine performs * generates the GCs required for a textbox style. * * Results: * None. * * Side Effects: * GCs are created for the style. * *---------------------------------------------------------------------- */ static void ConfigureTextBox(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { GC newGC; TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; XColor *bgColor; XGCValues gcValues; unsigned long gcMask; gcMask = GCForeground | GCBackground | GCFont; gcValues.font = Tk_FontId(CHOOSE(tvPtr->font, tbPtr->font)); bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, tbPtr->border)); gcValues.background = bgColor->pixel; gcValues.foreground = CHOOSE(tvPtr->fgColor, tbPtr->fgColor)->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (tbPtr->gc != NULL) { Tk_FreeGC(tvPtr->display, tbPtr->gc); } tbPtr->gc = newGC; gcValues.background = Tk_3DBorderColor(tbPtr->highlightBorder)->pixel; gcValues.foreground = tbPtr->highlightFgColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (tbPtr->highlightGC != NULL) { Tk_FreeGC(tvPtr->display, tbPtr->highlightGC); } tbPtr->highlightGC = newGC; gcValues.background = Tk_3DBorderColor(tbPtr->activeBorder)->pixel; gcValues.foreground = tbPtr->activeFgColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (tbPtr->activeGC != NULL) { Tk_FreeGC(tvPtr->display, tbPtr->activeGC); } tbPtr->activeGC = newGC; tbPtr->flags |= STYLE_DIRTY; } /* *---------------------------------------------------------------------- * * MeasureTextBox -- * * Determines the space requirements for the "textbox" given * the value to be displayed. Depending upon whether an icon * or text is displayed and their relative placements, this * routine computes the space needed for the text entry. * * Results: * None. * * Side Effects: * The width and height fields of *valuePtr* are set with the * computed dimensions. * *---------------------------------------------------------------------- */ static void MeasureTextBox(tvPtr, stylePtr, valuePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; TreeViewValue *valuePtr; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; int iconWidth, iconHeight; int textWidth, textHeight; int gap; textWidth = textHeight = 0; iconWidth = iconHeight = 0; valuePtr->width = valuePtr->height = 0; if (tbPtr->icon != NULL) { iconWidth = TreeViewIconWidth(tbPtr->icon); iconHeight = TreeViewIconHeight(tbPtr->icon); } if (valuePtr->textPtr != NULL) { Blt_Free(valuePtr->textPtr); valuePtr->textPtr = NULL; } if (valuePtr->string != NULL) { /* New string defined. */ TextStyle ts; Blt_InitTextStyle(&ts); ts.font = CHOOSE(tvPtr->font, tbPtr->font); ts.anchor = TK_ANCHOR_NW; ts.justify = TK_JUSTIFY_LEFT; valuePtr->textPtr = Blt_GetTextLayout(valuePtr->string, &ts); } gap = 0; if (valuePtr->textPtr != NULL) { textWidth = valuePtr->textPtr->width; textHeight = valuePtr->textPtr->height; if (tbPtr->icon != NULL) { gap = tbPtr->gap; } } if (SIDE_VERTICAL(tbPtr->side)) { valuePtr->height = iconHeight + gap + textHeight; valuePtr->width = MAX(textWidth, iconWidth); } else { valuePtr->width = iconWidth + gap + textWidth; valuePtr->height = MAX(textHeight, iconHeight); } } /* *---------------------------------------------------------------------- * * DrawTextBox -- * * Draws the "textbox" given the screen coordinates and the * value to be displayed. * * Results: * None. * * Side Effects: * The textbox value is drawn. * *---------------------------------------------------------------------- */ static void DrawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, x, y) TreeView *tvPtr; Drawable drawable; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; int x, y; { GC gc; TreeViewColumn *columnPtr; TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; int iconX, iconY, iconWidth, iconHeight; int textX, textY, textWidth, textHeight; int gap, columnWidth; Tk_3DBorder border; XColor *fgColor; columnPtr = valuePtr->columnPtr; if (stylePtr->flags & STYLE_HIGHLIGHT) { gc = tbPtr->highlightGC; border = tbPtr->highlightBorder; fgColor = tbPtr->highlightFgColor; } else { gc = tbPtr->gc; border = CHOOSE(tvPtr->border, tbPtr->border); fgColor = CHOOSE(tvPtr->fgColor, tbPtr->fgColor); } if (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr)) { /* * Draw the active or normal background color over the entire * label area. This includes both the tab's text and image. * The rectangle should be 2 pixels wider/taller than this * area. So if the label consists of just an image, we get an * halo around the image when the tab is active. */ if (border != NULL) { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, border, x, y, columnPtr->width, entryPtr->height, 0, TK_RELIEF_FLAT); } } columnWidth = columnPtr->width - (2 * columnPtr->borderWidth + PADDING(columnPtr->pad)); if (columnWidth > valuePtr->width) { switch(columnPtr->justify) { case TK_JUSTIFY_RIGHT: x += (columnWidth - valuePtr->width); break; case TK_JUSTIFY_CENTER: x += (columnWidth - valuePtr->width) / 2; break; case TK_JUSTIFY_LEFT: break; } } textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */ iconWidth = iconHeight = 0; if (tbPtr->icon != NULL) { iconWidth = TreeViewIconWidth(tbPtr->icon); iconHeight = TreeViewIconHeight(tbPtr->icon); } textWidth = textHeight = 0; if (valuePtr->textPtr != NULL) { textWidth = valuePtr->textPtr->width; textHeight = valuePtr->textPtr->height; } gap = 0; if ((tbPtr->icon != NULL) && (valuePtr->textPtr != NULL)) { gap = tbPtr->gap; } switch (tbPtr->side) { case SIDE_RIGHT: textX = x; textY = y + (entryPtr->height - textHeight) / 2; iconX = textX + textWidth + gap; iconY = y + (entryPtr->height - iconHeight) / 2; break; case SIDE_LEFT: iconX = x; iconY = y + (entryPtr->height - iconHeight) / 2; textX = iconX + iconWidth + gap; textY = y + (entryPtr->height - textHeight) / 2; break; case SIDE_TOP: iconY = y; iconX = x + (columnWidth - iconWidth) / 2; textY = iconY + iconHeight + gap; textX = x + (columnWidth - textWidth) / 2; break; case SIDE_BOTTOM: textY = y; textX = x + (columnWidth - textWidth) / 2; iconY = textY + textHeight + gap; iconX = x + (columnWidth - iconWidth) / 2; break; } if (tbPtr->icon != NULL) { Tk_RedrawImage(TreeViewIconBits(tbPtr->icon), 0, 0, iconWidth, iconHeight, drawable, iconX, iconY); } if (valuePtr->textPtr != NULL) { TextStyle ts; XColor *color; Tk_Font font; font = CHOOSE(tvPtr->font, tbPtr->font); if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr)) { color = SELECT_FG(tvPtr); XSetForeground(tvPtr->display, gc, color->pixel); } else if (entryPtr->color != NULL) { color = entryPtr->color; XSetForeground(tvPtr->display, gc, color->pixel); } else { color = fgColor; } Blt_SetDrawTextStyle(&ts, font, gc, color, fgColor, NULL, 0.0, TK_ANCHOR_NW, TK_JUSTIFY_LEFT, 0, 0); Blt_DrawTextLayout(tvPtr->tkwin, drawable, valuePtr->textPtr, &ts, textX, textY); if (color != fgColor) { XSetForeground(tvPtr->display, gc, fgColor->pixel); } } stylePtr->flags &= ~STYLE_DIRTY; } /* *---------------------------------------------------------------------- * * EditCombobox -- * * Edits the "combobox". * * Results: * None. * * Side Effects: * The checkbox value is drawn. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int EditTextBox(tvPtr, entryPtr, valuePtr, stylePtr) TreeView *tvPtr; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; /* Not used. */ { return Blt_TreeViewTextbox(tvPtr, entryPtr, valuePtr->columnPtr); } /* *---------------------------------------------------------------------- * * FreeTextBox -- * * Releases resources allocated for the textbox. The resources * freed by this routine are specific only to the "textbox". * Other resources (common to all styles) are freed in the * Blt_TreeViewFreeStyle routine. * * Results: * None. * * Side Effects: * GCs allocated for the textbox are freed. * *---------------------------------------------------------------------- */ static void FreeTextBox(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; if (tbPtr->highlightGC != NULL) { Tk_FreeGC(tvPtr->display, tbPtr->highlightGC); } if (tbPtr->activeGC != NULL) { Tk_FreeGC(tvPtr->display, tbPtr->activeGC); } if (tbPtr->gc != NULL) { Tk_FreeGC(tvPtr->display, tbPtr->gc); } if (tbPtr->icon != NULL) { Blt_TreeViewFreeIcon(tvPtr, tbPtr->icon); } } /* *---------------------------------------------------------------------- * * CreateCheckbox -- * * Creates a "checkbox" style. * * Results: * A pointer to the new style structure. * *---------------------------------------------------------------------- */ static TreeViewStyle * CreateCheckBox(tvPtr, hPtr) TreeView *tvPtr; Blt_HashEntry *hPtr; { TreeViewCheckBox *cbPtr; cbPtr = Blt_Calloc(1, sizeof(TreeViewCheckBox)); assert(cbPtr); cbPtr->classPtr = &checkBoxClass; cbPtr->gap = 4; cbPtr->size = 11; cbPtr->lineWidth = 2; cbPtr->showValue = TRUE; cbPtr->name = Blt_Strdup(Blt_GetHashKey(&tvPtr->styleTable, hPtr)); cbPtr->hashPtr = hPtr; cbPtr->flags = STYLE_CHECKBOX; cbPtr->refCount = 1; Blt_SetHashValue(hPtr, cbPtr); return (TreeViewStyle *)cbPtr; } /* *---------------------------------------------------------------------- * * ConfigureCheckbox -- * * Configures a "checkbox" style. This routine performs * generates the GCs required for a checkbox style. * * Results: * None. * * Side Effects: * GCs are created for the style. * *---------------------------------------------------------------------- */ static void ConfigureCheckBox(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { GC newGC; TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr; XColor *bgColor; XGCValues gcValues; unsigned long gcMask; gcMask = GCForeground | GCBackground | GCFont; gcValues.font = Tk_FontId(CHOOSE(tvPtr->font, cbPtr->font)); bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, cbPtr->border)); gcValues.background = bgColor->pixel; gcValues.foreground = CHOOSE(tvPtr->fgColor, cbPtr->fgColor)->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->gc != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->gc); } cbPtr->gc = newGC; gcValues.background = Tk_3DBorderColor(cbPtr->highlightBorder)->pixel; gcValues.foreground = cbPtr->highlightFgColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->highlightGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->highlightGC); } cbPtr->highlightGC = newGC; gcValues.background = Tk_3DBorderColor(cbPtr->activeBorder)->pixel; gcValues.foreground = cbPtr->activeFgColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->activeGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->activeGC); } cbPtr->activeGC = newGC; gcMask = GCForeground; gcValues.foreground = cbPtr->fillColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->fillGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->fillGC); } cbPtr->fillGC = newGC; gcMask = GCForeground | GCLineWidth; gcValues.line_width = cbPtr->lineWidth; gcValues.foreground = cbPtr->boxColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->boxGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->boxGC); } cbPtr->boxGC = newGC; gcMask = GCForeground | GCLineWidth; gcValues.line_width = 1; gcValues.foreground = cbPtr->checkColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->checkGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->checkGC); } cbPtr->checkGC = newGC; cbPtr->flags |= STYLE_DIRTY; } /* *---------------------------------------------------------------------- * * MeasureCheckbox -- * * Determines the space requirements for the "checkbox" given * the value to be displayed. Depending upon whether an icon * or text is displayed and their relative placements, this * routine computes the space needed for the text entry. * * Results: * None. * * Side Effects: * The width and height fields of *valuePtr* are set with the * computed dimensions. * *---------------------------------------------------------------------- */ static void MeasureCheckBox(tvPtr, stylePtr, valuePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; TreeViewValue *valuePtr; { TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr; int iconWidth, iconHeight; int textWidth, textHeight; int gap; int boxWidth, boxHeight; boxWidth = boxHeight = ODD(cbPtr->size); textWidth = textHeight = iconWidth = iconHeight = 0; valuePtr->width = valuePtr->height = 0; if (cbPtr->icon != NULL) { iconWidth = TreeViewIconWidth(cbPtr->icon); iconHeight = TreeViewIconHeight(cbPtr->icon); } if (cbPtr->onPtr != NULL) { Blt_Free(cbPtr->onPtr); cbPtr->onPtr = NULL; } if (cbPtr->offPtr != NULL) { Blt_Free(cbPtr->offPtr); cbPtr->offPtr = NULL; } gap = 0; if (cbPtr->showValue) { TextStyle ts; char *string; Blt_InitTextStyle(&ts); ts.font = CHOOSE(tvPtr->font, cbPtr->font); ts.anchor = TK_ANCHOR_NW; ts.justify = TK_JUSTIFY_LEFT; string = (cbPtr->onValue != NULL) ? cbPtr->onValue : valuePtr->string; cbPtr->onPtr = Blt_GetTextLayout(string, &ts); string = (cbPtr->offValue != NULL) ? cbPtr->offValue : valuePtr->string; cbPtr->offPtr = Blt_GetTextLayout(string, &ts); textWidth = MAX(cbPtr->offPtr->width, cbPtr->onPtr->width); textHeight = MAX(cbPtr->offPtr->height, cbPtr->onPtr->height); if (cbPtr->icon != NULL) { gap = cbPtr->gap; } } valuePtr->width = cbPtr->gap * 2 + boxWidth + iconWidth + gap + textWidth; valuePtr->height = MAX3(boxHeight, textHeight, iconHeight); } /* *---------------------------------------------------------------------- * * DrawCheckbox -- * * Draws the "checkbox" given the screen coordinates and the * value to be displayed. * * Results: * None. * * Side Effects: * The checkbox value is drawn. * *---------------------------------------------------------------------- */ static void DrawCheckBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, x, y) TreeView *tvPtr; Drawable drawable; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; int x, y; { GC gc; TreeViewColumn *columnPtr; TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr; int iconX, iconY, iconWidth, iconHeight; int textX, textY, textHeight; int gap, columnWidth; Tk_3DBorder border; XColor *fgColor; Tk_Font font; int bool; int borderWidth, relief; TextLayout *textPtr; int boxX, boxY, boxWidth, boxHeight; font = CHOOSE(tvPtr->font, cbPtr->font); columnPtr = valuePtr->columnPtr; borderWidth = 0; relief = TK_RELIEF_FLAT; if (valuePtr == tvPtr->activeValuePtr) { gc = cbPtr->activeGC; border = cbPtr->activeBorder; fgColor = cbPtr->activeFgColor; borderWidth = 1; relief = TK_RELIEF_RAISED; } else if (stylePtr->flags & STYLE_HIGHLIGHT) { gc = cbPtr->highlightGC; border = cbPtr->highlightBorder; fgColor = cbPtr->highlightFgColor; } else { gc = cbPtr->gc; border = CHOOSE(tvPtr->border, cbPtr->border); fgColor = CHOOSE(tvPtr->fgColor, cbPtr->fgColor); } columnWidth = columnPtr->width - PADDING(columnPtr->pad); if (valuePtr == tvPtr->activeValuePtr) { /* * Draw the active or normal background color over the entire * label area. This includes both the tab's text and image. * The rectangle should be 2 pixels wider/taller than this * area. So if the label consists of just an image, we get an * halo around the image when the tab is active. */ if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr)) { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, SELECT_BORDER(tvPtr), x, y, columnWidth, entryPtr->height - 1, borderWidth, relief); } else { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, border, x, y, columnWidth, entryPtr->height - 1, borderWidth, relief); } } if (columnWidth > valuePtr->width) { switch(columnPtr->justify) { case TK_JUSTIFY_RIGHT: x += (columnWidth - valuePtr->width); break; case TK_JUSTIFY_CENTER: x += (columnWidth - valuePtr->width) / 2; break; case TK_JUSTIFY_LEFT: break; } } bool = (strcmp(valuePtr->string, cbPtr->onValue) == 0); textPtr = (bool) ? cbPtr->onPtr : cbPtr->offPtr; /* * Draw the box and check. * * +-----------+ * | | * | * | * | * | * | * * | * | * * | * | * * | * | * | * +-----------+ */ boxWidth = boxHeight = ODD(cbPtr->size); boxX = x + cbPtr->gap; boxY = y + (entryPtr->height - boxHeight) / 2; XFillRectangle(tvPtr->display, drawable, cbPtr->fillGC, boxX, boxY, boxWidth, boxHeight); XDrawRectangle(tvPtr->display, drawable, cbPtr->boxGC, boxX, boxY, boxWidth, boxHeight); if (bool) { int midX, midY; int i; for (i = 0; i < 3; i++) { midX = boxX + 2 * boxWidth / 5; midY = boxY + boxHeight - 5 + i; XDrawLine(tvPtr->display, drawable, cbPtr->checkGC, boxX + 2, boxY + boxHeight / 3 + 1 + i, midX, midY); XDrawLine(tvPtr->display, drawable, cbPtr->checkGC, midX, midY, boxX + boxWidth - 2, boxY + i + 1); } } #ifdef notdef textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */ #endif iconWidth = iconHeight = 0; if (cbPtr->icon != NULL) { iconWidth = TreeViewIconWidth(cbPtr->icon); iconHeight = TreeViewIconHeight(cbPtr->icon); } textHeight = 0; gap = 0; if (cbPtr->showValue) { textHeight = textPtr->height; if (cbPtr->icon != NULL) { gap = cbPtr->gap; } } x = boxX + boxWidth + cbPtr->gap; /* The icon sits to the left of the text. */ iconX = x; iconY = y + (entryPtr->height - iconHeight) / 2; textX = iconX + iconWidth + gap; textY = y + (entryPtr->height - textHeight) / 2; if (cbPtr->icon != NULL) { Tk_RedrawImage(TreeViewIconBits(cbPtr->icon), 0, 0, iconWidth, iconHeight, drawable, iconX, iconY); } if ((cbPtr->showValue) && (textPtr != NULL)) { TextStyle ts; XColor *color; if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr)) { color = SELECT_FG(tvPtr); XSetForeground(tvPtr->display, gc, color->pixel); } else if (entryPtr->color != NULL) { color = entryPtr->color; XSetForeground(tvPtr->display, gc, color->pixel); } else { color = fgColor; } Blt_SetDrawTextStyle(&ts, font, gc, color, fgColor, NULL, 0.0, TK_ANCHOR_NW, TK_JUSTIFY_LEFT, 0, 0); Blt_DrawTextLayout(tvPtr->tkwin, drawable, textPtr, &ts, textX, textY); if (color != fgColor) { XSetForeground(tvPtr->display, gc, fgColor->pixel); } } stylePtr->flags &= ~STYLE_DIRTY; } /* *---------------------------------------------------------------------- * * PickCheckbox -- * * Draws the "checkbox" given the screen coordinates and the * value to be displayed. * * Results: * None. * * Side Effects: * The checkbox value is drawn. * *---------------------------------------------------------------------- */ static int PickCheckBox(entryPtr, valuePtr, stylePtr, worldX, worldY) TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; int worldX, worldY; { TreeViewColumn *columnPtr; TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr; int columnWidth; int x, y, width, height; columnPtr = valuePtr->columnPtr; columnWidth = columnPtr->width - (2 * columnPtr->borderWidth + PADDING(columnPtr->pad)); if (columnWidth > valuePtr->width) { switch(columnPtr->justify) { case TK_JUSTIFY_RIGHT: worldX += (columnWidth - valuePtr->width); break; case TK_JUSTIFY_CENTER: worldX += (columnWidth - valuePtr->width) / 2; break; case TK_JUSTIFY_LEFT: break; } } width = height = ODD(cbPtr->size) + 2 * cbPtr->lineWidth; x = columnPtr->worldX + columnPtr->pad.side1 + cbPtr->gap - cbPtr->lineWidth; y = entryPtr->worldY + (entryPtr->height - height) / 2; if ((worldX >= x) && (worldX < (x + width)) && (worldY >= y) && (worldY < (y + height))) { return TRUE; } return FALSE; } /* *---------------------------------------------------------------------- * * EditCheckbox -- * * Edits the "checkbox". * * Results: * None. * * Side Effects: * The checkbox value is drawn. * *---------------------------------------------------------------------- */ static int EditCheckBox(tvPtr, entryPtr, valuePtr, stylePtr) TreeView *tvPtr; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; { TreeViewColumn *columnPtr; TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr; Tcl_Obj *objPtr; columnPtr = valuePtr->columnPtr; if (Blt_TreeGetValueByKey(tvPtr->interp, tvPtr->tree, entryPtr->node, columnPtr->key, &objPtr) != TCL_OK) { return TCL_ERROR; } if (strcmp(Tcl_GetString(objPtr), cbPtr->onValue) == 0) { objPtr = Tcl_NewStringObj(cbPtr->offValue, -1); } else { objPtr = Tcl_NewStringObj(cbPtr->onValue, -1); } entryPtr->flags |= ENTRY_DIRTY; tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_RESORT); if (Blt_TreeSetValueByKey(tvPtr->interp, tvPtr->tree, entryPtr->node, columnPtr->key, objPtr) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * FreeCheckbox -- * * Releases resources allocated for the checkbox. The resources * freed by this routine are specific only to the "checkbox". * Other resources (common to all styles) are freed in the * Blt_TreeViewFreeStyle routine. * * Results: * None. * * Side Effects: * GCs allocated for the checkbox are freed. * *---------------------------------------------------------------------- */ static void FreeCheckBox(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr; if (cbPtr->highlightGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->highlightGC); } if (cbPtr->activeGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->activeGC); } if (cbPtr->gc != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->gc); } if (cbPtr->fillGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->fillGC); } if (cbPtr->boxGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->boxGC); } if (cbPtr->checkGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->checkGC); } if (cbPtr->icon != NULL) { Blt_TreeViewFreeIcon(tvPtr, cbPtr->icon); } if (cbPtr->offPtr != NULL) { Blt_Free(cbPtr->offPtr); } if (cbPtr->onPtr != NULL) { Blt_Free(cbPtr->onPtr); } } /* *---------------------------------------------------------------------- * * CreateComboBox -- * * Creates a "combobox" style. * * Results: * A pointer to the new style structure. * *---------------------------------------------------------------------- */ static TreeViewStyle * CreateComboBox(tvPtr, hPtr) TreeView *tvPtr; Blt_HashEntry *hPtr; { TreeViewComboBox *cbPtr; cbPtr = Blt_Calloc(1, sizeof(TreeViewComboBox)); assert(cbPtr); cbPtr->classPtr = &comboBoxClass; cbPtr->gap = STYLE_GAP; cbPtr->buttonRelief = TK_RELIEF_RAISED; cbPtr->buttonBorderWidth = 1; cbPtr->borderWidth = 1; cbPtr->relief = TK_RELIEF_FLAT; cbPtr->name = Blt_Strdup(Blt_GetHashKey(&tvPtr->styleTable, hPtr)); cbPtr->hashPtr = hPtr; cbPtr->flags = STYLE_COMBOBOX; cbPtr->refCount = 1; Blt_SetHashValue(hPtr, cbPtr); return (TreeViewStyle *)cbPtr; } /* *---------------------------------------------------------------------- * * ConfigureComboBox -- * * Configures a "combobox" style. This routine performs * generates the GCs required for a combobox style. * * Results: * None. * * Side Effects: * GCs are created for the style. * *---------------------------------------------------------------------- */ static void ConfigureComboBox(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { GC newGC; TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr; XColor *bgColor; XGCValues gcValues; unsigned long gcMask; gcValues.font = Tk_FontId(CHOOSE(tvPtr->font, cbPtr->font)); bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, cbPtr->border)); gcMask = GCForeground | GCBackground | GCFont; /* Normal foreground */ gcValues.background = bgColor->pixel; gcValues.foreground = CHOOSE(tvPtr->fgColor, cbPtr->fgColor)->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->gc != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->gc); } cbPtr->gc = newGC; /* Highlight foreground */ gcValues.background = Tk_3DBorderColor(cbPtr->highlightBorder)->pixel; gcValues.foreground = cbPtr->highlightFgColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->highlightGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->highlightGC); } cbPtr->highlightGC = newGC; /* Active foreground */ gcValues.background = Tk_3DBorderColor(cbPtr->activeBorder)->pixel; gcValues.foreground = cbPtr->activeFgColor->pixel; newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues); if (cbPtr->activeGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->activeGC); } cbPtr->activeGC = newGC; cbPtr->flags |= STYLE_DIRTY; } /* *---------------------------------------------------------------------- * * MeasureComboBox -- * * Determines the space requirements for the "combobox" given * the value to be displayed. Depending upon whether an icon * or text is displayed and their relative placements, this * routine computes the space needed for the text entry. * * Results: * None. * * Side Effects: * The width and height fields of *valuePtr* are set with the * computed dimensions. * *---------------------------------------------------------------------- */ static void MeasureComboBox(tvPtr, stylePtr, valuePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; TreeViewValue *valuePtr; { TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr; int iconWidth, iconHeight; int textWidth, textHeight; int gap; Tk_Font font; textWidth = textHeight = 0; iconWidth = iconHeight = 0; valuePtr->width = valuePtr->height = 0; if (cbPtr->icon != NULL) { iconWidth = TreeViewIconWidth(cbPtr->icon); iconHeight = TreeViewIconHeight(cbPtr->icon); } if (valuePtr->textPtr != NULL) { Blt_Free(valuePtr->textPtr); valuePtr->textPtr = NULL; } font = CHOOSE(tvPtr->font, cbPtr->font); if (valuePtr->string != NULL) { /* New string defined. */ TextStyle ts; Blt_InitTextStyle(&ts); ts.font = font; ts.anchor = TK_ANCHOR_NW; ts.justify = TK_JUSTIFY_LEFT; valuePtr->textPtr = Blt_GetTextLayout(valuePtr->string, &ts); } gap = 0; if (valuePtr->textPtr != NULL) { textWidth = valuePtr->textPtr->width; textHeight = valuePtr->textPtr->height; if (cbPtr->icon != NULL) { gap = cbPtr->gap; } } cbPtr->buttonWidth = STD_ARROW_WIDTH + 6 + 2 * cbPtr->buttonBorderWidth; valuePtr->width = 2 * cbPtr->borderWidth + iconWidth + 4 * gap + cbPtr->buttonWidth + textWidth; valuePtr->height = MAX(textHeight, iconHeight) + 2 * cbPtr->borderWidth; } /* *---------------------------------------------------------------------- * * DrawComboBox -- * * Draws the "combobox" given the screen coordinates and the * value to be displayed. * * Results: * None. * * Side Effects: * The combobox value is drawn. * *---------------------------------------------------------------------- */ static void DrawComboBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, x, y) TreeView *tvPtr; Drawable drawable; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; int x, y; { GC gc; TreeViewColumn *columnPtr; TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr; int iconX, iconY, iconWidth, iconHeight; int textX, textY, textHeight; int buttonX, buttonY; int gap, columnWidth; Tk_3DBorder border; XColor *fgColor; columnPtr = valuePtr->columnPtr; if (stylePtr->flags & STYLE_HIGHLIGHT) { gc = cbPtr->highlightGC; border = cbPtr->highlightBorder; fgColor = cbPtr->highlightFgColor; } else { gc = cbPtr->gc; border = CHOOSE(tvPtr->border, cbPtr->border); fgColor = CHOOSE(tvPtr->fgColor, cbPtr->fgColor); } if (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr)) { /* * Draw the active or normal background color over the entire * label area. This includes both the tab's text and image. * The rectangle should be 2 pixels wider/taller than this * area. So if the label consists of just an image, we get an * halo around the image when the tab is active. */ if (border != NULL) { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, border, x, y, columnPtr->width, entryPtr->height, cbPtr->borderWidth, cbPtr->relief); } } buttonX = x + columnPtr->width; buttonX -= columnPtr->pad.side2 + cbPtr->borderWidth + cbPtr->buttonWidth + cbPtr->gap; buttonY = y; columnWidth = columnPtr->width - (2 * columnPtr->borderWidth + PADDING(columnPtr->pad)); if (columnWidth > valuePtr->width) { switch(columnPtr->justify) { case TK_JUSTIFY_RIGHT: x += (columnWidth - valuePtr->width); break; case TK_JUSTIFY_CENTER: x += (columnWidth - valuePtr->width) / 2; break; case TK_JUSTIFY_LEFT: break; } } #ifdef notdef textX = textY = iconX = iconY = 0; /* Suppress compiler warning. */ #endif iconWidth = iconHeight = 0; if (cbPtr->icon != NULL) { iconWidth = TreeViewIconWidth(cbPtr->icon); iconHeight = TreeViewIconHeight(cbPtr->icon); } textHeight = 0; if (valuePtr->textPtr != NULL) { textHeight = valuePtr->textPtr->height; } gap = 0; if ((cbPtr->icon != NULL) && (valuePtr->textPtr != NULL)) { gap = cbPtr->gap; } iconX = x + gap; iconY = y + (entryPtr->height - iconHeight) / 2; textX = iconX + iconWidth + gap; textY = y + (entryPtr->height - textHeight) / 2; if (cbPtr->icon != NULL) { Tk_RedrawImage(TreeViewIconBits(cbPtr->icon), 0, 0, iconWidth, iconHeight, drawable, iconX, iconY); } if (valuePtr->textPtr != NULL) { TextStyle ts; XColor *color; Tk_Font font; font = CHOOSE(tvPtr->font, cbPtr->font); if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr)) { color = SELECT_FG(tvPtr); XSetForeground(tvPtr->display, gc, color->pixel); } else if (entryPtr->color != NULL) { color = entryPtr->color; XSetForeground(tvPtr->display, gc, color->pixel); } else { color = fgColor; } Blt_SetDrawTextStyle(&ts, font, gc, color, fgColor, NULL, 0.0, TK_ANCHOR_NW, TK_JUSTIFY_LEFT, 0, 0); Blt_DrawTextLayout(tvPtr->tkwin, drawable, valuePtr->textPtr, &ts, textX, textY); if (color != fgColor) { XSetForeground(tvPtr->display, gc, fgColor->pixel); } } if (valuePtr == tvPtr->activeValuePtr) { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, stylePtr->activeBorder, buttonX, buttonY + cbPtr->borderWidth, cbPtr->buttonWidth, entryPtr->height - 2 * cbPtr->borderWidth, cbPtr->buttonBorderWidth, cbPtr->buttonRelief); } else { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, columnPtr->titleBorder, buttonX, buttonY + cbPtr->borderWidth, cbPtr->buttonWidth, entryPtr->height - 2 * cbPtr->borderWidth, cbPtr->buttonBorderWidth, cbPtr->buttonRelief); } buttonX += cbPtr->buttonWidth / 2; buttonY += entryPtr->height / 2; Blt_DrawArrow(tvPtr->display, drawable, gc, buttonX, buttonY, STD_ARROW_HEIGHT, ARROW_DOWN); stylePtr->flags &= ~STYLE_DIRTY; } /* *---------------------------------------------------------------------- * * PickCombobox -- * * Draws the "checkbox" given the screen coordinates and the * value to be displayed. * * Results: * None. * * Side Effects: * The checkbox value is drawn. * *---------------------------------------------------------------------- */ static int PickComboBox(entryPtr, valuePtr, stylePtr, worldX, worldY) TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; int worldX, worldY; { TreeViewColumn *columnPtr; TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr; int x, y, width, height; columnPtr = valuePtr->columnPtr; width = cbPtr->buttonWidth; height = entryPtr->height - 4; x = columnPtr->worldX + columnPtr->width - columnPtr->pad.side2 - cbPtr->borderWidth - columnPtr->borderWidth - width; y = entryPtr->worldY + cbPtr->borderWidth; if ((worldX >= x) && (worldX < (x + width)) && (worldY >= y) && (worldY < (y + height))) { return TRUE; } return FALSE; } /* *---------------------------------------------------------------------- * * EditCombobox -- * * Edits the "combobox". * * Results: * None. * * Side Effects: * The checkbox value is drawn. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int EditComboBox(tvPtr, entryPtr, valuePtr, stylePtr) TreeView *tvPtr; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; TreeViewStyle *stylePtr; /* Not used. */ { return Blt_TreeViewTextbox(tvPtr, entryPtr, valuePtr->columnPtr); } /* *---------------------------------------------------------------------- * * FreeComboBox -- * * Releases resources allocated for the combobox. The resources * freed by this routine are specific only to the "combobox". * Other resources (common to all styles) are freed in the * Blt_TreeViewFreeStyle routine. * * Results: * None. * * Side Effects: * GCs allocated for the combobox are freed. * *---------------------------------------------------------------------- */ static void FreeComboBox(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr; if (cbPtr->highlightGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->highlightGC); } if (cbPtr->activeGC != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->activeGC); } if (cbPtr->gc != NULL) { Tk_FreeGC(tvPtr->display, cbPtr->gc); } if (cbPtr->icon != NULL) { Blt_TreeViewFreeIcon(tvPtr, cbPtr->icon); } } static TreeViewStyle * GetStyle(interp, tvPtr, styleName) Tcl_Interp *interp; TreeView *tvPtr; char *styleName; { Blt_HashEntry *hPtr; hPtr = Blt_FindHashEntry(&tvPtr->styleTable, styleName); if (hPtr == NULL) { if (interp != NULL) { Tcl_AppendResult(interp, "can't find cell style \"", styleName, "\"", (char *)NULL); } return NULL; } return Blt_GetHashValue(hPtr); } int Blt_TreeViewGetStyle(interp, tvPtr, styleName, stylePtrPtr) Tcl_Interp *interp; TreeView *tvPtr; char *styleName; TreeViewStyle **stylePtrPtr; { TreeViewStyle *stylePtr; stylePtr = GetStyle(interp, tvPtr, styleName); if (stylePtr == NULL) { return TCL_ERROR; } stylePtr->refCount++; *stylePtrPtr = stylePtr; return TCL_OK; } static TreeViewStyle * CreateStyle(interp, tvPtr, type, styleName, objc, objv) Tcl_Interp *interp; TreeView *tvPtr; /* TreeView widget. */ int type; /* Type of style: either * STYLE_TEXTBOX, * STYLE_COMBOBOX, or * STYLE_CHECKBOX */ char *styleName; /* Name of the new style. */ int objc; Tcl_Obj *CONST *objv; { Blt_HashEntry *hPtr; int isNew; TreeViewStyle *stylePtr; hPtr = Blt_CreateHashEntry(&tvPtr->styleTable, styleName, &isNew); if (!isNew) { if (interp != NULL) { Tcl_AppendResult(interp, "cell style \"", styleName, "\" already exists", (char *)NULL); } return NULL; } /* Create the new marker based upon the given type */ switch (type) { case STYLE_TEXTBOX: stylePtr = CreateTextBox(tvPtr, hPtr); break; case STYLE_COMBOBOX: stylePtr = CreateComboBox(tvPtr, hPtr); break; case STYLE_CHECKBOX: stylePtr = CreateCheckBox(tvPtr, hPtr); break; default: return NULL; } bltTreeViewIconOption.clientData = tvPtr; if (Blt_ConfigureComponentFromObj(interp, tvPtr->tkwin, styleName, stylePtr->classPtr->className, stylePtr->classPtr->specsPtr, objc, objv, (char *)stylePtr, 0) != TCL_OK) { Blt_TreeViewFreeStyle(tvPtr, stylePtr); return NULL; } return stylePtr; } void Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { (*stylePtr->classPtr->configProc)(tvPtr, stylePtr); stylePtr->flags |= STYLE_DIRTY; Blt_TreeViewEventuallyRedraw(tvPtr); } TreeViewStyle * Blt_TreeViewCreateStyle(interp, tvPtr, type, styleName) Tcl_Interp *interp; TreeView *tvPtr; /* TreeView widget. */ int type; /* Type of style: either * STYLE_TEXTBOX, * STYLE_COMBOBOX, or * STYLE_CHECKBOX */ char *styleName; /* Name of the new style. */ { return CreateStyle(interp, tvPtr, type, styleName, 0, (Tcl_Obj **)NULL); } void Blt_TreeViewFreeStyle(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { stylePtr->refCount--; #ifdef notdef fprint(f(stderr, "Blt_TreeViewFreeStyle %s count=%d\n", stylePtr->name, stylePtr->refCount); #endif /* Remove the style from the hash table so that it's name can be used.*/ /* If no cell is using the style, remove it.*/ if ((stylePtr->refCount <= 0) && !(stylePtr->flags & STYLE_USER)){ #ifdef notdef fprintf(stderr, "freeing %s\n", stylePtr->name); #endif bltTreeViewIconOption.clientData = tvPtr; Blt_FreeObjOptions(stylePtr->classPtr->specsPtr, (char *)stylePtr, tvPtr->display, 0); (*stylePtr->classPtr->freeProc)(tvPtr, stylePtr); if (stylePtr->hashPtr != NULL) { Blt_DeleteHashEntry(&tvPtr->styleTable, stylePtr->hashPtr); } if (stylePtr->name != NULL) { Blt_Free(stylePtr->name); } Blt_Free(stylePtr); } } void Blt_TreeViewSetStyleIcon(tvPtr, stylePtr, icon) TreeView *tvPtr; TreeViewStyle *stylePtr; TreeViewIcon icon; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; if (tbPtr->icon != NULL) { Blt_TreeViewFreeIcon(tvPtr, tbPtr->icon); } tbPtr->icon = icon; } GC Blt_TreeViewGetStyleGC(stylePtr) TreeViewStyle *stylePtr; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; return tbPtr->gc; } Tk_3DBorder Blt_TreeViewGetStyleBorder(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; Tk_3DBorder border; border = (tbPtr->flags & STYLE_HIGHLIGHT) ? tbPtr->highlightBorder : tbPtr->border; return (border != NULL) ? border : tvPtr->border; } Tk_Font Blt_TreeViewGetStyleFont(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; if (tbPtr->font != NULL) { return tbPtr->font; } return tvPtr->font; } XColor * Blt_TreeViewGetStyleFg(tvPtr, stylePtr) TreeView *tvPtr; TreeViewStyle *stylePtr; { TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr; if (tbPtr->fgColor != NULL) { return tbPtr->fgColor; } return tvPtr->fgColor; } static void DrawValue(tvPtr, entryPtr, valuePtr) TreeView *tvPtr; TreeViewEntry *entryPtr; TreeViewValue *valuePtr; { Drawable drawable; int sx, sy, dx, dy; int width, height; int left, right, top, bottom; TreeViewColumn *columnPtr; TreeViewStyle *stylePtr; stylePtr = valuePtr->stylePtr; if (stylePtr == NULL) { stylePtr = valuePtr->columnPtr->stylePtr; } if (stylePtr->cursor != None) { if (valuePtr == tvPtr->activeValuePtr) { Tk_DefineCursor(tvPtr->tkwin, stylePtr->cursor); } else { if (tvPtr->cursor != None) { Tk_DefineCursor(tvPtr->tkwin, tvPtr->cursor); } else { Tk_UndefineCursor(tvPtr->tkwin); } } } columnPtr = valuePtr->columnPtr; dx = SCREENX(tvPtr, columnPtr->worldX) + columnPtr->pad.side1; dy = SCREENY(tvPtr, entryPtr->worldY); height = entryPtr->height - 1; width = valuePtr->columnPtr->width - PADDING(columnPtr->pad); top = tvPtr->titleHeight + tvPtr->inset; bottom = Tk_Height(tvPtr->tkwin) - tvPtr->inset; left = tvPtr->inset; right = Tk_Width(tvPtr->tkwin) - tvPtr->inset; if (((dx + width) < left) || (dx > right) || ((dy + height) < top) || (dy > bottom)) { return; /* Value is clipped. */ } drawable = Tk_GetPixmap(tvPtr->display, Tk_WindowId(tvPtr->tkwin), width, height, Tk_Depth(tvPtr->tkwin)); /* Draw the background of the value. */ if ((valuePtr == tvPtr->activeValuePtr) || (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr))) { Tk_3DBorder border; border = Blt_TreeViewGetStyleBorder(tvPtr, tvPtr->stylePtr); Blt_Fill3DRectangle(tvPtr->tkwin, drawable, border, 0, 0, width, height, 0, TK_RELIEF_FLAT); } else { Blt_Fill3DRectangle(tvPtr->tkwin, drawable, SELECT_BORDER(tvPtr), 0, 0, width, height, tvPtr->selBorderWidth, tvPtr->selRelief); } Blt_TreeViewDrawValue(tvPtr, entryPtr, valuePtr, drawable, 0, 0); /* Clip the drawable if necessary */ sx = sy = 0; if (dx < left) { width -= left - dx; sx += left - dx; dx = left; } if ((dx + width) >= right) { width -= (dx + width) - right; } if (dy < top) { height -= top - dy; sy += top - dy; dy = top; } if ((dy + height) >= bottom) { height -= (dy + height) - bottom; } XCopyArea(tvPtr->display, drawable, Tk_WindowId(tvPtr->tkwin), tvPtr->lineGC, sx, sy, width, height, dx, dy); Tk_FreePixmap(tvPtr->display, drawable); } /* *---------------------------------------------------------------------- * * StyleActivateOp -- * * Turns on/off highlighting for a particular style. * * .t style activate entry column * * Results: * A standard Tcl result. If TCL_ERROR is returned, then * interp->result contains an error message. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleActivateOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; { TreeViewEntry *entryPtr; TreeViewValue *valuePtr, *oldPtr; oldPtr = tvPtr->activeValuePtr; if (objc == 3) { Tcl_Obj *listObjPtr; valuePtr = tvPtr->activeValuePtr; entryPtr = tvPtr->activePtr; listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL); if ((entryPtr != NULL) && (valuePtr != NULL)) { Tcl_Obj *objPtr; objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node)); Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); objPtr = Tcl_NewStringObj(valuePtr->columnPtr->key, -1); Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); } Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; } else if (objc == 4) { tvPtr->activeValuePtr = NULL; if ((oldPtr != NULL) && (tvPtr->activePtr != NULL)) { DrawValue(tvPtr, tvPtr->activePtr, oldPtr); } } else { TreeViewColumn *columnPtr; if (Blt_TreeViewGetEntry(tvPtr, objv[3], &entryPtr) != TCL_OK) { return TCL_ERROR; } if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr) != TCL_OK) { return TCL_ERROR; } valuePtr = Blt_TreeViewFindValue(entryPtr, columnPtr); if (valuePtr == NULL) { return TCL_OK; } tvPtr->activePtr = entryPtr; tvPtr->activeColumnPtr = columnPtr; oldPtr = tvPtr->activeValuePtr; tvPtr->activeValuePtr = valuePtr; if (valuePtr != oldPtr) { if (oldPtr != NULL) { DrawValue(tvPtr, entryPtr, oldPtr); } if (valuePtr != NULL) { DrawValue(tvPtr, entryPtr, valuePtr); } } } return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleCgetOp -- * * .t style cget "styleName" -background * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleCgetOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3])); if (stylePtr == NULL) { return TCL_ERROR; } return Blt_ConfigureValueFromObj(interp, tvPtr->tkwin, stylePtr->classPtr->specsPtr, (char *)tvPtr, objv[4], 0); } /* *---------------------------------------------------------------------- * * StyleCheckBoxOp -- * * .t style checkbox "styleName" -background blue * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleCheckBoxOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; stylePtr = CreateStyle(interp, tvPtr, STYLE_CHECKBOX, Tcl_GetString(objv[3]), objc - 4, objv + 4); if (stylePtr == NULL) { return TCL_ERROR; } stylePtr->refCount = 0; stylePtr->flags |= STYLE_USER; Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr); Tcl_SetObjResult(interp, objv[3]); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleComboBoxOp -- * * .t style combobox "styleName" -background blue * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleComboBoxOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; stylePtr = CreateStyle(interp, tvPtr, STYLE_COMBOBOX, Tcl_GetString(objv[3]), objc - 4, objv + 4); if (stylePtr == NULL) { return TCL_ERROR; } stylePtr->refCount = 0; stylePtr->flags |= STYLE_USER; Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr); Tcl_SetObjResult(interp, objv[3]); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleConfigureOp -- * * This procedure is called to process a list of configuration * options database, in order to reconfigure a style. * * .t style configure "styleName" option value * * Results: * A standard Tcl result. If TCL_ERROR is returned, then * interp->result contains an error message. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for stylePtr; old resources get freed, if there * were any. * *---------------------------------------------------------------------- */ static int StyleConfigureOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3])); if (stylePtr == NULL) { return TCL_ERROR; } if (objc == 4) { return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, stylePtr->classPtr->specsPtr, (char *)stylePtr, (Tcl_Obj *)NULL, 0); } else if (objc == 5) { return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, stylePtr->classPtr->specsPtr, (char *)stylePtr, objv[5], 0); } bltTreeViewIconOption.clientData = tvPtr; if (Blt_ConfigureWidgetFromObj(interp, tvPtr->tkwin, stylePtr->classPtr->specsPtr, objc - 4, objv + 4, (char *)stylePtr, BLT_CONFIG_OBJV_ONLY) != TCL_OK) { return TCL_ERROR; } (*stylePtr->classPtr->configProc)(tvPtr, stylePtr); stylePtr->flags |= STYLE_DIRTY; tvPtr->flags |= (TV_LAYOUT | TV_DIRTY); Blt_TreeViewEventuallyRedraw(tvPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleForgetOp -- * * Eliminates one or more style names. A style still may be in * use after its name has been officially removed. Only its hash * table entry is removed. The style itself remains until its * reference count returns to zero (i.e. no one else is using it). * * .t style forget "styleName"... * * Results: * A standard Tcl result. If TCL_ERROR is returned, then * interp->result contains an error message. * *---------------------------------------------------------------------- */ static int StyleForgetOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; int i; for (i = 3; i < objc; i++) { stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[i])); if (stylePtr == NULL) { return TCL_ERROR; } if (stylePtr->hashPtr != NULL) { Blt_DeleteHashEntry(&tvPtr->styleTable, stylePtr->hashPtr); stylePtr->hashPtr = NULL; } stylePtr->flags &= ~STYLE_USER; if (stylePtr->refCount <= 0) { Blt_TreeViewFreeStyle(tvPtr, stylePtr); } } Blt_TreeViewEventuallyRedraw(tvPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleHighlightOp -- * * Turns on/off highlighting for a particular style. * * .t style highlight styleName on|off * * Results: * A standard Tcl result. If TCL_ERROR is returned, then * interp->result contains an error message. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleHighlightOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; int bool, oldBool; stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3])); if (stylePtr == NULL) { return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[4], &bool) != TCL_OK) { return TCL_ERROR; } oldBool = ((stylePtr->flags & STYLE_HIGHLIGHT) != 0); if (oldBool != bool) { if (bool) { stylePtr->flags |= STYLE_HIGHLIGHT; } else { stylePtr->flags &= ~STYLE_HIGHLIGHT; } Blt_TreeViewEventuallyRedraw(tvPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleNamesOp -- * * Lists the names of all the current styles in the treeview widget. * * .t style names * * Results: * Always TCL_OK. * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleNamesOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; /* Not used. */ { Blt_HashEntry *hPtr; Blt_HashSearch cursor; Tcl_Obj *listObjPtr, *objPtr; TreeViewStyle *stylePtr; listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL); for (hPtr = Blt_FirstHashEntry(&tvPtr->styleTable, &cursor); hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) { stylePtr = Blt_GetHashValue(hPtr); objPtr = Tcl_NewStringObj(stylePtr->name, -1); Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); } Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleSetOp -- * * Sets a style for a given key for all the ids given. * * .t style set styleName key node... * * Results: * A standard Tcl result. If TCL_ERROR is returned, then * interp->result contains an error message. * *---------------------------------------------------------------------- */ static int StyleSetOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; Tcl_Obj *CONST *objv; { Blt_TreeKey key; TreeViewEntry *entryPtr; TreeViewStyle *stylePtr, *oldStylePtr; TreeViewTagInfo info; int i; stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3])); if (stylePtr == NULL) { return TCL_ERROR; } key = Blt_TreeGetKey(Tcl_GetString(objv[4])); stylePtr->flags |= STYLE_LAYOUT; for (i = 5; i < objc; i++) { if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[i], &info) != TCL_OK) { return TCL_ERROR; } for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL; entryPtr = Blt_TreeViewNextTaggedEntry(&info)) { register TreeViewValue *valuePtr; for (valuePtr = entryPtr->values; valuePtr != NULL; valuePtr = valuePtr->nextPtr) { if (valuePtr->columnPtr->key == key) { stylePtr->refCount++; oldStylePtr = valuePtr->stylePtr; valuePtr->stylePtr = stylePtr; if (oldStylePtr != NULL) { Blt_TreeViewFreeStyle(tvPtr, oldStylePtr); } break; } } } } Blt_TreeViewEventuallyRedraw(tvPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleTextBoxOp -- * * .t style text "styleName" -background blue * *---------------------------------------------------------------------- */ /*ARGSUSED*/ static int StyleTextBoxOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; /* Not used. */ Tcl_Obj *CONST *objv; { TreeViewStyle *stylePtr; stylePtr = CreateStyle(interp, tvPtr, STYLE_TEXTBOX, Tcl_GetString(objv[3]), objc - 4, objv + 4); if (stylePtr == NULL) { return TCL_ERROR; } stylePtr->refCount = 0; stylePtr->flags |= STYLE_USER; Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr); Tcl_SetObjResult(interp, objv[3]); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleUnsetOp -- * * Removes a style for a given key for all the ids given. * The cell's style is returned to its default state. * * .t style unset styleName key node... * * Results: * A standard Tcl result. If TCL_ERROR is returned, then * interp->result contains an error message. * *---------------------------------------------------------------------- */ static int StyleUnsetOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; Tcl_Obj *CONST *objv; { Blt_TreeKey key; TreeViewEntry *entryPtr; TreeViewStyle *stylePtr; TreeViewTagInfo info; int i; stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3])); if (stylePtr == NULL) { return TCL_ERROR; } key = Blt_TreeGetKey(Tcl_GetString(objv[4])); stylePtr->flags |= STYLE_LAYOUT; for (i = 5; i < objc; i++) { if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[i], &info) != TCL_OK) { return TCL_ERROR; } for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL; entryPtr = Blt_TreeViewNextTaggedEntry(&info)) { register TreeViewValue *valuePtr; for (valuePtr = entryPtr->values; valuePtr != NULL; valuePtr = valuePtr->nextPtr) { if (valuePtr->columnPtr->key == key) { if (valuePtr->stylePtr != NULL) { Blt_TreeViewFreeStyle(tvPtr, valuePtr->stylePtr); valuePtr->stylePtr = NULL; } break; } } } } Blt_TreeViewEventuallyRedraw(tvPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StyleOp -- * * .t style activate $node $column * .t style activate * .t style cget "highlight" -foreground * .t style configure "highlight" -fg blue -bg green * .t style checkbox "highlight" * .t style highlight "highlight" on|off * .t style combobox "highlight" * .t style text "highlight" * .t style forget "highlight" * .t style get "mtime" $node * .t style names * .t style set "mtime" "highlight" all * .t style unset "mtime" all * *---------------------------------------------------------------------- */ static Blt_OpSpec styleOps[] = { {"activate", 1, (Blt_Op)StyleActivateOp, 3, 5,"entry column",}, {"cget", 2, (Blt_Op)StyleCgetOp, 5, 5, "styleName option",}, {"checkbox", 2, (Blt_Op)StyleCheckBoxOp, 4, 0, "styleName options...",}, {"combobox", 3, (Blt_Op)StyleComboBoxOp, 4, 0, "styleName options...",}, {"configure", 3, (Blt_Op)StyleConfigureOp, 4, 0, "styleName options...",}, {"forget", 1, (Blt_Op)StyleForgetOp, 3, 0, "styleName...",}, {"highlight", 1, (Blt_Op)StyleHighlightOp, 5, 5, "styleName boolean",}, {"names", 1, (Blt_Op)StyleNamesOp, 3, 3, "",}, {"set", 1, (Blt_Op)StyleSetOp, 6, 6, "key styleName tagOrId...",}, {"textbox", 1, (Blt_Op)StyleTextBoxOp, 4, 0, "styleName options...",}, {"unset", 1, (Blt_Op)StyleUnsetOp, 5, 5, "key tagOrId",}, }; static int nStyleOps = sizeof(styleOps) / sizeof(Blt_OpSpec); int Blt_TreeViewStyleOp(tvPtr, interp, objc, objv) TreeView *tvPtr; Tcl_Interp *interp; int objc; Tcl_Obj *CONST *objv; { Blt_Op proc; int result; proc = Blt_GetOpFromObj(interp, nStyleOps, styleOps, BLT_OP_ARG2, objc, objv, 0); if (proc == NULL) { return TCL_ERROR; } result = (*proc)(tvPtr, interp, objc, objv); return result; } #endif /* NO_TREEVIEW */