summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorjoye <joye>2014-02-11 23:12:27 (GMT)
committerjoye <joye>2014-02-11 23:12:27 (GMT)
commitb6ceb4fad7349af3398c1d076221662aa05ede47 (patch)
tree165d3673aa88070507f87687029f99c96f3c87d1 /src
parent1b5777512ab2c4aed0ab186edfe36c86fb40590c (diff)
downloadblt-b6ceb4fad7349af3398c1d076221662aa05ede47.zip
blt-b6ceb4fad7349af3398c1d076221662aa05ede47.tar.gz
blt-b6ceb4fad7349af3398c1d076221662aa05ede47.tar.bz2
*** empty log message ***
Diffstat (limited to 'src')
-rw-r--r--src/bltConfig.C1
-rw-r--r--src/bltGrHairs.C3
-rw-r--r--src/bltGrLegd.C4150
-rw-r--r--src/bltGrLegd.h4
-rw-r--r--src/bltGraph.C28
-rw-r--r--src/bltGraph.h4
6 files changed, 1882 insertions, 2308 deletions
diff --git a/src/bltConfig.C b/src/bltConfig.C
index dc69c33..7368173 100644
--- a/src/bltConfig.C
+++ b/src/bltConfig.C
@@ -93,7 +93,6 @@ Tk_ObjCustomOption backgroundObjOption =
"background", BackgroundSetProc, BackgroundGetProc, NULL, NULL, NULL
};
-
static int BackgroundSetProc(ClientData clientData, Tcl_Interp *interp,
Tk_Window tkwin, Tcl_Obj** objPtr, char* widgRec,
int offset, char* save, int flags)
diff --git a/src/bltGrHairs.C b/src/bltGrHairs.C
index e3cffd9..2124598 100644
--- a/src/bltGrHairs.C
+++ b/src/bltGrHairs.C
@@ -98,6 +98,7 @@ int Blt_CreateCrosshairs(Graph* graphPtr)
chPtr->hidden = TRUE;
chPtr->hotSpot.x = chPtr->hotSpot.y = -1;
graphPtr->crosshairs = chPtr;
+
return TCL_OK;
}
@@ -144,7 +145,7 @@ static int CgetOp(Graph* graphPtr, Tcl_Interp* interp,
return TCL_OK;
}
-static int ConfigureOp(Graph *graphPtr, Tcl_Interp *interp,
+static int ConfigureOp(Graph* graphPtr, Tcl_Interp* interp,
int objc, Tcl_Obj* const objv[])
{
Crosshairs* chPtr = graphPtr->crosshairs;
diff --git a/src/bltGrLegd.C b/src/bltGrLegd.C
index 89d6c5a..1bf0f6e 100644
--- a/src/bltGrLegd.C
+++ b/src/bltGrLegd.C
@@ -44,8 +44,6 @@
/*
* Selection related flags:
*
- * SELECT_EXPORT Export the selection to X11.
- *
* SELECT_PENDING A "selection" command idle task is pending.
*
* SELECT_CLEAR Clear selection flag of entry.
@@ -63,135 +61,125 @@
*/
#define SELECT_CLEAR (1<<16)
-#define SELECT_EXPORT (1<<17)
#define SELECT_PENDING (1<<18)
#define SELECT_SET (1<<19)
#define SELECT_TOGGLE (SELECT_SET | SELECT_CLEAR)
#define SELECT_BLTMASK (SELECT_SET | SELECT_CLEAR)
#define SELECT_SORTED (1<<20)
-#define RAISED (1<<21)
-
-#define SELECT_MODE_SINGLE (1<<0)
-#define SELECT_MODE_MULTIPLE (1<<1)
-
-typedef int (GraphLegendProc)(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv);
+typedef enum {SELECT_MODE_SINGLE, SELECT_MODE_MULTIPLE} SelectMode;
-/*
- * Legend --
- *
- * Contains information specific to how the legend will be displayed.
- */
struct _Legend {
- unsigned int flags;
- ClassId classId; /* Type: Element or Marker. */
+ Tk_OptionTable optionTable;
+ unsigned int flags;
+ ClassId classId; /* Type: Element or Marker. */
- int nEntries; /* Number of element entries in
- * table. */
- short int nColumns, nRows; /* Number of columns and rows in
+ int nEntries; /* Number of element entries in
+ * table. */
+ short int nColumns, nRows; /* Number of columns and rows in
* legend */
- short int width, height; /* Dimensions of the legend */
- short int entryWidth, entryHeight;
-
- int site;
- short int xReq, yReq; /* User-requested site of legend, not
- * the final actual position. Used in
- * conjunction with the anchor below
- * to determine location of the
- * legend. */
+ short int width, height; /* Dimensions of the legend */
+ short int entryWidth, entryHeight;
- Tk_Anchor anchor; /* Anchor of legend. Used to interpret
+ int site;
+ short int xReq, yReq; /* User-requested site of legend, not
+ * the final actual position. Used in
+ * conjunction with the anchor below
+ * to determine location of the
+ * legend. */
+
+ Tk_Anchor anchor; /* Anchor of legend. Used to interpret
* the positioning point of the legend
* in the graph*/
- int x, y; /* Computed origin of legend. */
+ int x, y; /* Computed origin of legend. */
- Graph *graphPtr;
- Tcl_Command cmdToken; /* Token for graph's widget command. */
- int reqColumns, reqRows;
+ Graph *graphPtr;
+ Tcl_Command cmdToken; /* Token for graph's widget command. */
+ int reqColumns, reqRows;
- int ixPad, iyPad; /* # of pixels interior padding around
+ int ixPad, iyPad; /* # of pixels interior padding around
* legend entries */
- int xPad, yPad; /* # of pixels padding to exterior of
+ int xPad, yPad; /* # of pixels padding to exterior of
* legend */
- Tk_Window tkwin; /* If non-NULL, external window to draw
+ Tk_Window tkwin; /* If non-NULL, external window to draw
* legend. */
- TextStyle style;
+ TextStyle style;
- int maxSymSize; /* Size of largest symbol to be
+ int maxSymSize; /* Size of largest symbol to be
* displayed. Used to calculate size
* of legend */
- XColor *fgColor;
- Blt_Background activeBg; /* Active legend entry background
+ XColor *fgColor;
+ Blt_Background activeBg; /* Active legend entry background
* color. */
- XColor *activeFgColor;
- int activeRelief; /* 3-D effect on active entry. */
- int entryBW; /* Border width around each entry in
- * legend. */
- Blt_Background normalBg; /* 3-D effect of legend. */
- int borderWidth; /* Width of legend 3-D border */
- int relief; /* 3-d effect of border around the
+ XColor *activeFgColor;
+ int activeRelief; /* 3-D effect on active entry. */
+ int entryBW; /* Border width around each entry in
+ * legend. */
+ Blt_Background normalBg; /* 3-D effect of legend. */
+ int borderWidth; /* Width of legend 3-D border */
+ int relief; /* 3-d effect of border around the
* legend: TK_RELIEF_RAISED etc. */
- Blt_BindTable bindTable;
+ Blt_BindTable bindTable;
- int selRelief;
- int selBW;
+ int selRelief;
+ int selBW;
- XColor *selInFocusFgColor; /* Text color of a selected entry. */
- XColor *selOutFocusFgColor;
+ XColor *selInFocusFgColor; /* Text color of a selected entry. */
+ XColor *selOutFocusFgColor;
- Blt_Background selInFocusBg;
- Blt_Background selOutFocusBg;
+ Blt_Background selInFocusBg;
+ Blt_Background selOutFocusBg;
- XColor *focusColor;
- Blt_Dashes focusDashes; /* Dash on-off value. */
- GC focusGC; /* Graphics context for the active
+ XColor *focusColor;
+ Blt_Dashes focusDashes; /* Dash on-off value. */
+ GC focusGC; /* Graphics context for the active
* label. */
- const char *takeFocus;
- int focus; /* Position of the focus entry. */
+ const char *takeFocus;
+ int focus; /* Position of the focus entry. */
- int cursorX, cursorY; /* Position of the insertion cursor in
- * the textbox window. */
- short int cursorWidth; /* Size of the insertion cursor
+ int cursorX, cursorY; /* Position of the insertion cursor in
+ * the textbox window. */
+ short int cursorWidth; /* Size of the insertion cursor
* symbol. */
- short int cursorHeight;
- Element *focusPtr; /* Element that currently has the
+ short int cursorHeight;
+ Element *focusPtr; /* Element that currently has the
* focus. If NULL, no legend entry has
* the focus. */
- Element *selAnchorPtr; /* Fixed end of selection. Used to
+ Element *selAnchorPtr; /* Fixed end of selection. Used to
* extend the selection while
* maintaining the other end of the
* selection. */
- Element *selMarkPtr;
- Element *selFirstPtr; /* First element selected in current
- * pick. */
- Element *selLastPtr; /* Last element selected in current
- * pick. */
- int exportSelection;
- int active;
- int cursorOn; /* Indicates if the cursor is
- * displayed. */
- int onTime, offTime; /* Time in milliseconds to wait before
- * changing the cursor from off-to-on
- * and on-to-off. Setting offTime to 0
- * makes the * cursor steady. */
- Tcl_TimerToken timerToken; /* Handle for a timer event called
+ Element *selMarkPtr;
+ Element *selFirstPtr; /* First element selected in current
+ * pick. */
+ Element *selLastPtr; /* Last element selected in current
+ * pick. */
+ int hide;
+ int exportSelection;
+ int active;
+ int cursorOn; /* Indicates if the cursor is
+ * displayed. */
+ int onTime, offTime; /* Time in milliseconds to wait before
+ * changing the cursor from off-to-on
+ * and on-to-off. Setting offTime to 0
+ * makes the * cursor steady. */
+ Tcl_TimerToken timerToken; /* Handle for a timer event called
* periodically to blink the cursor. */
- const char *selectCmd; /* TCL script that's invoked whenever
+ const char *selectCmd; /* TCL script that's invoked whenever
* the selection changes. */
- int selectMode; /* Mode of selection: single or
- * multiple. */
- Tcl_HashTable selectTable; /* Table of selected elements. Used to
+ SelectMode selectMode; /* Mode of selection: single or
+ * multiple. */
+ Tcl_HashTable selectTable; /* Table of selected elements. Used to
* quickly determine whether an element
* is selected. */
- Blt_Chain selected; /* List of selected elements. */
+ Blt_Chain selected; /* List of selected elements. */
- const char *title;
- unsigned int titleWidth, titleHeight;
- TextStyle titleStyle; /* Legend title attributes */
+ const char *title;
+ unsigned int titleWidth, titleHeight;
+ TextStyle titleStyle; /* Legend title attributes */
};
#define LABEL_PAD 2
@@ -213,434 +201,58 @@ struct _Legend {
#define DEF_LEGEND_PADX "1"
#define DEF_LEGEND_PADY "1"
#define DEF_LEGEND_POSITION "rightmargin"
-#define DEF_LEGEND_RAISED "no"
#define DEF_LEGEND_RELIEF "flat"
#define DEF_LEGEND_ROWS "0"
#define DEF_LEGEND_SELECTBACKGROUND skyblue4
-#define DEF_LEGEND_SELECT_BG_MONO STD_SELECT_BG_MONO
#define DEF_LEGEND_SELECTBORDERWIDTH "1"
+#define DEF_LEGEND_SELECTCOMMAND (char*)NULL
#define DEF_LEGEND_SELECTMODE "multiple"
-#define DEF_LEGEND_SELECT_FG_MONO STD_SELECT_FG_MONO
#define DEF_LEGEND_SELECTFOREGROUND white
#define DEF_LEGEND_SELECTRELIEF "flat"
#define DEF_LEGEND_FOCUSDASHES "dot"
#define DEF_LEGEND_FOCUSEDIT "no"
#define DEF_LEGEND_FOCUSFOREGROUND STD_ACTIVE_FOREGROUND
-#define DEF_LEGEND_FOCUS_FG_MONO STD_ACTIVE_FG_MONO
#define DEF_LEGEND_TAKEFOCUS "1"
-#define DEF_LEGEND_TITLE (char *)NULL
+#define DEF_LEGEND_TITLE (char*)NULL
#define DEF_LEGEND_TITLECOLOR STD_NORMAL_FOREGROUND
#define DEF_LEGEND_TITLEFONT STD_FONT_SMALL
-static Blt_OptionParseProc ObjToPosition;
-static Blt_OptionPrintProc PositionToObj;
-static Blt_CustomOption legendPositionOption =
-{
- ObjToPosition, PositionToObj, NULL, (ClientData)0
-};
-
-static Blt_OptionParseProc ObjToSelectmode;
-static Blt_OptionPrintProc SelectmodeToObj;
-static Blt_CustomOption selectmodeOption = {
- ObjToSelectmode, SelectmodeToObj, NULL, NULL,
-};
-
-Blt_CustomOption bitmaskGrLegdExportOption =
-{
- ObjToBitmaskProc, BitmaskToObjProc, NULL, (ClientData)SELECT_EXPORT
-};
-
-Blt_CustomOption bitmaskGrLegdHideOption =
-{
- ObjToBitmaskProc, BitmaskToObjProc, NULL, (ClientData)HIDE
-};
-
-Blt_CustomOption bitmaskGrLegdRaisedOption =
-{
- ObjToBitmaskProc, BitmaskToObjProc, NULL, (ClientData)RAISED
-};
-
-static Blt_ConfigSpec configSpecs[] = {
- {BLT_CONFIG_CUSTOM, "-activebackground", "activeBackground",
- "ActiveBackground", DEF_LEGEND_ACTIVEBACKGROUND,
- Tk_Offset(Legend, activeBg), 0,
- &backgroundOption},
- {BLT_CONFIG_PIXELS, "-activeborderwidth", "activeBorderWidth",
- "BorderWidth", DEF_LEGEND_BORDERWIDTH,
- Tk_Offset(Legend, entryBW), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground",
- "ActiveForeground", DEF_LEGEND_ACTIVEFOREGROUND,
- Tk_Offset(Legend, activeFgColor), 0},
- {BLT_CONFIG_RELIEF, "-activerelief", "activeRelief", "Relief",
- DEF_LEGEND_ACTIVERELIEF, Tk_Offset(Legend, activeRelief),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", DEF_LEGEND_ANCHOR,
- Tk_Offset(Legend, anchor), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
- {BLT_CONFIG_CUSTOM, "-background", "background", "Background",
- DEF_LEGEND_BACKGROUND, Tk_Offset(Legend, normalBg),BLT_CONFIG_NULL_OK,
- &backgroundOption},
- {BLT_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_LEGEND_BORDERWIDTH, Tk_Offset(Legend, borderWidth),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0,0},
- {BLT_CONFIG_INT, "-columns", "columns", "columns",
- DEF_LEGEND_COLUMNS, Tk_Offset(Legend, reqColumns),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-exportselection", "exportSelection",
- "ExportSelection", DEF_LEGEND_EXPORTSELECTION,
- Tk_Offset(Legend, flags), BLT_CONFIG_DONT_SET_DEFAULT,
- &bitmaskGrLegdExportOption},
- {BLT_CONFIG_CUSTOM, "-focusdashes", "focusDashes", "FocusDashes",
- DEF_LEGEND_FOCUSDASHES, Tk_Offset(Legend, focusDashes),
- BLT_CONFIG_NULL_OK, &dashesOption},
- {BLT_CONFIG_COLOR, "-focusforeground", "focusForeground", "FocusForeground",
- DEF_LEGEND_FOCUSFOREGROUND, Tk_Offset(Legend, focusColor),
- BLT_CONFIG_COLOR_ONLY},
- {BLT_CONFIG_COLOR, "-focusforeground", "focusForeground", "FocusForeground",
- DEF_LEGEND_FOCUS_FG_MONO, Tk_Offset(Legend, focusColor),
- BLT_CONFIG_MONO_ONLY},
- {BLT_CONFIG_FONT, "-font", "font", "Font", DEF_LEGEND_FONT,
- Tk_Offset(Legend, style.font), 0},
- {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
- {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_LEGEND_FOREGROUND, Tk_Offset(Legend, fgColor), 0},
- {BLT_CONFIG_CUSTOM, "-hide", "hide", "Hide", DEF_LEGEND_HIDE,
- Tk_Offset(Legend, flags), BLT_CONFIG_DONT_SET_DEFAULT,
- &bitmaskGrLegdHideOption},
- {BLT_CONFIG_PIXELS, "-ipadx", "iPadX", "Pad", DEF_LEGEND_IPADX,
- Tk_Offset(Legend, ixPad), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-ipady", "iPadY", "Pad", DEF_LEGEND_IPADY,
- Tk_Offset(Legend, iyPad), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-nofocusselectbackground",
- "noFocusSelectBackground", "NoFocusSelectBackground",
- DEF_LEGEND_SELECTBACKGROUND, Tk_Offset(Legend, selOutFocusBg), 0,
- &backgroundOption},
- {BLT_CONFIG_COLOR, "-nofocusselectforeground", "noFocusSelectForeground",
- "NoFocusSelectForeground", DEF_LEGEND_SELECTFOREGROUND,
- Tk_Offset(Legend, selOutFocusFgColor), 0},
- {BLT_CONFIG_PIXELS, "-padx", "padX", "Pad", DEF_LEGEND_PADX,
- Tk_Offset(Legend, xPad), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-pady", "padY", "Pad", DEF_LEGEND_PADY,
- Tk_Offset(Legend, yPad), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-position", "position", "Position",
- DEF_LEGEND_POSITION, 0, BLT_CONFIG_DONT_SET_DEFAULT,
- &legendPositionOption},
- {BLT_CONFIG_CUSTOM, "-raised", "raised", "Raised", DEF_LEGEND_RAISED,
- Tk_Offset(Legend, flags), BLT_CONFIG_DONT_SET_DEFAULT,
- &bitmaskGrLegdRaisedOption},
- {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_LEGEND_RELIEF,
- Tk_Offset(Legend, relief), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_INT, "-rows", "rows", "rows", DEF_LEGEND_ROWS,
- Tk_Offset(Legend, reqRows),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-selectbackground", "selectBackground",
- "Background", DEF_LEGEND_SELECTBACKGROUND,
- Tk_Offset(Legend, selInFocusBg), 0,
- &backgroundOption},
- {BLT_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth",
- "BorderWidth", DEF_LEGEND_SELECTBORDERWIDTH,
- Tk_Offset(Legend, selBW), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_STRING, "-selectcommand", "selectCommand", "SelectCommand",
- (char *)NULL, Tk_Offset(Legend, selectCmd), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_COLOR, "-selectforeground", "selectForeground", "Foreground",
- DEF_LEGEND_SELECT_FG_MONO, Tk_Offset(Legend, selInFocusFgColor),
- BLT_CONFIG_MONO_ONLY},
- {BLT_CONFIG_COLOR, "-selectforeground", "selectForeground", "Foreground",
- DEF_LEGEND_SELECTFOREGROUND, Tk_Offset(Legend, selInFocusFgColor),
- BLT_CONFIG_COLOR_ONLY},
- {BLT_CONFIG_CUSTOM, "-selectmode", "selectMode", "SelectMode",
- DEF_LEGEND_SELECTMODE, Tk_Offset(Legend, selectMode),
- BLT_CONFIG_DONT_SET_DEFAULT, &selectmodeOption},
- {BLT_CONFIG_RELIEF, "-selectrelief", "selectRelief", "Relief",
- DEF_LEGEND_SELECTRELIEF, Tk_Offset(Legend, selRelief),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_LEGEND_TAKEFOCUS, Tk_Offset(Legend, takeFocus),
- BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_STRING, "-title", "title", "Title", DEF_LEGEND_TITLE,
- Tk_Offset(Legend, title), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_COLOR, "-titlecolor", "titleColor", "Foreground",
- DEF_LEGEND_TITLECOLOR, Tk_Offset(Legend, titleStyle.color), 0},
- {BLT_CONFIG_FONT, "-titlefont", "titleFont", "Font",
- DEF_LEGEND_TITLEFONT, Tk_Offset(Legend, titleStyle.font), 0},
- {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
-};
-
-static Tcl_IdleProc DisplayLegend;
-static Blt_BindPickProc PickEntryProc;
-static Tk_EventProc LegendEventProc;
-static Tcl_TimerProc BlinkCursorProc;
-static Tk_LostSelProc LostSelectionProc;
-static Tk_SelectionProc SelectionProc;
-
-extern Tcl_ObjCmdProc Blt_GraphInstCmdProc;
-
-/*
- *---------------------------------------------------------------------------
- *
- * Blt_Legend_EventuallyRedraw --
- *
- * Tells the Tk dispatcher to call the graph display routine at the next
- * idle point. This request is made only if the window is displayed and
- * no other redraw request is pending.
- *
- * Results: None.
- *
- * Side effects:
- * The window is eventually redisplayed.
- *
- *---------------------------------------------------------------------------
- */
-void
-Blt_Legend_EventuallyRedraw(Graph *graphPtr)
-{
- Legend *legendPtr = graphPtr->legend;
-
- if ((legendPtr->tkwin != NULL) && !(legendPtr->flags & REDRAW_PENDING)) {
- Tcl_DoWhenIdle(DisplayLegend, legendPtr);
- legendPtr->flags |= REDRAW_PENDING;
- }
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * SelectCmdProc --
- *
- * Invoked at the next idle point whenever the current selection changes.
- * Executes some application-specific code in the -selectcommand option.
- * This provides a way for applications to handle selection changes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * TCL code gets executed for some application-specific task.
- *
- *---------------------------------------------------------------------------
- */
-static void
-SelectCmdProc(ClientData clientData)
-{
- Legend *legendPtr = clientData;
-
- Tcl_Preserve(legendPtr);
- legendPtr->flags &= ~SELECT_PENDING;
- if (legendPtr->selectCmd != NULL) {
- Tcl_Interp *interp;
-
- interp = legendPtr->graphPtr->interp;
- if (Tcl_GlobalEval(interp, legendPtr->selectCmd) != TCL_OK) {
- Tcl_BackgroundError(interp);
- }
- }
- Tcl_Release(legendPtr);
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * EventuallyInvokeSelectCmd --
- *
- * Queues a request to execute the -selectcommand code associated with
- * the widget at the next idle point. Invoked whenever the selection
- * changes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * TCL code gets executed for some application-specific task.
- *
- *---------------------------------------------------------------------------
- */
-static void
-EventuallyInvokeSelectCmd(Legend *legendPtr)
-{
- if ((legendPtr->flags & SELECT_PENDING) == 0) {
- legendPtr->flags |= SELECT_PENDING;
- Tcl_DoWhenIdle(SelectCmdProc, legendPtr);
- }
-}
-
-static void
-ClearSelection(Legend *legendPtr)
-{
- Tcl_DeleteHashTable(&legendPtr->selectTable);
- Tcl_InitHashTable(&legendPtr->selectTable, TCL_ONE_WORD_KEYS);
- Blt_Chain_Reset(legendPtr->selected);
- Blt_Legend_EventuallyRedraw(legendPtr->graphPtr);
- if (legendPtr->selectCmd != NULL) {
- EventuallyInvokeSelectCmd(legendPtr);
- }
-}
-
-
-/*
- *---------------------------------------------------------------------------
- *
- * LostSelectionProc --
- *
- * This procedure is called back by Tk when the selection is grabbed away
- * from a Text widget.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The existing selection is unhighlighted, and the window is marked as
- * not containing a selection.
- *
- *---------------------------------------------------------------------------
- */
-static void
-LostSelectionProc(ClientData clientData)
-{
- Legend *legendPtr = clientData;
-
- if (legendPtr->flags & SELECT_EXPORT) {
- ClearSelection(legendPtr);
- }
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * LegendEventProc --
- *
- * This procedure is invoked by the Tk dispatcher for various events on
- * graphs.
- *
- * Results:
- * None.
- *
- * Side effects:
- * When the window gets deleted, internal structures get cleaned up.
- * When it gets exposed, the graph is eventually redisplayed.
- *
- *---------------------------------------------------------------------------
- */
-static void
-LegendEventProc(ClientData clientData, XEvent *eventPtr)
-{
- Graph *graphPtr = clientData;
- Legend *legendPtr;
-
- legendPtr = graphPtr->legend;
- if (eventPtr->type == Expose) {
- if (eventPtr->xexpose.count == 0) {
- Blt_Legend_EventuallyRedraw(graphPtr);
- }
- } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
- if (eventPtr->xfocus.detail == NotifyInferior) {
- return;
- }
- if (eventPtr->type == FocusIn) {
- legendPtr->flags |= FOCUS;
- } else {
- legendPtr->flags &= ~FOCUS;
- }
- Tcl_DeleteTimerHandler(legendPtr->timerToken);
- if ((legendPtr->active) && (legendPtr->flags & FOCUS)) {
- legendPtr->cursorOn = TRUE;
- if (legendPtr->offTime != 0) {
- legendPtr->timerToken = Tcl_CreateTimerHandler(
- legendPtr->onTime, BlinkCursorProc, graphPtr);
- }
- } else {
- legendPtr->cursorOn = FALSE;
- legendPtr->timerToken = (Tcl_TimerToken)NULL;
- }
- Blt_Legend_EventuallyRedraw(graphPtr);
- } else if (eventPtr->type == DestroyNotify) {
- Graph *graphPtr = legendPtr->graphPtr;
-
- if (legendPtr->site == LEGEND_WINDOW) {
- if (legendPtr->cmdToken != NULL) {
- Tcl_DeleteCommandFromToken(graphPtr->interp,
- legendPtr->cmdToken);
- legendPtr->cmdToken = NULL;
- }
- legendPtr->tkwin = graphPtr->tkwin;
- }
- if (legendPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(DisplayLegend, legendPtr);
- legendPtr->flags &= ~REDRAW_PENDING;
- }
- legendPtr->site = LEGEND_RIGHT;
- legendPtr->flags |= HIDE;
- graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
- Blt_MoveBindingTable(legendPtr->bindTable, graphPtr->tkwin);
- Blt_EventuallyRedrawGraph(graphPtr);
- } else if (eventPtr->type == ConfigureNotify) {
- Blt_Legend_EventuallyRedraw(graphPtr);
- }
-}
-
-static int
-CreateLegendWindow(Tcl_Interp *interp, Legend *legendPtr, const char *pathName)
+static int LegendObjConfigure(Tcl_Interp *interp, Graph* graphPtr,
+ int objc, Tcl_Obj* const objv[]);
+static void ConfigureLegend(Graph *graphPtr);
+static int EntryIsSelected(Legend *legendPtr, Element *elemPtr);
+static int GetElementFromObj(Graph *graphPtr, Tcl_Obj *objPtr,
+ Element **elemPtrPtr);
+static void ClearSelection(Legend *legendPtr);
+static void DeselectElement(Legend *legendPtr, Element *elemPtr);
+static int SelectRange(Legend *legendPtr, Element *fromPtr, Element *toPtr);
+static void EventuallyInvokeSelectCmd(Legend *legendPtr);
+static void SelectEntry(Legend *legendPtr, Element *elemPtr);
+static int CreateLegendWindow(Tcl_Interp *interp, Legend *legendPtr,
+ const char *pathName);
+
+// SelectMode
+
+static char* selectmodeObjOption[] =
+ {"single", "multiple", NULL};
+
+// Position
+
+static Tk_CustomOptionSetProc PositionSetProc;
+static Tk_CustomOptionGetProc PositionGetProc;
+Tk_ObjCustomOption positionObjOption =
+ {
+ "position", PositionSetProc, PositionGetProc, NULL, NULL, NULL
+ };
+
+static int PositionSetProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj** objPtr, char* widgRec,
+ int offset, char* save, int flags)
{
- Graph *graphPtr;
- Tk_Window tkwin;
-
- graphPtr = legendPtr->graphPtr;
- tkwin = Tk_CreateWindowFromPath(interp, graphPtr->tkwin, pathName, NULL);
- if (tkwin == NULL) {
- return TCL_ERROR;
- }
-
- ((TkWindow*)tkwin)->instanceData = legendPtr;
- Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask,
- LegendEventProc, graphPtr);
- /* Move the legend's binding table to the new window. */
- Blt_MoveBindingTable(legendPtr->bindTable, tkwin);
- if (legendPtr->tkwin != graphPtr->tkwin) {
- Tk_DestroyWindow(legendPtr->tkwin);
- }
- /* Create a command by the same name as the legend window so that Legend
- * bindings can use %W interchangably. */
- legendPtr->cmdToken = Tcl_CreateObjCommand(interp, pathName,
- Blt_GraphInstCmdProc, graphPtr, NULL);
- legendPtr->tkwin = tkwin;
- legendPtr->site = LEGEND_WINDOW;
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * ObjToPosition --
- *
- * Convert the string representation of a legend XY position into window
- * coordinates. The form of the string must be "@x,y" or none.
- *
- * Results:
- * The return value is a standard TCL result. The symbol type is written
- * into the widget record.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-ObjToPosition(
- ClientData clientData, /* Not used. */
- Tcl_Interp *interp, /* Interpreter to send results back
- * to */
- Tk_Window tkwin, /* Not used. */
- Tcl_Obj *objPtr, /* New legend position string */
- char *widgRec, /* Widget record */
- int offset, /* Not used. */
- int flags) /* Not used. */
-{
- Graph *graphPtr;
- Legend *legendPtr = (Legend *)widgRec;
- char c;
+ Legend* legendPtr = (Legend*)widgRec;
int length;
- const char *string;
-
- graphPtr = legendPtr->graphPtr;
- string = Tcl_GetStringFromObj(objPtr, &length);
+ const char* string = Tcl_GetStringFromObj(*objPtr, &length);
+ char c;
c = string[0];
if (c == '\0') {
legendPtr->site = LEGEND_RIGHT;
@@ -680,2036 +292,2008 @@ ObjToPosition(
if (CreateLegendWindow(interp, legendPtr, string) != TCL_OK) {
return TCL_ERROR;
}
- Blt_Legend_EventuallyRedraw(graphPtr);
} else {
Tcl_AppendResult(interp, "bad position \"", string, "\": should be \
\"leftmargin\", \"rightmargin\", \"topmargin\", \"bottommargin\", \
\"plotarea\", windowName or @x,y", (char *)NULL);
return TCL_ERROR;
}
- graphPtr->flags |= RESET_WORLD;
- Blt_EventuallyRedrawGraph(graphPtr);
return TCL_OK;
}
-/*
- *---------------------------------------------------------------------------
- *
- * PositionToObj --
- *
- * Convert the window coordinates into a string.
- *
- * Results:
- * The string representing the coordinate position is returned.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static Tcl_Obj *
-PositionToObj(
- ClientData clientData, /* Not used. */
- Tcl_Interp *interp, /* Not used. */
- Tk_Window tkwin, /* Not used. */
- char *widgRec, /* Widget record */
- int offset, /* Not used. */
- int flags) /* Not used. */
+static Tcl_Obj* PositionGetProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset)
{
- Legend *legendPtr = (Legend *)widgRec;
- Tcl_Obj *objPtr;
-
- switch (legendPtr->site) {
- case LEGEND_LEFT:
- objPtr = Tcl_NewStringObj("leftmargin", -1);
- break;
-
- case LEGEND_RIGHT:
- objPtr = Tcl_NewStringObj("rightmargin", -1);
- break;
-
- case LEGEND_TOP:
- objPtr = Tcl_NewStringObj("topmargin", -1);
- break;
-
- case LEGEND_BOTTOM:
- objPtr = Tcl_NewStringObj("bottommargin", -1);
- break;
+ Legend *legendPtr = (Legend *)widgRec;
+ Tcl_Obj *objPtr;
+
+ switch (legendPtr->site) {
+ case LEGEND_LEFT:
+ objPtr = Tcl_NewStringObj("leftmargin", -1);
+ break;
+ case LEGEND_RIGHT:
+ objPtr = Tcl_NewStringObj("rightmargin", -1);
+ break;
+ case LEGEND_TOP:
+ objPtr = Tcl_NewStringObj("topmargin", -1);
+ break;
+ case LEGEND_BOTTOM:
+ objPtr = Tcl_NewStringObj("bottommargin", -1);
+ break;
+ case LEGEND_PLOT:
+ objPtr = Tcl_NewStringObj("plotarea", -1);
+ break;
+ case LEGEND_WINDOW:
+ objPtr = Tcl_NewStringObj(Tk_PathName(legendPtr->tkwin), -1);
+ break;
+ case LEGEND_XY:
+ {
+ char string[200];
- case LEGEND_PLOT:
- objPtr = Tcl_NewStringObj("plotarea", -1);
- break;
+ sprintf_s(string, 200, "@%d,%d", legendPtr->xReq, legendPtr->yReq);
+ objPtr = Tcl_NewStringObj(string, -1);
+ }
+ default:
+ objPtr = Tcl_NewStringObj("unknown legend position", -1);
+ }
+ return objPtr;
+}
- case LEGEND_WINDOW:
- objPtr = Tcl_NewStringObj(Tk_PathName(legendPtr->tkwin), -1);
- break;
+static Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_CUSTOM, "-activebackground", "activeBackground",
+ "ActiveBackground",
+ DEF_LEGEND_ACTIVEBACKGROUND,
+ -1, Tk_Offset(Legend, activeBg), 0, &backgroundObjOption, 0},
+ {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
+ "ActiveBorderWidth",
+ DEF_LEGEND_BORDERWIDTH,
+ -1, Tk_Offset(Legend, entryBW), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "ActiveForeground",
+ DEF_LEGEND_ACTIVEFOREGROUND,
+ -1, Tk_Offset(Legend, activeFgColor), 0, NULL, 0},
+ {TK_OPTION_RELIEF, "-activerelief", "activeRelief", "ActiveRelief",
+ DEF_LEGEND_ACTIVERELIEF,
+ -1, Tk_Offset(Legend, activeRelief), 0, NULL, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_LEGEND_ANCHOR,
+ -1, Tk_Offset(Legend, anchor), 0, NULL, 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL,
+ -1, 0, 0, "-background", 0},
+ {TK_OPTION_CUSTOM, "-background", "background", "Background",
+ DEF_LEGEND_BACKGROUND,
+ -1, Tk_Offset(Legend, normalBg), TK_OPTION_NULL_OK, &backgroundObjOption, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_LEGEND_BORDERWIDTH,
+ -1, Tk_Offset(Legend, borderWidth), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL,
+ -1, 0, 0, "-borderwidth", 0},
+ {TK_OPTION_INT, "-columns", "columns", "columns",
+ DEF_LEGEND_COLUMNS,
+ -1, Tk_Offset(Legend, reqColumns), 0, NULL, 0},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection",
+ DEF_LEGEND_EXPORTSELECTION,
+ -1, Tk_Offset(Legend, exportSelection), 0, NULL, 0},
+ {TK_OPTION_CUSTOM, "-focusdashes", "focusDashes", "FocusDashes",
+ DEF_LEGEND_FOCUSDASHES,
+ -1, Tk_Offset(Legend, focusDashes), TK_OPTION_NULL_OK, &dashesObjOption, 0},
+ {TK_OPTION_COLOR, "-focusforeground", "focusForeground", "FocusForeground",
+ DEF_LEGEND_FOCUSFOREGROUND,
+ -1, Tk_Offset(Legend, focusColor), 0, NULL, 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_LEGEND_FONT,
+ -1, Tk_Offset(Legend, style.font), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL,
+ -1, 0, 0, "-foreground", 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_LEGEND_FOREGROUND,
+ -1, Tk_Offset(Legend, fgColor), 0, NULL, 0},
+ {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide",
+ DEF_LEGEND_HIDE,
+ -1, Tk_Offset(Legend, hide), 0, NULL, 0},
+ {TK_OPTION_PIXELS, "-ipadx", "iPadX", "Pad",
+ DEF_LEGEND_IPADX,
+ -1, Tk_Offset(Legend, ixPad), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_PIXELS, "-ipady", "iPadY", "Pad",
+ DEF_LEGEND_IPADY,
+ -1, Tk_Offset(Legend, iyPad), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_CUSTOM, "-nofocusselectbackground", "noFocusSelectBackground",
+ "NoFocusSelectBackground",
+ DEF_LEGEND_SELECTBACKGROUND,
+ -1, Tk_Offset(Legend, selOutFocusBg), 0, &backgroundObjOption, 0},
+ {TK_OPTION_COLOR, "-nofocusselectforeground", "noFocusSelectForeground",
+ "NoFocusSelectForeground",
+ DEF_LEGEND_SELECTFOREGROUND,
+ -1, Tk_Offset(Legend, selOutFocusFgColor), 0, NULL, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_LEGEND_PADX,
+ -1, Tk_Offset(Legend, xPad), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_LEGEND_PADY,
+ -1, Tk_Offset(Legend, yPad), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_CUSTOM, "-position", "position", "Position",
+ DEF_LEGEND_POSITION,
+ -1, 0, 0, &positionObjOption, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LEGEND_RELIEF,
+ -1, Tk_Offset(Legend, relief), 0, NULL, 0},
+ {TK_OPTION_INT, "-rows", "rows", "rows",
+ DEF_LEGEND_ROWS,
+ -1, Tk_Offset(Legend, reqRows), 0, NULL,
+ RESET_WORLD | CACHE_DIRTY},
+ {TK_OPTION_CUSTOM, "-selectbackground", "selectBackground",
+ "SelectBackground",
+ DEF_LEGEND_SELECTBACKGROUND,
+ -1, Tk_Offset(Legend, selInFocusBg), 0, &backgroundObjOption, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "SelectBorderWidth",
+ DEF_LEGEND_SELECTBORDERWIDTH,
+ -1, Tk_Offset(Legend, selBW), 0, NULL, 0},
+ {TK_OPTION_STRING, "-selectcommand", "selectCommand", "SelectCommand",
+ DEF_LEGEND_SELECTCOMMAND,
+ -1, Tk_Offset(Legend, selectCmd), TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "SelectForeground",
+ DEF_LEGEND_SELECTFOREGROUND,
+ -1, Tk_Offset(Legend, selInFocusFgColor), 0, NULL, 0},
+ {TK_OPTION_STRING_TABLE, "-selectmode", "selectMode", "SelectMode",
+ DEF_LEGEND_SELECTMODE,
+ -1, Tk_Offset(Legend, selectMode), 0, &selectmodeObjOption, 0},
+ {TK_OPTION_RELIEF, "-selectrelief", "selectRelief", "SelectRelief",
+ DEF_LEGEND_SELECTRELIEF,
+ -1, Tk_Offset(Legend, selRelief), 0, NULL, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_LEGEND_TAKEFOCUS,
+ -1, Tk_Offset(Legend, takeFocus), TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-title", "title", "Title",
+ DEF_LEGEND_TITLE,
+ -1, Tk_Offset(Legend, title), TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_COLOR, "-titlecolor", "titleColor", "TitleColor",
+ DEF_LEGEND_TITLECOLOR,
+ -1, Tk_Offset(Legend, titleStyle.color), 0, NULL, 0},
+ {TK_OPTION_FONT, "-titlefont", "titleFont", "TitleFont",
+ DEF_LEGEND_TITLEFONT,
+ -1, Tk_Offset(Legend, titleStyle.font), 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0}
+};
- case LEGEND_XY:
- {
- char string[200];
+static Tcl_IdleProc DisplayLegend;
+static Blt_BindPickProc PickEntryProc;
+static Tk_EventProc LegendEventProc;
+static Tcl_TimerProc BlinkCursorProc;
+static Tk_LostSelProc LostSelectionProc;
+static Tk_SelectionProc SelectionProc;
- sprintf_s(string, 200, "@%d,%d", legendPtr->xReq, legendPtr->yReq);
- objPtr = Tcl_NewStringObj(string, -1);
- }
- default:
- objPtr = Tcl_NewStringObj("unknown legend position", -1);
- }
- return objPtr;
-}
+extern Tcl_ObjCmdProc Blt_GraphInstCmdProc;
-/*
- *---------------------------------------------------------------------------
- *
- * ObjToSelectmode --
- *
- * Convert the string reprsenting a select mode, to its numeric form.
- *
- * 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
-ObjToSelectmode(
- 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, /* Offset to field in structure */
- int flags)
+int Blt_CreateLegend(Graph* graphPtr)
{
- char *string;
- char c;
- int *modePtr = (int *)(widgRec + offset);
+ Legend *legendPtr = calloc(1, sizeof(Legend));
+ graphPtr->legend = legendPtr;
+ legendPtr->optionTable =Tk_CreateOptionTable(graphPtr->interp, optionSpecs);
+ legendPtr->graphPtr = graphPtr;
+ legendPtr->tkwin = graphPtr->tkwin;
+ legendPtr->xReq = legendPtr->yReq = -SHRT_MAX;
+ legendPtr->relief = TK_RELIEF_SUNKEN;
+ legendPtr->activeRelief = TK_RELIEF_FLAT;
+ legendPtr->entryBW = 2;
+ legendPtr->borderWidth = 2;
+ legendPtr->ixPad = 1;
+ legendPtr->iyPad = 1;
+ legendPtr->xPad = 1;
+ legendPtr->yPad = 1;
+ legendPtr->anchor = TK_ANCHOR_N;
+ legendPtr->site = LEGEND_RIGHT;
+ legendPtr->selectMode = SELECT_MODE_MULTIPLE;
+ Blt_Ts_InitStyle(legendPtr->style);
+ Blt_Ts_InitStyle(legendPtr->titleStyle);
+ legendPtr->style.justify = TK_JUSTIFY_LEFT;
+ legendPtr->style.anchor = TK_ANCHOR_NW;
+ legendPtr->titleStyle.justify = TK_JUSTIFY_LEFT;
+ legendPtr->titleStyle.anchor = TK_ANCHOR_NW;
+ legendPtr->bindTable = Blt_CreateBindingTable(graphPtr->interp,
+ graphPtr->tkwin, graphPtr, PickEntryProc, Blt_GraphTags);
+
+ Tcl_InitHashTable(&legendPtr->selectTable, TCL_ONE_WORD_KEYS);
+ legendPtr->selected = Blt_Chain_Create();
+ Tk_CreateSelHandler(legendPtr->tkwin, XA_PRIMARY, XA_STRING,
+ SelectionProc, legendPtr, XA_STRING);
+ legendPtr->selRelief = TK_RELIEF_FLAT;
+ legendPtr->selBW = 1;
+ legendPtr->onTime = 600;
+ legendPtr->offTime = 300;
- string = Tcl_GetString(objPtr);
- c = string[0];
- if ((c == 's') && (strcmp(string, "single") == 0)) {
- *modePtr = SELECT_MODE_SINGLE;
- } else if ((c == 'm') && (strcmp(string, "multiple") == 0)) {
- *modePtr = SELECT_MODE_MULTIPLE;
- } else if ((c == 'a') && (strcmp(string, "active") == 0)) {
- *modePtr = SELECT_MODE_SINGLE;
- } else {
- Tcl_AppendResult(interp, "bad select mode \"", string,
- "\": should be \"single\" or \"multiple\"", (char *)NULL);
- return TCL_ERROR;
- }
return TCL_OK;
}
-/*
- *---------------------------------------------------------------------------
- *
- * SelectmodeToObj --
- *
- * Results:
- * The string representation of the select mode is returned.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static Tcl_Obj *
-SelectmodeToObj(
- ClientData clientData, /* Not used. */
- Tcl_Interp *interp,
- Tk_Window tkwin, /* Not used. */
- char *widgRec,
- int offset, /* Offset to field in structure */
- int flags)
+int Blt_ConfigureObjLegend(Graph* graphPtr, int objc, Tcl_Obj* const objv[])
{
- int mode = *(int *)(widgRec + offset);
-
- switch (mode) {
- case SELECT_MODE_SINGLE:
- return Tcl_NewStringObj("single", -1);
- case SELECT_MODE_MULTIPLE:
- return Tcl_NewStringObj("multiple", -1);
- default:
- return Tcl_NewStringObj("unknown scroll mode", -1);
- }
+ Legend* legendPtr = graphPtr->legend;
+ return Tk_InitOptions(graphPtr->interp, (char*)legendPtr,
+ legendPtr->optionTable, graphPtr->tkwin);
}
+static Blt_OpSpec legendOps[];
+static int nLegendOps;
+typedef int (GraphLegendProc)(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[]);
-static void
-SetLegendOrigin(Legend *legendPtr)
+int Blt_LegendOp(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[])
{
- Graph *graphPtr;
- int x, y, w, h;
-
- graphPtr = legendPtr->graphPtr;
- x = y = w = h = 0; /* Suppress compiler warning. */
- switch (legendPtr->site) {
- case LEGEND_RIGHT:
- w = graphPtr->rightMargin.width - graphPtr->rightMargin.axesOffset;
- h = graphPtr->bottom - graphPtr->top;
- x = graphPtr->right + graphPtr->rightMargin.axesOffset;
- y = graphPtr->top;
- break;
-
- case LEGEND_LEFT:
- w = graphPtr->leftMargin.width - graphPtr->leftMargin.axesOffset;
- h = graphPtr->bottom - graphPtr->top;
- x = graphPtr->inset;
- y = graphPtr->top;
- break;
-
- case LEGEND_TOP:
- w = graphPtr->right - graphPtr->left;
- h = graphPtr->topMargin.height - graphPtr->topMargin.axesOffset;
- if (graphPtr->title != NULL) {
- h -= graphPtr->titleHeight;
- }
- x = graphPtr->left;
- y = graphPtr->inset;
- if (graphPtr->title != NULL) {
- y += graphPtr->titleHeight;
- }
- break;
-
- case LEGEND_BOTTOM:
- w = graphPtr->right - graphPtr->left;
- h = graphPtr->bottomMargin.height - graphPtr->bottomMargin.axesOffset;
- x = graphPtr->left;
- y = graphPtr->bottom + graphPtr->bottomMargin.axesOffset;
- break;
-
- case LEGEND_PLOT:
- w = graphPtr->right - graphPtr->left;
- h = graphPtr->bottom - graphPtr->top;
- x = graphPtr->left;
- y = graphPtr->top;
- break;
-
- case LEGEND_XY:
- w = legendPtr->width;
- h = legendPtr->height;
- x = legendPtr->xReq;
- y = legendPtr->yReq;
- if (x < 0) {
- x += graphPtr->width;
- }
- if (y < 0) {
- y += graphPtr->height;
- }
- break;
-
- case LEGEND_WINDOW:
- legendPtr->anchor = TK_ANCHOR_NW;
- legendPtr->x = legendPtr->y = 0;
- return;
- }
+ GraphLegendProc *proc = Blt_GetOpFromObj(interp, nLegendOps, legendOps,
+ BLT_OP_ARG2, objc, objv,0);
+ if (proc == NULL)
+ return TCL_ERROR;
- switch (legendPtr->anchor) {
- case TK_ANCHOR_NW: /* Upper left corner */
- break;
- case TK_ANCHOR_W: /* Left center */
- if (h > legendPtr->height) {
- y += (h - legendPtr->height) / 2;
- }
- break;
- case TK_ANCHOR_SW: /* Lower left corner */
- if (h > legendPtr->height) {
- y += (h - legendPtr->height);
- }
- break;
- case TK_ANCHOR_N: /* Top center */
- if (w > legendPtr->width) {
- x += (w - legendPtr->width) / 2;
- }
- break;
- case TK_ANCHOR_CENTER: /* Center */
- if (h > legendPtr->height) {
- y += (h - legendPtr->height) / 2;
- }
- if (w > legendPtr->width) {
- x += (w - legendPtr->width) / 2;
- }
- break;
- case TK_ANCHOR_S: /* Bottom center */
- if (w > legendPtr->width) {
- x += (w - legendPtr->width) / 2;
- }
- if (h > legendPtr->height) {
- y += (h - legendPtr->height);
- }
- break;
- case TK_ANCHOR_NE: /* Upper right corner */
- if (w > legendPtr->width) {
- x += w - legendPtr->width;
- }
- break;
- case TK_ANCHOR_E: /* Right center */
- if (w > legendPtr->width) {
- x += w - legendPtr->width;
- }
- if (h > legendPtr->height) {
- y += (h - legendPtr->height) / 2;
- }
- break;
- case TK_ANCHOR_SE: /* Lower right corner */
- if (w > legendPtr->width) {
- x += w - legendPtr->width;
- }
- if (h > legendPtr->height) {
- y += (h - legendPtr->height);
- }
- break;
- }
- legendPtr->x = x + legendPtr->xPad;
- legendPtr->y = y + legendPtr->yPad;
+ return (*proc) (graphPtr, interp, objc, objv);
}
-static int
-EntryIsSelected(Legend *legendPtr, Element *elemPtr)
+static int CgetOp(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[])
{
- Tcl_HashEntry *hPtr;
-
- hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
- return (hPtr != NULL);
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "cget option");
+ return TCL_ERROR;
+ }
+
+ Legend* legendPtr = graphPtr->legend;
+ Tcl_Obj* objPtr = Tk_GetOptionValue(interp, (char*)legendPtr,
+ legendPtr->optionTable,
+ objv[3], graphPtr->tkwin);
+ if (objPtr == NULL)
+ return TCL_ERROR;
+ else
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
}
-static void
-SelectElement(Legend *legendPtr, Element *elemPtr)
+static int ConfigureOp(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[])
{
- int isNew;
- Tcl_HashEntry *hPtr;
-
- hPtr = Tcl_CreateHashEntry(&legendPtr->selectTable, (char *)elemPtr,&isNew);
- if (isNew) {
- Blt_ChainLink link;
-
- link = Blt_Chain_Append(legendPtr->selected, elemPtr);
- Tcl_SetHashValue(hPtr, link);
- }
+ Legend* legendPtr = graphPtr->legend;
+ if (objc <= 4) {
+ Tcl_Obj* objPtr = Tk_GetOptionInfo(graphPtr->interp, (char*)legendPtr,
+ legendPtr->optionTable,
+ (objc == 4) ? objv[3] : NULL,
+ graphPtr->tkwin);
+ if (objPtr == NULL)
+ return TCL_ERROR;
+ else
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ else
+ return LegendObjConfigure(interp, graphPtr, objc-3, objv+3);
}
-static void
-DeselectElement(Legend *legendPtr, Element *elemPtr)
+static int LegendObjConfigure(Tcl_Interp *interp, Graph* graphPtr,
+ int objc, Tcl_Obj* const objv[])
{
- Tcl_HashEntry *hPtr;
-
- hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
- if (hPtr != NULL) {
- Blt_ChainLink link;
+ Legend* legendPtr = graphPtr->legend;
+ Tk_SavedOptions savedOptions;
+ int mask =0;
+ int error;
+ Tcl_Obj* errorResult;
+
+ for (error=0; error<=1; error++) {
+ if (!error) {
+ if (Tk_SetOptions(interp, (char*)legendPtr, legendPtr->optionTable,
+ objc, objv, graphPtr->tkwin, &savedOptions, &mask)
+ != TCL_OK)
+ continue;
+ }
+ else {
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ ConfigureLegend(graphPtr);
+ graphPtr->flags |= mask;
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ break;
+ }
- link = Tcl_GetHashValue(hPtr);
- Blt_Chain_DeleteLink(legendPtr->selected, link);
- Tcl_DeleteHashEntry(hPtr);
- }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ return TCL_OK;
+ }
+ else {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ }
}
-static void
-SelectEntry(Legend *legendPtr, Element *elemPtr)
+static void ConfigureLegend(Graph *graphPtr)
{
- Tcl_HashEntry *hPtr;
-
- switch (legendPtr->flags & SELECT_BLTMASK) {
- case SELECT_CLEAR:
- DeselectElement(legendPtr, elemPtr);
- break;
-
- case SELECT_SET:
- SelectElement(legendPtr, elemPtr);
- break;
-
- case SELECT_TOGGLE:
- hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
- if (hPtr != NULL) {
- DeselectElement(legendPtr, elemPtr);
- } else {
- SelectElement(legendPtr, elemPtr);
- }
- break;
- }
+ Legend* legendPtr = graphPtr->legend;
+
+ /* GC for active label. Dashed outline. */
+ unsigned long gcMask = GCForeground | GCLineStyle;
+ XGCValues gcValues;
+ gcValues.foreground = legendPtr->focusColor->pixel;
+ gcValues.line_style = (LineIsDashed(legendPtr->focusDashes))
+ ? LineOnOffDash : LineSolid;
+ GC newGC = Blt_GetPrivateGC(legendPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(legendPtr->focusDashes)) {
+ legendPtr->focusDashes.offset = 2;
+ Blt_SetDashes(graphPtr->display, newGC, &legendPtr->focusDashes);
+ }
+ if (legendPtr->focusGC != NULL)
+ Blt_FreePrivateGC(graphPtr->display, legendPtr->focusGC);
+
+ legendPtr->focusGC = newGC;
}
-/*ARGSUSED*/
-static ClientData
-PickEntryProc(ClientData clientData, int x, int y, ClientData *contextPtr)
+static void DisplayLegend(ClientData clientData)
{
- Graph *graphPtr = clientData;
- Legend *legendPtr;
+ Legend *legendPtr = clientData;
+ Graph *graphPtr;
+
+ legendPtr->flags &= ~REDRAW_PENDING;
+ if (legendPtr->tkwin == NULL) {
+ return; /* Window has been destroyed. */
+ }
+ graphPtr = legendPtr->graphPtr;
+ if (legendPtr->site == LEGEND_WINDOW) {
int w, h;
- legendPtr = graphPtr->legend;
- w = legendPtr->width;
- h = legendPtr->height;
-
- if (legendPtr->titleHeight > 0) {
- y -= legendPtr->titleHeight + legendPtr->yPad;
- }
- x -= legendPtr->x + legendPtr->borderWidth;
- y -= legendPtr->y + legendPtr->borderWidth;
- w -= 2 * legendPtr->borderWidth + 2*legendPtr->xPad;
- h -= 2 * legendPtr->borderWidth + 2*legendPtr->yPad;
-
- if ((x >= 0) && (x < w) && (y >= 0) && (y < h)) {
- int row, column;
- int n;
-
- /*
- * It's in the bounding box, so compute the index.
- */
- row = y / legendPtr->entryHeight;
- column = x / legendPtr->entryWidth;
- n = (column * legendPtr->nRows) + row;
- if (n < legendPtr->nEntries) {
- Blt_ChainLink link;
- int count;
-
- /* Legend entries are stored in bottom-to-top. */
- count = 0;
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label != NULL) {
- if (count == n) {
- return elemPtr;
- }
- count++;
- }
- }
- if (link != NULL) {
- return Blt_Chain_GetValue(link);
- }
- }
+ w = Tk_Width(legendPtr->tkwin);
+ h = Tk_Height(legendPtr->tkwin);
+ if ((w != legendPtr->width) || (h != legendPtr->height)) {
+ Blt_MapLegend(graphPtr, w, h);
}
- return NULL;
+ }
+ if (Tk_IsMapped(legendPtr->tkwin)) {
+ Blt_DrawLegend(graphPtr, Tk_WindowId(legendPtr->tkwin));
+ }
}
-/*
- *---------------------------------------------------------------------------
- *
- * Blt_MapLegend --
- *
- * Calculates the dimensions (width and height) needed for the legend.
- * Also determines the number of rows and columns necessary to list all
- * the valid element labels.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The following fields of the legend are calculated and set.
- *
- * nEntries - number of valid labels of elements in the
- * display list.
- * nRows - number of rows of entries
- * nColumns - number of columns of entries
- * entryHeight - height of each entry
- * entryWidth - width of each entry
- * height - width of legend (includes borders and padding)
- * width - height of legend (includes borders and padding)
- *
- *---------------------------------------------------------------------------
- */
-void
-Blt_MapLegend(
- Graph *graphPtr,
- int plotWidth, /* Maximum width available in window
- * to draw the legend. Will calculate
- * # of columns from this. */
- int plotHeight) /* Maximum height available in window
- * to draw the legend. Will calculate
- * # of rows from this. */
+static void LegendEventProc(ClientData clientData, XEvent *eventPtr)
{
- Legend *legendPtr = graphPtr->legend;
- Blt_ChainLink link;
- int nRows, nColumns, nEntries;
- int lw, lh;
- int maxWidth, maxHeight;
- int symbolWidth;
- Tk_FontMetrics fontMetrics;
-
- /* Initialize legend values to default (no legend displayed) */
- legendPtr->entryWidth = legendPtr->entryHeight = 0;
- legendPtr->nRows = legendPtr->nColumns = legendPtr->nEntries = 0;
- legendPtr->height = legendPtr->width = 0;
+ Graph *graphPtr = clientData;
+ Legend *legendPtr;
- if (legendPtr->site == LEGEND_WINDOW) {
- if (Tk_Width(legendPtr->tkwin) > 1) {
- plotWidth = Tk_Width(legendPtr->tkwin);
- }
- if (Tk_Height(legendPtr->tkwin) > 1) {
- plotHeight = Tk_Height(legendPtr->tkwin);
- }
+ legendPtr = graphPtr->legend;
+ if (eventPtr->type == Expose) {
+ if (eventPtr->xexpose.count == 0) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
}
- Blt_Ts_GetExtents(&legendPtr->titleStyle, legendPtr->title,
- &legendPtr->titleWidth, &legendPtr->titleHeight);
- /*
- * Count the number of legend entries and determine the widest and tallest
- * label. The number of entries would normally be the number of elements,
- * but elements can have no legend entry (-label "").
- */
- nEntries = 0;
- maxWidth = maxHeight = 0;
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- unsigned int w, h;
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue; /* Element has no legend entry. */
- }
- Blt_Ts_GetExtents(&legendPtr->style, elemPtr->label, &w, &h);
- if (maxWidth < w) {
- maxWidth = w;
- }
- if (maxHeight < h) {
- maxHeight = h;
- }
- nEntries++;
+ } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
+ if (eventPtr->xfocus.detail == NotifyInferior) {
+ return;
}
- if (nEntries == 0) {
- return; /* No visible legend entries. */
+ if (eventPtr->type == FocusIn) {
+ legendPtr->flags |= FOCUS;
+ } else {
+ legendPtr->flags &= ~FOCUS;
+ }
+ Tcl_DeleteTimerHandler(legendPtr->timerToken);
+ if ((legendPtr->active) && (legendPtr->flags & FOCUS)) {
+ legendPtr->cursorOn = TRUE;
+ if (legendPtr->offTime != 0) {
+ legendPtr->timerToken = Tcl_CreateTimerHandler(legendPtr->onTime,
+ BlinkCursorProc,
+ graphPtr);
+ }
+ } else {
+ legendPtr->cursorOn = FALSE;
+ legendPtr->timerToken = (Tcl_TimerToken)NULL;
}
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ } else if (eventPtr->type == DestroyNotify) {
+ Graph *graphPtr = legendPtr->graphPtr;
-
- Tk_GetFontMetrics(legendPtr->style.font, &fontMetrics);
- symbolWidth = 2 * fontMetrics.ascent;
-
- maxWidth += 2 * legendPtr->entryBW + 2*legendPtr->ixPad +
- + symbolWidth + 3 * LABEL_PAD;
-
- maxHeight += 2 * legendPtr->entryBW + 2*legendPtr->iyPad;
-
- maxWidth |= 0x01;
- maxHeight |= 0x01;
-
- lw = plotWidth - 2 * legendPtr->borderWidth - 2*legendPtr->xPad;
- lh = plotHeight - 2 * legendPtr->borderWidth - 2*legendPtr->yPad;
-
- /*
- * The number of rows and columns is computed as one of the following:
- *
- * both options set User defined.
- * -rows Compute columns from rows.
- * -columns Compute rows from columns.
- * neither set Compute rows and columns from
- * size of plot.
- */
- if (legendPtr->reqRows > 0) {
- nRows = MIN(legendPtr->reqRows, nEntries);
- if (legendPtr->reqColumns > 0) {
- nColumns = MIN(legendPtr->reqColumns, nEntries);
- } else {
- nColumns = ((nEntries - 1) / nRows) + 1; /* Only -rows. */
- }
- } else if (legendPtr->reqColumns > 0) { /* Only -columns. */
- nColumns = MIN(legendPtr->reqColumns, nEntries);
- nRows = ((nEntries - 1) / nColumns) + 1;
- } else {
- /* Compute # of rows and columns from the legend size. */
- nRows = lh / maxHeight;
- nColumns = lw / maxWidth;
- if (nRows < 1) {
- nRows = nEntries;
- }
- if (nColumns < 1) {
- nColumns = nEntries;
- }
- if (nRows > nEntries) {
- nRows = nEntries;
- }
- switch (legendPtr->site) {
- case LEGEND_TOP:
- case LEGEND_BOTTOM:
- nRows = ((nEntries - 1) / nColumns) + 1;
- break;
- case LEGEND_LEFT:
- case LEGEND_RIGHT:
- default:
- nColumns = ((nEntries - 1) / nRows) + 1;
- break;
- }
+ if (legendPtr->site == LEGEND_WINDOW) {
+ if (legendPtr->cmdToken != NULL) {
+ Tcl_DeleteCommandFromToken(graphPtr->interp,
+ legendPtr->cmdToken);
+ legendPtr->cmdToken = NULL;
+ }
+ legendPtr->tkwin = graphPtr->tkwin;
}
- if (nColumns < 1) {
- nColumns = 1;
- }
- if (nRows < 1) {
- nRows = 1;
+ if (legendPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayLegend, legendPtr);
+ legendPtr->flags &= ~REDRAW_PENDING;
}
+ legendPtr->site = LEGEND_RIGHT;
+ legendPtr->hide = 1;
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ Blt_MoveBindingTable(legendPtr->bindTable, graphPtr->tkwin);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ } else if (eventPtr->type == ConfigureNotify) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+}
- lh = (nRows * maxHeight);
- if (legendPtr->titleHeight > 0) {
- lh += legendPtr->titleHeight + legendPtr->yPad;
- }
- lw = nColumns * maxWidth;
- if (lw < legendPtr->titleWidth) {
- lw = legendPtr->titleWidth;
- }
- legendPtr->width = lw + 2 * legendPtr->borderWidth +
- 2*legendPtr->xPad;
- legendPtr->height = lh + 2 * legendPtr->borderWidth +
- 2*legendPtr->yPad;
- legendPtr->nRows = nRows;
- legendPtr->nColumns = nColumns;
- legendPtr->nEntries = nEntries;
- legendPtr->entryHeight = maxHeight;
- legendPtr->entryWidth = maxWidth;
+void Blt_DeleteLegend(Graph* graphPtr)
+{
+ Legend *legendPtr = graphPtr->legend;
+ if (legendPtr != NULL)
+ Tk_FreeConfigOptions((char*)legendPtr, legendPtr->optionTable,
+ graphPtr->tkwin);
+}
- {
- int row, col, count;
+void Blt_DestroyLegend(Graph *graphPtr)
+{
+ Legend *legendPtr = graphPtr->legend;
- row = col = count = 0;
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- count++;
- elemPtr->row = row;
- elemPtr->col = col;
- row++;
- if ((count % nRows) == 0) {
- col++;
- row = 0;
- }
- }
+ if (graphPtr->legend == NULL)
+ return;
+
+ Blt_Ts_FreeStyle(graphPtr->display, &legendPtr->style);
+ Blt_Ts_FreeStyle(graphPtr->display, &legendPtr->titleStyle);
+ Blt_DestroyBindingTable(legendPtr->bindTable);
+
+ if (legendPtr->focusGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, legendPtr->focusGC);
+ }
+ if (legendPtr->timerToken != NULL) {
+ Tcl_DeleteTimerHandler(legendPtr->timerToken);
+ }
+ if (legendPtr->tkwin != NULL) {
+ Tk_DeleteSelHandler(legendPtr->tkwin, XA_PRIMARY, XA_STRING);
+ }
+ if (legendPtr->site == LEGEND_WINDOW) {
+ Tk_Window tkwin;
+
+ /* The graph may be in the process of being torn down */
+ if (legendPtr->cmdToken != NULL) {
+ Tcl_DeleteCommandFromToken(graphPtr->interp, legendPtr->cmdToken);
}
- if ((legendPtr->site == LEGEND_WINDOW) &&
- ((Tk_ReqWidth(legendPtr->tkwin) != legendPtr->width) ||
- (Tk_ReqHeight(legendPtr->tkwin) != legendPtr->height))) {
- Tk_GeometryRequest(legendPtr->tkwin,legendPtr->width,legendPtr->height);
+ if (legendPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayLegend, legendPtr);
+ legendPtr->flags &= ~REDRAW_PENDING;
}
+ tkwin = legendPtr->tkwin;
+ legendPtr->tkwin = NULL;
+ if (tkwin != NULL) {
+ Tk_DeleteEventHandler(tkwin, ExposureMask | StructureNotifyMask,
+ LegendEventProc, graphPtr);
+ Tk_DestroyWindow(tkwin);
+ }
+ }
+ free(legendPtr);
}
-void
-Blt_DrawLegend(Graph *graphPtr, Drawable drawable)
+// Widget commands
+
+static int ActivateOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Blt_Background bg;
+ Legend *legendPtr = graphPtr->legend;
+ unsigned int active, redraw;
+ const char *string;
+ int i;
+
+ string = Tcl_GetString(objv[2]);
+ active = (string[0] == 'a') ? LABEL_ACTIVE : 0;
+ redraw = FALSE;
+ for (i = 3; i < objc; i++) {
Blt_ChainLink link;
- Tk_FontMetrics fontMetrics;
- Legend *legendPtr = graphPtr->legend;
- Pixmap pixmap;
- Tk_Window tkwin;
- int count;
- int symbolSize, xMid, yMid;
- int x, y, w, h;
- int xLabel, yStart, xSymbol, ySymbol;
+ const char *pattern;
- if ((legendPtr->flags & HIDE) || (legendPtr->nEntries == 0)) {
- return;
+ pattern = Tcl_GetString(objv[i]);
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (Tcl_StringMatch(elemPtr->obj.name, pattern)) {
+ fprintf(stderr, "legend %s(%s) %s is currently %d\n",
+ string, pattern, elemPtr->obj.name,
+ (elemPtr->flags & LABEL_ACTIVE));
+ if (active) {
+ if ((elemPtr->flags & LABEL_ACTIVE) == 0) {
+ elemPtr->flags |= LABEL_ACTIVE;
+ redraw = TRUE;
+ }
+ } else {
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ elemPtr->flags &= ~LABEL_ACTIVE;
+ redraw = TRUE;
+ }
+ }
+ fprintf(stderr, "legend %s(%s) %s is now %d\n",
+ string, pattern, elemPtr->obj.name,
+ (elemPtr->flags & LABEL_ACTIVE));
+ }
+ }
+ }
+ if ((redraw) && ((legendPtr->hide) == 0)) {
+ /*
+ * See if how much we need to draw. If the graph is already scheduled
+ * for a redraw, just make sure the right flags are set. Otherwise
+ * redraw only the legend: it's either in an external window or it's
+ * the only thing that need updating.
+ */
+ if ((legendPtr->site != LEGEND_WINDOW) &&
+ (graphPtr->flags & REDRAW_PENDING)) {
+ graphPtr->flags |= CACHE_DIRTY;
+ graphPtr->flags |= REDRAW_WORLD; /* Redraw entire graph. */
+ } else {
+ Blt_Legend_EventuallyRedraw(graphPtr);
}
+ }
+ {
+ Blt_ChainLink link;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ /* List active elements in stacking order. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
- SetLegendOrigin(legendPtr);
- graphPtr = legendPtr->graphPtr;
- tkwin = legendPtr->tkwin;
- if (legendPtr->site == LEGEND_WINDOW) {
- w = Tk_Width(tkwin);
- h = Tk_Height(tkwin);
- } else {
- w = legendPtr->width;
- h = legendPtr->height;
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
}
+ Tcl_SetObjResult(interp, listObjPtr);
+ }
+ return TCL_OK;
+}
- pixmap = Tk_GetPixmap(graphPtr->display, Tk_WindowId(tkwin), w, h,
- Tk_Depth(tkwin));
+static int BindOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch iter;
+ Tcl_Obj *listObjPtr;
- if (legendPtr->normalBg != NULL) {
- Blt_FillBackgroundRectangle(tkwin, pixmap, legendPtr->normalBg, 0, 0,
- w, h, 0, TK_RELIEF_FLAT);
- } else if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
- /*
- * Legend background is transparent and is positioned over the the
- * plot area. Either copy the part of the background from the backing
- * store pixmap or (if no backing store exists) just fill it with the
- * background color of the plot.
- */
- if (graphPtr->cache != None) {
- XCopyArea(graphPtr->display, graphPtr->cache, pixmap,
- graphPtr->drawGC, legendPtr->x, legendPtr->y, w, h, 0, 0);
- } else {
- Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->plotBg, 0, 0,
- w, h, TK_RELIEF_FLAT, 0);
- }
- } else {
- int xOrigin, yOrigin;
- /*
- * The legend is located in one of the margins or the external window.
- */
- Blt_GetBackgroundOrigin(graphPtr->normalBg, &xOrigin, &yOrigin);
- Blt_SetBackgroundOrigin(graphPtr->tkwin, graphPtr->normalBg,
- xOrigin - legendPtr->x,yOrigin - legendPtr->y);
- Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->normalBg, 0, 0,
- w, h, 0, TK_RELIEF_FLAT);
- Blt_SetBackgroundOrigin(tkwin, graphPtr->normalBg, xOrigin, yOrigin);
- }
- Tk_GetFontMetrics(legendPtr->style.font, &fontMetrics);
-
- symbolSize = fontMetrics.ascent;
- xMid = symbolSize + 1 + legendPtr->entryBW;
- yMid = (symbolSize / 2) + 1 + legendPtr->entryBW;
- xLabel = 2 * symbolSize + legendPtr->entryBW +
- legendPtr->ixPad + 2 * LABEL_PAD;
- ySymbol = yMid + legendPtr->iyPad;
- xSymbol = xMid + LABEL_PAD;
-
- x = legendPtr->xPad + legendPtr->borderWidth;
- y = legendPtr->yPad + legendPtr->borderWidth;
- Blt_DrawText(tkwin, pixmap, legendPtr->title, &legendPtr->titleStyle, x, y);
- if (legendPtr->titleHeight > 0) {
- y += legendPtr->titleHeight + legendPtr->yPad;
- }
- count = 0;
- yStart = y;
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
- int isSelected;
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (hPtr = Tcl_FirstHashEntry(&graphPtr->elements.tagTable, &iter);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&iter)) {
+ const char *tagName;
+ Tcl_Obj *objPtr;
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue; /* Skip this entry */
- }
- isSelected = EntryIsSelected(legendPtr, elemPtr);
- if (elemPtr->flags & LABEL_ACTIVE) {
- int xOrigin, yOrigin;
-
- Blt_GetBackgroundOrigin(legendPtr->activeBg, &xOrigin, &yOrigin);
- Blt_SetBackgroundOrigin(tkwin, legendPtr->activeBg,
- xOrigin - legendPtr->x, yOrigin - legendPtr->y);
- Blt_Ts_SetForeground(legendPtr->style, legendPtr->activeFgColor);
- Blt_FillBackgroundRectangle(tkwin, pixmap, legendPtr->activeBg,
- x, y, legendPtr->entryWidth, legendPtr->entryHeight,
- legendPtr->entryBW, legendPtr->activeRelief);
- Blt_SetBackgroundOrigin(tkwin, legendPtr->activeBg,
- xOrigin, yOrigin);
- } else if (isSelected) {
- int xOrigin, yOrigin;
- Blt_Background bg;
- XColor *fg;
-
- fg = (legendPtr->flags & FOCUS) ?
- legendPtr->selInFocusFgColor : legendPtr->selOutFocusFgColor;
- bg = (legendPtr->flags & FOCUS) ?
- legendPtr->selInFocusBg : legendPtr->selOutFocusBg;
- Blt_GetBackgroundOrigin(bg, &xOrigin, &yOrigin);
- Blt_SetBackgroundOrigin(tkwin, bg, xOrigin - legendPtr->x,
- yOrigin - legendPtr->y);
- Blt_Ts_SetForeground(legendPtr->style, fg);
- Blt_FillBackgroundRectangle(tkwin, pixmap, bg, x, y,
- legendPtr->entryWidth, legendPtr->entryHeight,
- legendPtr->selBW, legendPtr->selRelief);
- Blt_SetBackgroundOrigin(tkwin, bg, xOrigin, yOrigin);
- } else {
- Blt_Ts_SetForeground(legendPtr->style, legendPtr->fgColor);
- if (elemPtr->legendRelief != TK_RELIEF_FLAT) {
- Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->normalBg,
- x, y, legendPtr->entryWidth,
- legendPtr->entryHeight, legendPtr->entryBW,
- elemPtr->legendRelief);
- }
- }
- (*elemPtr->procsPtr->drawSymbolProc) (graphPtr, pixmap, elemPtr,
- x + xSymbol, y + ySymbol, symbolSize);
- Blt_DrawText(tkwin, pixmap, elemPtr->label, &legendPtr->style,
- x + xLabel,
- y + legendPtr->entryBW + legendPtr->iyPad);
- count++;
- if (legendPtr->focusPtr == elemPtr) { /* Focus outline */
- if (isSelected) {
- XColor *color;
-
- color = (legendPtr->flags & FOCUS) ?
- legendPtr->selInFocusFgColor :
- legendPtr->selOutFocusFgColor;
- XSetForeground(graphPtr->display, legendPtr->focusGC,
- color->pixel);
- }
- XDrawRectangle(graphPtr->display, pixmap, legendPtr->focusGC,
- x + 1, y + 1, legendPtr->entryWidth - 3,
- legendPtr->entryHeight - 3);
- if (isSelected) {
- XSetForeground(graphPtr->display, legendPtr->focusGC,
- legendPtr->focusColor->pixel);
- }
- }
- /* Check when to move to the next column */
- if ((count % legendPtr->nRows) > 0) {
- y += legendPtr->entryHeight;
- } else {
- x += legendPtr->entryWidth;
- y = yStart;
- }
+ tagName = Tcl_GetHashKey(&graphPtr->elements.tagTable, hPtr);
+ objPtr = Tcl_NewStringObj(tagName, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
}
- /*
- * Draw the border and/or background of the legend.
- */
- bg = legendPtr->normalBg;
- if (bg == NULL) {
- bg = graphPtr->normalBg;
- }
- /* Disable crosshairs before redisplaying to the screen */
- if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
- Blt_DisableCrosshairs(graphPtr);
- }
- Blt_DrawBackgroundRectangle(tkwin, pixmap, bg, 0, 0, w, h,
- legendPtr->borderWidth, legendPtr->relief);
- XCopyArea(graphPtr->display, pixmap, drawable, graphPtr->drawGC, 0, 0, w, h,
- legendPtr->x, legendPtr->y);
- if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
- Blt_EnableCrosshairs(graphPtr);
- }
- Tk_FreePixmap(graphPtr->display, pixmap);
- graphPtr->flags &= ~DRAW_LEGEND;
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ return Blt_ConfigureBindingsFromObj(interp, graphPtr->legend->bindTable, Blt_MakeElementTag(graphPtr, Tcl_GetString(objv[3])), objc - 4, objv + 4);
}
-/*
- *---------------------------------------------------------------------------
- *
- * Blt_LegendToPostScript --
- *
- *---------------------------------------------------------------------------
- */
-void
-Blt_LegendToPostScript(Graph *graphPtr, Blt_Ps ps)
+static int CurselectionOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Legend *legendPtr = graphPtr->legend;
- double x, y, yStart;
- int xLabel, xSymbol, ySymbol;
- int count;
+ Legend *legendPtr = graphPtr->legend;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (legendPtr->flags & SELECT_SORTED) {
Blt_ChainLink link;
- int symbolSize, xMid, yMid;
- int width, height;
- Tk_FontMetrics fontMetrics;
- if ((legendPtr->flags & HIDE) || (legendPtr->nEntries == 0)) {
- return;
+ for (link = Blt_Chain_FirstLink(legendPtr->selected); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+ Tcl_Obj *objPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
}
- SetLegendOrigin(legendPtr);
+ } else {
+ Blt_ChainLink link;
- x = legendPtr->x, y = legendPtr->y;
- width = legendPtr->width - 2*legendPtr->xPad;
- height = legendPtr->height - 2*legendPtr->yPad;
+ /* List of selected entries is in stacking order. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
- Blt_Ps_Append(ps, "% Legend\n");
- graphPtr = legendPtr->graphPtr;
- if (graphPtr->pageSetup->flags & PS_DECORATIONS) {
- if (legendPtr->normalBg != NULL) {
- Tk_3DBorder border;
+ elemPtr = Blt_Chain_GetValue(link);
- border = Blt_BackgroundBorder(legendPtr->normalBg);
- Blt_Ps_Fill3DRectangle(ps, border, x, y, width, height,
- legendPtr->borderWidth, legendPtr->relief);
- } else {
- Tk_3DBorder border;
+ if (EntryIsSelected(legendPtr, elemPtr)) {
+ Tcl_Obj *objPtr;
- border = Blt_BackgroundBorder(graphPtr->normalBg);
- Blt_Ps_Draw3DRectangle(ps, border, x, y, width, height,
- legendPtr->borderWidth, legendPtr->relief);
- }
- } else {
- Blt_Ps_SetClearBackground(ps);
- Blt_Ps_XFillRectangle(ps, x, y, width, height);
- }
- Tk_GetFontMetrics(legendPtr->style.font, &fontMetrics);
- symbolSize = fontMetrics.ascent;
- xMid = symbolSize + 1 + legendPtr->entryBW;
- yMid = (symbolSize / 2) + 1 + legendPtr->entryBW;
- xLabel = 2 * symbolSize + legendPtr->entryBW + legendPtr->ixPad + 5;
- xSymbol = xMid + legendPtr->ixPad;
- ySymbol = yMid + legendPtr->iyPad;
-
- x += legendPtr->borderWidth;
- y += legendPtr->borderWidth;
- Blt_Ps_DrawText(ps, legendPtr->title, &legendPtr->titleStyle, x, y);
- if (legendPtr->titleHeight > 0) {
- y += legendPtr->titleHeight + legendPtr->yPad;
- }
-
- count = 0;
- yStart = y;
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue; /* Skip this label */
- }
- if (elemPtr->flags & LABEL_ACTIVE) {
- Tk_3DBorder border;
-
- border = Blt_BackgroundBorder(legendPtr->activeBg);
- Blt_Ts_SetForeground(legendPtr->style, legendPtr->activeFgColor);
- Blt_Ps_Fill3DRectangle(ps, border, x, y, legendPtr->entryWidth,
- legendPtr->entryHeight, legendPtr->entryBW,
- legendPtr->activeRelief);
- } else {
- Blt_Ts_SetForeground(legendPtr->style, legendPtr->fgColor);
- if (elemPtr->legendRelief != TK_RELIEF_FLAT) {
- Tk_3DBorder border;
-
- border = Blt_BackgroundBorder(graphPtr->normalBg);
- Blt_Ps_Draw3DRectangle(ps, border, x, y, legendPtr->entryWidth,
- legendPtr->entryHeight, legendPtr->entryBW,
- elemPtr->legendRelief);
- }
- }
- (*elemPtr->procsPtr->printSymbolProc) (graphPtr, ps, elemPtr,
- x + xSymbol, y + ySymbol, symbolSize);
- Blt_Ps_DrawText(ps, elemPtr->label, &legendPtr->style,
- x + xLabel, y + legendPtr->entryBW + legendPtr->iyPad);
- count++;
- if ((count % legendPtr->nRows) > 0) {
- y += legendPtr->entryHeight;
- } else {
- x += legendPtr->entryWidth;
- y = yStart;
- }
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
}
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
}
-/*
- *---------------------------------------------------------------------------
- *
- * DisplayLegend --
- *
- *---------------------------------------------------------------------------
- */
-static void
-DisplayLegend(ClientData clientData)
+static int FocusOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Legend *legendPtr = clientData;
- Graph *graphPtr;
+ Legend *legendPtr = graphPtr->legend;
- legendPtr->flags &= ~REDRAW_PENDING;
- if (legendPtr->tkwin == NULL) {
- return; /* Window has been destroyed. */
- }
- graphPtr = legendPtr->graphPtr;
- if (legendPtr->site == LEGEND_WINDOW) {
- int w, h;
+ if (objc == 4) {
+ Element *elemPtr;
- w = Tk_Width(legendPtr->tkwin);
- h = Tk_Height(legendPtr->tkwin);
- if ((w != legendPtr->width) || (h != legendPtr->height)) {
- Blt_MapLegend(graphPtr, w, h);
- }
+ if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
}
- if (Tk_IsMapped(legendPtr->tkwin)) {
- Blt_DrawLegend(graphPtr, Tk_WindowId(legendPtr->tkwin));
+ if ((elemPtr != NULL) && (elemPtr != legendPtr->focusPtr)) {
+ /* Changing focus can only affect the visible entries. The entry
+ * layout stays the same. */
+ legendPtr->focusPtr = elemPtr;
}
+ Blt_SetFocusItem(legendPtr->bindTable, legendPtr->focusPtr,
+ CID_LEGEND_ENTRY);
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ if (legendPtr->focusPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ legendPtr->focusPtr->obj.name, -1);
+ }
+ return TCL_OK;
}
-void Blt_ConfigureLegend(Graph *graphPtr)
+static int GetOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- GC newGC;
- XGCValues gcValues;
- unsigned long gcMask;
- Legend *legendPtr;
-
- legendPtr = graphPtr->legend;
- /* GC for active label. Dashed outline. */
- gcMask = GCForeground | GCLineStyle;
- gcValues.foreground = legendPtr->focusColor->pixel;
- gcValues.line_style = (LineIsDashed(legendPtr->focusDashes))
- ? LineOnOffDash : LineSolid;
- newGC = Blt_GetPrivateGC(legendPtr->tkwin, gcMask, &gcValues);
- if (LineIsDashed(legendPtr->focusDashes)) {
- legendPtr->focusDashes.offset = 2;
- Blt_SetDashes(graphPtr->display, newGC, &legendPtr->focusDashes);
- }
- if (legendPtr->focusGC != NULL) {
- Blt_FreePrivateGC(graphPtr->display, legendPtr->focusGC);
- }
- legendPtr->focusGC = newGC;
-
- /*
- * Update the layout of the graph (and redraw the elements) if any of
- * the following legend options (all of which affect the size of the
- * legend) have changed.
- *
- * -activeborderwidth, -borderwidth
- * -border
- * -font
- * -hide
- * -ipadx, -ipady, -padx, -pady
- * -rows
- *
- * If the position of the legend changed to/from the default
- * position, also indicate that a new layout is needed.
- *
- */
- if (legendPtr->site == LEGEND_WINDOW) {
- Blt_Legend_EventuallyRedraw(graphPtr);
- } else if (Blt_ConfigModified(configSpecs, "-*border*", "-*pad?",
- "-hide", "-font", "-rows", (char *)NULL)) {
- graphPtr->flags |= RESET_WORLD;
- graphPtr->flags |= (REDRAW_WORLD | CACHE_DIRTY);
- Blt_EventuallyRedrawGraph(graphPtr);
- }
-}
+ Legend *legendPtr = graphPtr->legend;
-/*
- *---------------------------------------------------------------------------
- *
- * Blt_DestroyLegend --
- *
- * Results:
- * None.
- *
- * Side effects:
- * Resources associated with the legend are freed.
- *
- *---------------------------------------------------------------------------
- */
-void
-Blt_DestroyLegend(Graph *graphPtr)
-{
- Legend *legendPtr = graphPtr->legend;
-
- if (graphPtr->legend == NULL) {
- return;
- }
+ if (((legendPtr->hide) == 0) && (legendPtr->nEntries > 0)) {
+ Element *elemPtr;
- Blt_FreeOptions(configSpecs, (char *)legendPtr, graphPtr->display, 0);
- Blt_Ts_FreeStyle(graphPtr->display, &legendPtr->style);
- Blt_Ts_FreeStyle(graphPtr->display, &legendPtr->titleStyle);
- Blt_DestroyBindingTable(legendPtr->bindTable);
-
- if (legendPtr->focusGC != NULL) {
- Blt_FreePrivateGC(graphPtr->display, legendPtr->focusGC);
- }
- if (legendPtr->timerToken != NULL) {
- Tcl_DeleteTimerHandler(legendPtr->timerToken);
- }
- if (legendPtr->tkwin != NULL) {
- Tk_DeleteSelHandler(legendPtr->tkwin, XA_PRIMARY, XA_STRING);
+ if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
}
- if (legendPtr->site == LEGEND_WINDOW) {
- Tk_Window tkwin;
-
- /* The graph may be in the process of being torn down */
- if (legendPtr->cmdToken != NULL) {
- Tcl_DeleteCommandFromToken(graphPtr->interp, legendPtr->cmdToken);
- }
- if (legendPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(DisplayLegend, legendPtr);
- legendPtr->flags &= ~REDRAW_PENDING;
- }
- tkwin = legendPtr->tkwin;
- legendPtr->tkwin = NULL;
- if (tkwin != NULL) {
- Tk_DeleteEventHandler(tkwin, ExposureMask | StructureNotifyMask,
- LegendEventProc, graphPtr);
- Tk_DestroyWindow(tkwin);
- }
+ if (elemPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name,-1);
}
- free(legendPtr);
+ }
+ return TCL_OK;
}
-int Blt_CreateLegend(Graph *graphPtr)
-{
- Legend *legendPtr;
+static Blt_OpSpec selectionOps[];
+static int nSelectionOps;
- legendPtr = calloc(1, sizeof(Legend));
- graphPtr->legend = legendPtr;
- legendPtr->graphPtr = graphPtr;
- legendPtr->tkwin = graphPtr->tkwin;
- legendPtr->xReq = legendPtr->yReq = -SHRT_MAX;
- legendPtr->relief = TK_RELIEF_SUNKEN;
- legendPtr->activeRelief = TK_RELIEF_FLAT;
- legendPtr->entryBW = 2;
- legendPtr->borderWidth = 2;
- legendPtr->ixPad = 1;
- legendPtr->iyPad = 1;
- legendPtr->xPad = 1;
- legendPtr->yPad = 1;
- legendPtr->anchor = TK_ANCHOR_N;
- legendPtr->site = LEGEND_RIGHT;
- legendPtr->selectMode = SELECT_MODE_MULTIPLE;
- Blt_Ts_InitStyle(legendPtr->style);
- Blt_Ts_InitStyle(legendPtr->titleStyle);
- legendPtr->style.justify = TK_JUSTIFY_LEFT;
- legendPtr->style.anchor = TK_ANCHOR_NW;
- legendPtr->titleStyle.justify = TK_JUSTIFY_LEFT;
- legendPtr->titleStyle.anchor = TK_ANCHOR_NW;
- legendPtr->bindTable = Blt_CreateBindingTable(graphPtr->interp,
- graphPtr->tkwin, graphPtr, PickEntryProc, Blt_GraphTags);
+static int SelectionOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
+{
+ GraphLegendProc *proc;
+ int result;
- Tcl_InitHashTable(&legendPtr->selectTable, TCL_ONE_WORD_KEYS);
- legendPtr->selected = Blt_Chain_Create();
- Tk_CreateSelHandler(legendPtr->tkwin, XA_PRIMARY, XA_STRING,
- SelectionProc, legendPtr, XA_STRING);
- legendPtr->selRelief = TK_RELIEF_FLAT;
- legendPtr->selBW = 1;
- legendPtr->onTime = 600;
- legendPtr->offTime = 300;
- if (Blt_ConfigureComponentFromObj(graphPtr->interp, graphPtr->tkwin,
- "legend", "Legend", configSpecs, 0, (Tcl_Obj **)NULL,
- (char *)legendPtr, 0) != TCL_OK) {
+ proc = Blt_GetOpFromObj(interp, nSelectionOps, selectionOps, BLT_OP_ARG3,
+ objc, objv, 0);
+ if (proc == NULL) {
return TCL_ERROR;
}
-
- return TCL_OK;
+ result = (*proc) (graphPtr, interp, objc, objv);
+ return result;
}
-static Element *
-GetNextRow(Graph *graphPtr, Element *focusPtr)
+static Blt_OpSpec legendOps[] =
{
- Blt_ChainLink link;
- int row, col;
+ {"activate", 1, ActivateOp, 3, 0, "?pattern?...",},
+ {"bind", 1, BindOp, 3, 6, "elem sequence command",},
+ {"cget", 2, CgetOp, 4, 4, "option",},
+ {"configure", 2, ConfigureOp, 3, 0, "?option value?...",},
+ {"curselection", 2, CurselectionOp, 3, 3, "",},
+ {"deactivate", 1, ActivateOp, 3, 0, "?pattern?...",},
+ {"focus", 1, FocusOp, 4, 4, "elem",},
+ {"get", 1, GetOp, 4, 4, "elem",},
+ {"selection", 1, SelectionOp, 3, 0, "args"},
+};
+static int nLegendOps = sizeof(legendOps) / sizeof(Blt_OpSpec);
- col = focusPtr->col;
- row = focusPtr->row + 1;
- for (link = focusPtr->link; link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
+// Selection Widget Ops
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue;
- }
- if ((elemPtr->col == col) && (elemPtr->row == row)) {
- return elemPtr;
- }
- }
- return NULL;
+static int SelectionAnchorOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ Element *elemPtr;
+
+ if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Set both the anchor and the mark. Indicates that a single entry
+ * is selected. */
+ legendPtr->selAnchorPtr = elemPtr;
+ legendPtr->selMarkPtr = NULL;
+ if (elemPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name, -1);
+ }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ return TCL_OK;
}
-static Element *
-GetNextColumn(Graph *graphPtr, Element *focusPtr)
+static int SelectionClearallOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Blt_ChainLink link;
- int row, col;
-
- col = focusPtr->col + 1;
- row = focusPtr->row;
- for (link = focusPtr->link; link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
+ Legend *legendPtr = graphPtr->legend;
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue;
- }
- if ((elemPtr->col == col) && (elemPtr->row == row)) {
- return elemPtr; /* Don't go beyond legend boundaries. */
- }
- }
- return NULL;
+ ClearSelection(legendPtr);
+ return TCL_OK;
}
-static Element *
-GetPreviousRow(Graph *graphPtr, Element *focusPtr)
+static int SelectionIncludesOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Blt_ChainLink link;
- int row, col;
-
- col = focusPtr->col;
- row = focusPtr->row - 1;
- for (link = focusPtr->link; link != NULL; link = Blt_Chain_PrevLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue;
- }
- if ((elemPtr->col == col) && (elemPtr->row == row)) {
- return elemPtr;
- }
- }
- return NULL;
+ Legend *legendPtr = graphPtr->legend;
+ Element *elemPtr;
+ int bool;
+
+ if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ bool = EntryIsSelected(legendPtr, elemPtr);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
+ return TCL_OK;
}
-static Element *
-GetPreviousColumn(Graph *graphPtr, Element *focusPtr)
+static int SelectionMarkOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Blt_ChainLink link;
- int row, col;
-
- col = focusPtr->col - 1;
- row = focusPtr->row;
- for (link = focusPtr->link; link != NULL; link = Blt_Chain_PrevLink(link)) {
- Element *elemPtr;
+ Legend *legendPtr = graphPtr->legend;
+ Element *elemPtr;
+
+ if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (legendPtr->selAnchorPtr == NULL) {
+ Tcl_AppendResult(interp, "selection anchor must be set first",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (legendPtr->selMarkPtr != elemPtr) {
+ Blt_ChainLink link, next;
+
+ /* Deselect entry from the list all the way back to the anchor. */
+ for (link = Blt_Chain_LastLink(legendPtr->selected); link != NULL;
+ link = next) {
+ Element *selectPtr;
+
+ next = Blt_Chain_PrevLink(link);
+ selectPtr = Blt_Chain_GetValue(link);
+ if (selectPtr == legendPtr->selAnchorPtr) {
+ break;
+ }
+ DeselectElement(legendPtr, selectPtr);
+ }
+ legendPtr->flags &= ~SELECT_BLTMASK;
+ legendPtr->flags |= SELECT_SET;
+ SelectRange(legendPtr, legendPtr->selAnchorPtr, elemPtr);
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name, -1);
+ legendPtr->selMarkPtr = elemPtr;
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label == NULL) {
- continue;
- }
- if ((elemPtr->col == col) && (elemPtr->row == row)) {
- return elemPtr;
- }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ if (legendPtr->selectCmd != NULL) {
+ EventuallyInvokeSelectCmd(legendPtr);
}
- return NULL;
+ }
+ return TCL_OK;
}
-static Element *
-GetFirstElement(Graph *graphPtr)
+static int SelectionPresentOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Blt_ChainLink link;
-
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
+ Legend *legendPtr = graphPtr->legend;
+ int bool;
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label != NULL) {
- return elemPtr;
- }
- }
- return NULL;
+ bool = (Blt_Chain_GetLength(legendPtr->selected) > 0);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
+ return TCL_OK;
}
-static Element *
-GetLastElement(Graph *graphPtr)
+static int SelectionSetOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv)
{
- Blt_ChainLink link;
-
- for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_PrevLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->label != NULL) {
- return elemPtr;
- }
- }
- return NULL;
+ Legend *legendPtr = graphPtr->legend;
+ Element *firstPtr, *lastPtr;
+ const char *string;
+
+ legendPtr->flags &= ~SELECT_BLTMASK;
+ string = Tcl_GetString(objv[3]);
+ switch (string[0]) {
+ case 's':
+ legendPtr->flags |= SELECT_SET;
+ break;
+ case 'c':
+ legendPtr->flags |= SELECT_CLEAR;
+ break;
+ case 't':
+ legendPtr->flags |= SELECT_TOGGLE;
+ break;
+ }
+ if (GetElementFromObj(graphPtr, objv[4], &firstPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((firstPtr->flags & HIDE) && ((legendPtr->flags & SELECT_CLEAR)==0)) {
+ Tcl_AppendResult(interp, "can't select hidden node \"",
+ Tcl_GetString(objv[4]), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ lastPtr = firstPtr;
+ if (objc > 5) {
+ if (GetElementFromObj(graphPtr, objv[5], &lastPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((lastPtr->flags & HIDE) &&
+ ((legendPtr->flags & SELECT_CLEAR) == 0)) {
+ Tcl_AppendResult(interp, "can't select hidden node \"",
+ Tcl_GetString(objv[5]), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (firstPtr == lastPtr) {
+ SelectEntry(legendPtr, firstPtr);
+ } else {
+ SelectRange(legendPtr, firstPtr, lastPtr);
+ }
+ /* Set both the anchor and the mark. Indicates that a single entry is
+ * selected. */
+ if (legendPtr->selAnchorPtr == NULL) {
+ legendPtr->selAnchorPtr = firstPtr;
+ }
+ if (legendPtr->exportSelection) {
+ Tk_OwnSelection(legendPtr->tkwin, XA_PRIMARY, LostSelectionProc,
+ legendPtr);
+ }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ if (legendPtr->selectCmd != NULL) {
+ EventuallyInvokeSelectCmd(legendPtr);
+ }
+ return TCL_OK;
}
-/*
- *---------------------------------------------------------------------------
- *
- * GetElementFromObj --
- *
- * Parse an index into an entry and return either its value or an error.
- *
- * Results:
- * A standard TCL result. If all went well, then *indexPtr is filled in
- * with the character index (into entryPtr) corresponding to string. The
- * index value is guaranteed to lie between 0 and the number of characters
- * in the string, inclusive. If an error occurs then an error message is
- * left in the interp's result.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-static int
-GetElementFromObj(Graph *graphPtr, Tcl_Obj *objPtr, Element **elemPtrPtr)
+static Blt_OpSpec selectionOps[] =
{
- Element *elemPtr;
- Legend *legendPtr;
- Tcl_Interp *interp;
- char c;
- const char *string;
- int last;
+ {"anchor", 1, SelectionAnchorOp, 5, 5, "elem",},
+ {"clear", 5, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
+ {"clearall", 6, SelectionClearallOp, 4, 4, "",},
+ {"includes", 1, SelectionIncludesOp, 5, 5, "elem",},
+ {"mark", 1, SelectionMarkOp, 5, 5, "elem",},
+ {"present", 1, SelectionPresentOp, 4, 4, "",},
+ {"set", 1, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
+ {"toggle", 1, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
+};
+static int nSelectionOps = sizeof(selectionOps) / sizeof(Blt_OpSpec);
- legendPtr = graphPtr->legend;
- interp = graphPtr->interp;
- string = Tcl_GetString(objPtr);
- c = string[0];
- elemPtr = NULL;
-
- last = Blt_Chain_GetLength(graphPtr->elements.displayList) - 1;
- if ((c == 'a') && (strcmp(string, "anchor") == 0)) {
- elemPtr = legendPtr->selAnchorPtr;
- } else if ((c == 'c') && (strcmp(string, "current") == 0)) {
- elemPtr = (Element *)Blt_GetCurrentItem(legendPtr->bindTable);
- } else if ((c == 'f') && (strcmp(string, "first") == 0)) {
- elemPtr = GetFirstElement(graphPtr);
- } else if ((c == 'f') && (strcmp(string, "focus") == 0)) {
- elemPtr = legendPtr->focusPtr;
- } else if ((c == 'l') && (strcmp(string, "last") == 0)) {
- elemPtr = GetLastElement(graphPtr);
- } else if ((c == 'e') && (strcmp(string, "end") == 0)) {
- elemPtr = GetLastElement(graphPtr);
- } else if ((c == 'n') && (strcmp(string, "next.row") == 0)) {
- elemPtr = GetNextRow(graphPtr, legendPtr->focusPtr);
- } else if ((c == 'n') && (strcmp(string, "next.column") == 0)) {
- elemPtr = GetNextColumn(graphPtr, legendPtr->focusPtr);
- } else if ((c == 'p') && (strcmp(string, "previous.row") == 0)) {
- elemPtr = GetPreviousRow(graphPtr, legendPtr->focusPtr);
- } else if ((c == 'p') && (strcmp(string, "previous.column") == 0)) {
- elemPtr = GetPreviousColumn(graphPtr, legendPtr->focusPtr);
- } else if ((c == 's') && (strcmp(string, "sel.first") == 0)) {
- elemPtr = legendPtr->selFirstPtr;
- } else if ((c == 's') && (strcmp(string, "sel.last") == 0)) {
- elemPtr = legendPtr->selLastPtr;
- } else if (c == '@') {
- int x, y;
+// Support
- if (Blt_GetXY(interp, legendPtr->tkwin, string, &x, &y) != TCL_OK) {
- return TCL_ERROR;
- }
- elemPtr = (Element *)PickEntryProc(graphPtr, x, y, NULL);
- } else {
- if (Blt_GetElement(interp, graphPtr, objPtr, &elemPtr) != TCL_OK) {
- return TCL_ERROR;
- }
- if (elemPtr->link == NULL) {
- Tcl_AppendResult(interp, "bad legend index \"", string, "\"",
- (char *)NULL);
- return TCL_ERROR;
- }
- if (elemPtr->label == NULL) {
- elemPtr = NULL;
- }
- }
- *elemPtrPtr = elemPtr;
- return TCL_OK;
+void Blt_Legend_EventuallyRedraw(Graph *graphPtr)
+{
+ Legend *legendPtr = graphPtr->legend;
+
+ if ((legendPtr->tkwin != NULL) && !(legendPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayLegend, legendPtr);
+ legendPtr->flags |= REDRAW_PENDING;
+ }
}
/*
*---------------------------------------------------------------------------
*
- * SelectRange --
+ * SelectCmdProc --
*
- * Sets the selection flag for a range of nodes. The range is determined
- * by two pointers which designate the first/last nodes of the range.
+ * Invoked at the next idle point whenever the current selection changes.
+ * Executes some application-specific code in the -selectcommand option.
+ * This provides a way for applications to handle selection changes.
*
* Results:
- * Always returns TCL_OK.
+ * None.
+ *
+ * Side effects:
+ * TCL code gets executed for some application-specific task.
*
*---------------------------------------------------------------------------
*/
-static int
-SelectRange(Legend *legendPtr, Element *fromPtr, Element *toPtr)
+static void SelectCmdProc(ClientData clientData)
{
+ Legend *legendPtr = clientData;
- if (Blt_Chain_IsBefore(fromPtr->link, toPtr->link)) {
- Blt_ChainLink link;
-
- for (link = fromPtr->link; link != NULL;
- link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- SelectEntry(legendPtr, elemPtr);
- if (link == toPtr->link) {
- break;
- }
- }
- } else {
- Blt_ChainLink link;
+ Tcl_Preserve(legendPtr);
+ legendPtr->flags &= ~SELECT_PENDING;
+ if (legendPtr->selectCmd != NULL) {
+ Tcl_Interp *interp;
- for (link = fromPtr->link; link != NULL;
- link = Blt_Chain_PrevLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- SelectEntry(legendPtr, elemPtr);
- if (link == toPtr->link) {
- break;
- }
- }
+ interp = legendPtr->graphPtr->interp;
+ if (Tcl_GlobalEval(interp, legendPtr->selectCmd) != TCL_OK) {
+ Tcl_BackgroundError(interp);
}
- return TCL_OK;
+ }
+ Tcl_Release(legendPtr);
}
-
/*
*---------------------------------------------------------------------------
*
- * ActivateOp --
+ * EventuallyInvokeSelectCmd --
*
- * Activates a particular label in the legend.
+ * Queues a request to execute the -selectcommand code associated with
+ * the widget at the next idle point. Invoked whenever the selection
+ * changes.
*
* Results:
- * A standard TCL result.
+ * None.
*
- * Side Effects:
- * Graph will be redrawn to reflect the new legend attributes.
+ * Side effects:
+ * TCL code gets executed for some application-specific task.
*
*---------------------------------------------------------------------------
*/
-static int
-ActivateOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+static void EventuallyInvokeSelectCmd(Legend *legendPtr)
{
- Legend *legendPtr = graphPtr->legend;
- unsigned int active, redraw;
- const char *string;
- int i;
-
- string = Tcl_GetString(objv[2]);
- active = (string[0] == 'a') ? LABEL_ACTIVE : 0;
- redraw = FALSE;
- for (i = 3; i < objc; i++) {
- Blt_ChainLink link;
- const char *pattern;
-
- pattern = Tcl_GetString(objv[i]);
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (Tcl_StringMatch(elemPtr->obj.name, pattern)) {
- fprintf(stderr, "legend %s(%s) %s is currently %d\n",
- string, pattern, elemPtr->obj.name,
- (elemPtr->flags & LABEL_ACTIVE));
- if (active) {
- if ((elemPtr->flags & LABEL_ACTIVE) == 0) {
- elemPtr->flags |= LABEL_ACTIVE;
- redraw = TRUE;
- }
- } else {
- if (elemPtr->flags & LABEL_ACTIVE) {
- elemPtr->flags &= ~LABEL_ACTIVE;
- redraw = TRUE;
- }
- }
- fprintf(stderr, "legend %s(%s) %s is now %d\n",
- string, pattern, elemPtr->obj.name,
- (elemPtr->flags & LABEL_ACTIVE));
- }
- }
- }
- if ((redraw) && ((legendPtr->flags & HIDE) == 0)) {
- /*
- * See if how much we need to draw. If the graph is already scheduled
- * for a redraw, just make sure the right flags are set. Otherwise
- * redraw only the legend: it's either in an external window or it's
- * the only thing that need updating.
- */
- if ((legendPtr->site != LEGEND_WINDOW) &&
- (graphPtr->flags & REDRAW_PENDING)) {
- graphPtr->flags |= CACHE_DIRTY;
- graphPtr->flags |= REDRAW_WORLD; /* Redraw entire graph. */
- } else {
- Blt_Legend_EventuallyRedraw(graphPtr);
- }
- }
- {
- Blt_ChainLink link;
- Tcl_Obj *listObjPtr;
-
- listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
- /* List active elements in stacking order. */
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
-
- elemPtr = Blt_Chain_GetValue(link);
- if (elemPtr->flags & LABEL_ACTIVE) {
- Tcl_Obj *objPtr;
-
- objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
- Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
- }
- }
- Tcl_SetObjResult(interp, listObjPtr);
- }
- return TCL_OK;
+ if ((legendPtr->flags & SELECT_PENDING) == 0) {
+ legendPtr->flags |= SELECT_PENDING;
+ Tcl_DoWhenIdle(SelectCmdProc, legendPtr);
+ }
}
-/*
- *---------------------------------------------------------------------------
- *
- * BindOp --
- *
- * .t bind index sequence command
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-BindOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+static void ClearSelection(Legend *legendPtr)
{
- if (objc == 3) {
- Tcl_HashEntry *hPtr;
- Tcl_HashSearch iter;
- Tcl_Obj *listObjPtr;
-
- listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
- for (hPtr = Tcl_FirstHashEntry(&graphPtr->elements.tagTable, &iter);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&iter)) {
- const char *tagName;
- Tcl_Obj *objPtr;
-
- tagName = Tcl_GetHashKey(&graphPtr->elements.tagTable, hPtr);
- objPtr = Tcl_NewStringObj(tagName, -1);
- Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
- }
- Tcl_SetObjResult(interp, listObjPtr);
- return TCL_OK;
- }
- return Blt_ConfigureBindingsFromObj(interp, graphPtr->legend->bindTable,
- Blt_MakeElementTag(graphPtr, Tcl_GetString(objv[3])), objc - 4,
- objv + 4);
+ Tcl_DeleteHashTable(&legendPtr->selectTable);
+ Tcl_InitHashTable(&legendPtr->selectTable, TCL_ONE_WORD_KEYS);
+ Blt_Chain_Reset(legendPtr->selected);
+ Blt_Legend_EventuallyRedraw(legendPtr->graphPtr);
+ if (legendPtr->selectCmd != NULL) {
+ EventuallyInvokeSelectCmd(legendPtr);
+ }
}
/*
*---------------------------------------------------------------------------
*
- * CgetOp --
+ * LostSelectionProc --
*
- * Queries or resets options for the legend.
+ * This procedure is called back by Tk when the selection is grabbed away
+ * from a Text widget.
*
* Results:
- * A standard TCL result.
+ * None.
*
- * Side Effects:
- * Graph will be redrawn to reflect the new legend attributes.
+ * Side effects:
+ * The existing selection is unhighlighted, and the window is marked as
+ * not containing a selection.
*
*---------------------------------------------------------------------------
*/
-/* ARGSUSED */
-static int
-CgetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+static void LostSelectionProc(ClientData clientData)
{
- return Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, configSpecs,
- (char *)graphPtr->legend, objv[3], 0);
+ Legend *legendPtr = clientData;
+
+ if (legendPtr->exportSelection) {
+ ClearSelection(legendPtr);
+ }
}
-/*
- *---------------------------------------------------------------------------
- *
- * ConfigureOp --
- *
- * Queries or resets options for the legend.
- *
- * Results:
- * A standard TCL result.
- *
- * Side Effects:
- * Graph will be redrawn to reflect the new legend attributes.
- *
- *---------------------------------------------------------------------------
- */
-static int
-ConfigureOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+static int CreateLegendWindow(Tcl_Interp *interp, Legend *legendPtr,
+ const char *pathName)
{
- int flags = BLT_CONFIG_OBJV_ONLY;
- Legend *legendPtr;
-
- legendPtr = graphPtr->legend;
- if (objc == 3) {
- return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
- (char *)legendPtr, (Tcl_Obj *)NULL, flags);
- } else if (objc == 4) {
- return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
- (char *)legendPtr, objv[3], flags);
- }
- if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
- objc - 3, objv + 3, (char *)legendPtr, flags) != TCL_OK) {
- return TCL_ERROR;
- }
- Blt_ConfigureLegend(graphPtr);
- return TCL_OK;
+ Graph *graphPtr;
+ Tk_Window tkwin;
+
+ graphPtr = legendPtr->graphPtr;
+ tkwin = Tk_CreateWindowFromPath(interp, graphPtr->tkwin, pathName, NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ ((TkWindow*)tkwin)->instanceData = legendPtr;
+ Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask,
+ LegendEventProc, graphPtr);
+ /* Move the legend's binding table to the new window. */
+ Blt_MoveBindingTable(legendPtr->bindTable, tkwin);
+ if (legendPtr->tkwin != graphPtr->tkwin) {
+ Tk_DestroyWindow(legendPtr->tkwin);
+ }
+ /* Create a command by the same name as the legend window so that Legend
+ * bindings can use %W interchangably. */
+ legendPtr->cmdToken = Tcl_CreateObjCommand(interp, pathName,
+ Blt_GraphInstCmdProc,
+ graphPtr, NULL);
+ legendPtr->tkwin = tkwin;
+ legendPtr->site = LEGEND_WINDOW;
+ return TCL_OK;
}
+static void SetLegendOrigin(Legend *legendPtr)
+{
+ Graph *graphPtr;
+ int x, y, w, h;
+
+ graphPtr = legendPtr->graphPtr;
+ x = y = w = h = 0; /* Suppress compiler warning. */
+ switch (legendPtr->site) {
+ case LEGEND_RIGHT:
+ w = graphPtr->rightMargin.width - graphPtr->rightMargin.axesOffset;
+ h = graphPtr->bottom - graphPtr->top;
+ x = graphPtr->right + graphPtr->rightMargin.axesOffset;
+ y = graphPtr->top;
+ break;
+
+ case LEGEND_LEFT:
+ w = graphPtr->leftMargin.width - graphPtr->leftMargin.axesOffset;
+ h = graphPtr->bottom - graphPtr->top;
+ x = graphPtr->inset;
+ y = graphPtr->top;
+ break;
+
+ case LEGEND_TOP:
+ w = graphPtr->right - graphPtr->left;
+ h = graphPtr->topMargin.height - graphPtr->topMargin.axesOffset;
+ if (graphPtr->title != NULL) {
+ h -= graphPtr->titleHeight;
+ }
+ x = graphPtr->left;
+ y = graphPtr->inset;
+ if (graphPtr->title != NULL) {
+ y += graphPtr->titleHeight;
+ }
+ break;
+
+ case LEGEND_BOTTOM:
+ w = graphPtr->right - graphPtr->left;
+ h = graphPtr->bottomMargin.height - graphPtr->bottomMargin.axesOffset;
+ x = graphPtr->left;
+ y = graphPtr->bottom + graphPtr->bottomMargin.axesOffset;
+ break;
+
+ case LEGEND_PLOT:
+ w = graphPtr->right - graphPtr->left;
+ h = graphPtr->bottom - graphPtr->top;
+ x = graphPtr->left;
+ y = graphPtr->top;
+ break;
+
+ case LEGEND_XY:
+ w = legendPtr->width;
+ h = legendPtr->height;
+ x = legendPtr->xReq;
+ y = legendPtr->yReq;
+ if (x < 0) {
+ x += graphPtr->width;
+ }
+ if (y < 0) {
+ y += graphPtr->height;
+ }
+ break;
+
+ case LEGEND_WINDOW:
+ legendPtr->anchor = TK_ANCHOR_NW;
+ legendPtr->x = legendPtr->y = 0;
+ return;
+ }
+
+ switch (legendPtr->anchor) {
+ case TK_ANCHOR_NW: /* Upper left corner */
+ break;
+ case TK_ANCHOR_W: /* Left center */
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height) / 2;
+ }
+ break;
+ case TK_ANCHOR_SW: /* Lower left corner */
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height);
+ }
+ break;
+ case TK_ANCHOR_N: /* Top center */
+ if (w > legendPtr->width) {
+ x += (w - legendPtr->width) / 2;
+ }
+ break;
+ case TK_ANCHOR_CENTER: /* Center */
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height) / 2;
+ }
+ if (w > legendPtr->width) {
+ x += (w - legendPtr->width) / 2;
+ }
+ break;
+ case TK_ANCHOR_S: /* Bottom center */
+ if (w > legendPtr->width) {
+ x += (w - legendPtr->width) / 2;
+ }
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height);
+ }
+ break;
+ case TK_ANCHOR_NE: /* Upper right corner */
+ if (w > legendPtr->width) {
+ x += w - legendPtr->width;
+ }
+ break;
+ case TK_ANCHOR_E: /* Right center */
+ if (w > legendPtr->width) {
+ x += w - legendPtr->width;
+ }
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height) / 2;
+ }
+ break;
+ case TK_ANCHOR_SE: /* Lower right corner */
+ if (w > legendPtr->width) {
+ x += w - legendPtr->width;
+ }
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height);
+ }
+ break;
+ }
+ legendPtr->x = x + legendPtr->xPad;
+ legendPtr->y = y + legendPtr->yPad;
+}
-/*ARGSUSED*/
-static int
-CurselectionOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
+static int EntryIsSelected(Legend *legendPtr, Element *elemPtr)
{
- Legend *legendPtr = graphPtr->legend;
- Tcl_Obj *listObjPtr;
+ Tcl_HashEntry *hPtr;
- listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
- if (legendPtr->flags & SELECT_SORTED) {
- Blt_ChainLink link;
+ hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
+ return (hPtr != NULL);
+}
- for (link = Blt_Chain_FirstLink(legendPtr->selected); link != NULL;
- link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
- Tcl_Obj *objPtr;
+static void SelectElement(Legend *legendPtr, Element *elemPtr)
+{
+ int isNew;
+ Tcl_HashEntry *hPtr;
- elemPtr = Blt_Chain_GetValue(link);
- objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
- Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
- }
- } else {
- Blt_ChainLink link;
+ hPtr = Tcl_CreateHashEntry(&legendPtr->selectTable, (char *)elemPtr,&isNew);
+ if (isNew) {
+ Blt_ChainLink link;
- /* List of selected entries is in stacking order. */
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
+ link = Blt_Chain_Append(legendPtr->selected, elemPtr);
+ Tcl_SetHashValue(hPtr, link);
+ }
+}
- elemPtr = Blt_Chain_GetValue(link);
+static void DeselectElement(Legend *legendPtr, Element *elemPtr)
+{
+ Tcl_HashEntry *hPtr;
- if (EntryIsSelected(legendPtr, elemPtr)) {
- Tcl_Obj *objPtr;
+ hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
+ if (hPtr != NULL) {
+ Blt_ChainLink link;
- objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
- Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
- }
- }
- }
- Tcl_SetObjResult(interp, listObjPtr);
- return TCL_OK;
+ link = Tcl_GetHashValue(hPtr);
+ Blt_Chain_DeleteLink(legendPtr->selected, link);
+ Tcl_DeleteHashEntry(hPtr);
+ }
}
-/*ARGSUSED*/
-static int
-FocusOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+static void SelectEntry(Legend *legendPtr, Element *elemPtr)
{
- Legend *legendPtr = graphPtr->legend;
+ Tcl_HashEntry *hPtr;
- if (objc == 4) {
- Element *elemPtr;
+ switch (legendPtr->flags & SELECT_BLTMASK) {
+ case SELECT_CLEAR:
+ DeselectElement(legendPtr, elemPtr);
+ break;
- if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) {
- return TCL_ERROR;
- }
- if ((elemPtr != NULL) && (elemPtr != legendPtr->focusPtr)) {
- /* Changing focus can only affect the visible entries. The entry
- * layout stays the same. */
- legendPtr->focusPtr = elemPtr;
- }
- Blt_SetFocusItem(legendPtr->bindTable, legendPtr->focusPtr,
- CID_LEGEND_ENTRY);
- Blt_Legend_EventuallyRedraw(graphPtr);
- }
- if (legendPtr->focusPtr != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- legendPtr->focusPtr->obj.name, -1);
+ case SELECT_SET:
+ SelectElement(legendPtr, elemPtr);
+ break;
+
+ case SELECT_TOGGLE:
+ hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
+ if (hPtr != NULL) {
+ DeselectElement(legendPtr, elemPtr);
+ } else {
+ SelectElement(legendPtr, elemPtr);
}
- return TCL_OK;
+ break;
+ }
}
-/*
- *---------------------------------------------------------------------------
- *
- * GetOp --
- *
- * Find the legend entry from the given argument. The argument can be
- * either a screen position "@x,y" or the name of an element.
- *
- * I don't know how useful it is to test with the name of an element.
- *
- * Results:
- * A standard TCL result.
- *
- * Side Effects:
- * Graph will be redrawn to reflect the new legend attributes.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-GetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+static ClientData PickEntryProc(ClientData clientData, int x, int y,
+ ClientData *contextPtr)
{
- Legend *legendPtr = graphPtr->legend;
+ Graph *graphPtr = clientData;
+ Legend *legendPtr;
+ int w, h;
+
+ legendPtr = graphPtr->legend;
+ w = legendPtr->width;
+ h = legendPtr->height;
+
+ if (legendPtr->titleHeight > 0) {
+ y -= legendPtr->titleHeight + legendPtr->yPad;
+ }
+ x -= legendPtr->x + legendPtr->borderWidth;
+ y -= legendPtr->y + legendPtr->borderWidth;
+ w -= 2 * legendPtr->borderWidth + 2*legendPtr->xPad;
+ h -= 2 * legendPtr->borderWidth + 2*legendPtr->yPad;
+
+ if ((x >= 0) && (x < w) && (y >= 0) && (y < h)) {
+ int row, column;
+ int n;
- if (((legendPtr->flags & HIDE) == 0) && (legendPtr->nEntries > 0)) {
+ /*
+ * It's in the bounding box, so compute the index.
+ */
+ row = y / legendPtr->entryHeight;
+ column = x / legendPtr->entryWidth;
+ n = (column * legendPtr->nRows) + row;
+ if (n < legendPtr->nEntries) {
+ Blt_ChainLink link;
+ int count;
+
+ /* Legend entries are stored in bottom-to-top. */
+ count = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
Element *elemPtr;
- if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) {
- return TCL_ERROR;
- }
- if (elemPtr != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name,-1);
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label != NULL) {
+ if (count == n) {
+ return elemPtr;
+ }
+ count++;
}
+ }
+ if (link != NULL) {
+ return Blt_Chain_GetValue(link);
+ }
}
- return TCL_OK;
+ }
+ return NULL;
}
/*
*---------------------------------------------------------------------------
*
- * SelectionAnchorOp --
+ * Blt_MapLegend --
*
- * Sets the selection anchor to the element given by a index. The
- * selection anchor is the end of the selection that is fixed while
- * dragging out a selection with the mouse. The index "anchor" may be
- * used to refer to the anchor element.
+ * Calculates the dimensions (width and height) needed for the legend.
+ * Also determines the number of rows and columns necessary to list all
+ * the valid element labels.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * The selection changes.
+ * The following fields of the legend are calculated and set.
+ *
+ * nEntries - number of valid labels of elements in the
+ * display list.
+ * nRows - number of rows of entries
+ * nColumns - number of columns of entries
+ * entryHeight - height of each entry
+ * entryWidth - width of each entry
+ * height - width of legend (includes borders and padding)
+ * width - height of legend (includes borders and padding)
*
*---------------------------------------------------------------------------
*/
-/*ARGSUSED*/
-static int
-SelectionAnchorOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
+void Blt_MapLegend(Graph *graphPtr, int plotWidth, int plotHeight)
{
- Legend *legendPtr = graphPtr->legend;
+ Legend *legendPtr = graphPtr->legend;
+ Blt_ChainLink link;
+ int nRows, nColumns, nEntries;
+ int lw, lh;
+ int maxWidth, maxHeight;
+ int symbolWidth;
+ Tk_FontMetrics fontMetrics;
+
+ /* Initialize legend values to default (no legend displayed) */
+ legendPtr->entryWidth = legendPtr->entryHeight = 0;
+ legendPtr->nRows = legendPtr->nColumns = legendPtr->nEntries = 0;
+ legendPtr->height = legendPtr->width = 0;
+
+ if (legendPtr->site == LEGEND_WINDOW) {
+ if (Tk_Width(legendPtr->tkwin) > 1) {
+ plotWidth = Tk_Width(legendPtr->tkwin);
+ }
+ if (Tk_Height(legendPtr->tkwin) > 1) {
+ plotHeight = Tk_Height(legendPtr->tkwin);
+ }
+ }
+ Blt_Ts_GetExtents(&legendPtr->titleStyle, legendPtr->title,
+ &legendPtr->titleWidth, &legendPtr->titleHeight);
+ /*
+ * Count the number of legend entries and determine the widest and tallest
+ * label. The number of entries would normally be the number of elements,
+ * but elements can have no legend entry (-label "").
+ */
+ nEntries = 0;
+ maxWidth = maxHeight = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ unsigned int w, h;
Element *elemPtr;
- if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
- return TCL_ERROR;
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue; /* Element has no legend entry. */
}
- /* Set both the anchor and the mark. Indicates that a single entry
- * is selected. */
- legendPtr->selAnchorPtr = elemPtr;
- legendPtr->selMarkPtr = NULL;
- if (elemPtr != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name, -1);
+ Blt_Ts_GetExtents(&legendPtr->style, elemPtr->label, &w, &h);
+ if (maxWidth < w) {
+ maxWidth = w;
}
- Blt_Legend_EventuallyRedraw(graphPtr);
- return TCL_OK;
-}
+ if (maxHeight < h) {
+ maxHeight = h;
+ }
+ nEntries++;
+ }
+ if (nEntries == 0) {
+ return; /* No visible legend entries. */
+ }
-/*
- *---------------------------------------------------------------------------
- *
- * SelectionClearallOp
- *
- * Clears the entire selection.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The selection changes.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SelectionClearallOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
-{
- Legend *legendPtr = graphPtr->legend;
+ Tk_GetFontMetrics(legendPtr->style.font, &fontMetrics);
+ symbolWidth = 2 * fontMetrics.ascent;
- ClearSelection(legendPtr);
- return TCL_OK;
+ maxWidth += 2 * legendPtr->entryBW + 2*legendPtr->ixPad +
+ + symbolWidth + 3 * LABEL_PAD;
+
+ maxHeight += 2 * legendPtr->entryBW + 2*legendPtr->iyPad;
+
+ maxWidth |= 0x01;
+ maxHeight |= 0x01;
+
+ lw = plotWidth - 2 * legendPtr->borderWidth - 2*legendPtr->xPad;
+ lh = plotHeight - 2 * legendPtr->borderWidth - 2*legendPtr->yPad;
+
+ /*
+ * The number of rows and columns is computed as one of the following:
+ *
+ * both options set User defined.
+ * -rows Compute columns from rows.
+ * -columns Compute rows from columns.
+ * neither set Compute rows and columns from
+ * size of plot.
+ */
+ if (legendPtr->reqRows > 0) {
+ nRows = MIN(legendPtr->reqRows, nEntries);
+ if (legendPtr->reqColumns > 0) {
+ nColumns = MIN(legendPtr->reqColumns, nEntries);
+ } else {
+ nColumns = ((nEntries - 1) / nRows) + 1; /* Only -rows. */
+ }
+ } else if (legendPtr->reqColumns > 0) { /* Only -columns. */
+ nColumns = MIN(legendPtr->reqColumns, nEntries);
+ nRows = ((nEntries - 1) / nColumns) + 1;
+ } else {
+ /* Compute # of rows and columns from the legend size. */
+ nRows = lh / maxHeight;
+ nColumns = lw / maxWidth;
+ if (nRows < 1) {
+ nRows = nEntries;
+ }
+ if (nColumns < 1) {
+ nColumns = nEntries;
+ }
+ if (nRows > nEntries) {
+ nRows = nEntries;
+ }
+ switch (legendPtr->site) {
+ case LEGEND_TOP:
+ case LEGEND_BOTTOM:
+ nRows = ((nEntries - 1) / nColumns) + 1;
+ break;
+ case LEGEND_LEFT:
+ case LEGEND_RIGHT:
+ default:
+ nColumns = ((nEntries - 1) / nRows) + 1;
+ break;
+ }
+ }
+ if (nColumns < 1) {
+ nColumns = 1;
+ }
+ if (nRows < 1) {
+ nRows = 1;
+ }
+
+ lh = (nRows * maxHeight);
+ if (legendPtr->titleHeight > 0) {
+ lh += legendPtr->titleHeight + legendPtr->yPad;
+ }
+ lw = nColumns * maxWidth;
+ if (lw < legendPtr->titleWidth) {
+ lw = legendPtr->titleWidth;
+ }
+ legendPtr->width = lw + 2 * legendPtr->borderWidth +
+ 2*legendPtr->xPad;
+ legendPtr->height = lh + 2 * legendPtr->borderWidth +
+ 2*legendPtr->yPad;
+ legendPtr->nRows = nRows;
+ legendPtr->nColumns = nColumns;
+ legendPtr->nEntries = nEntries;
+ legendPtr->entryHeight = maxHeight;
+ legendPtr->entryWidth = maxWidth;
+
+ {
+ int row, col, count;
+
+ row = col = count = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ count++;
+ elemPtr->row = row;
+ elemPtr->col = col;
+ row++;
+ if ((count % nRows) == 0) {
+ col++;
+ row = 0;
+ }
+ }
+ }
+ if ((legendPtr->site == LEGEND_WINDOW) &&
+ ((Tk_ReqWidth(legendPtr->tkwin) != legendPtr->width) ||
+ (Tk_ReqHeight(legendPtr->tkwin) != legendPtr->height))) {
+ Tk_GeometryRequest(legendPtr->tkwin,legendPtr->width,legendPtr->height);
+ }
}
-/*
- *---------------------------------------------------------------------------
- *
- * SelectionIncludesOp
- *
- * Returns 1 if the element indicated by index is currently
- * selected, 0 if it isn't.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The selection changes.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SelectionIncludesOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
+void Blt_DrawLegend(Graph *graphPtr, Drawable drawable)
{
- Legend *legendPtr = graphPtr->legend;
- Element *elemPtr;
- int bool;
-
- if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
- return TCL_ERROR;
+ Blt_Background bg;
+ Blt_ChainLink link;
+ Tk_FontMetrics fontMetrics;
+ Legend *legendPtr = graphPtr->legend;
+ Pixmap pixmap;
+ Tk_Window tkwin;
+ int count;
+ int symbolSize, xMid, yMid;
+ int x, y, w, h;
+ int xLabel, yStart, xSymbol, ySymbol;
+
+ if ((legendPtr->hide) || (legendPtr->nEntries == 0)) {
+ return;
+ }
+
+ SetLegendOrigin(legendPtr);
+ graphPtr = legendPtr->graphPtr;
+ tkwin = legendPtr->tkwin;
+ if (legendPtr->site == LEGEND_WINDOW) {
+ w = Tk_Width(tkwin);
+ h = Tk_Height(tkwin);
+ } else {
+ w = legendPtr->width;
+ h = legendPtr->height;
+ }
+
+ pixmap = Tk_GetPixmap(graphPtr->display, Tk_WindowId(tkwin), w, h,
+ Tk_Depth(tkwin));
+
+ if (legendPtr->normalBg != NULL) {
+ Blt_FillBackgroundRectangle(tkwin, pixmap, legendPtr->normalBg, 0, 0,
+ w, h, 0, TK_RELIEF_FLAT);
+ } else if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
+ /*
+ * Legend background is transparent and is positioned over the the
+ * plot area. Either copy the part of the background from the backing
+ * store pixmap or (if no backing store exists) just fill it with the
+ * background color of the plot.
+ */
+ if (graphPtr->cache != None) {
+ XCopyArea(graphPtr->display, graphPtr->cache, pixmap,
+ graphPtr->drawGC, legendPtr->x, legendPtr->y, w, h, 0, 0);
+ } else {
+ Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->plotBg, 0, 0,
+ w, h, TK_RELIEF_FLAT, 0);
}
- bool = EntryIsSelected(legendPtr, elemPtr);
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
- return TCL_OK;
+ } else {
+ int xOrigin, yOrigin;
+ /*
+ * The legend is located in one of the margins or the external window.
+ */
+ Blt_GetBackgroundOrigin(graphPtr->normalBg, &xOrigin, &yOrigin);
+ Blt_SetBackgroundOrigin(graphPtr->tkwin, graphPtr->normalBg,
+ xOrigin - legendPtr->x,yOrigin - legendPtr->y);
+ Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->normalBg, 0, 0,
+ w, h, 0, TK_RELIEF_FLAT);
+ Blt_SetBackgroundOrigin(tkwin, graphPtr->normalBg, xOrigin, yOrigin);
+ }
+ Tk_GetFontMetrics(legendPtr->style.font, &fontMetrics);
+
+ symbolSize = fontMetrics.ascent;
+ xMid = symbolSize + 1 + legendPtr->entryBW;
+ yMid = (symbolSize / 2) + 1 + legendPtr->entryBW;
+ xLabel = 2 * symbolSize + legendPtr->entryBW +
+ legendPtr->ixPad + 2 * LABEL_PAD;
+ ySymbol = yMid + legendPtr->iyPad;
+ xSymbol = xMid + LABEL_PAD;
+
+ x = legendPtr->xPad + legendPtr->borderWidth;
+ y = legendPtr->yPad + legendPtr->borderWidth;
+ Blt_DrawText(tkwin, pixmap, legendPtr->title, &legendPtr->titleStyle, x, y);
+ if (legendPtr->titleHeight > 0) {
+ y += legendPtr->titleHeight + legendPtr->yPad;
+ }
+ count = 0;
+ yStart = y;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+ int isSelected;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue; /* Skip this entry */
+ }
+ isSelected = EntryIsSelected(legendPtr, elemPtr);
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ int xOrigin, yOrigin;
+
+ Blt_GetBackgroundOrigin(legendPtr->activeBg, &xOrigin, &yOrigin);
+ Blt_SetBackgroundOrigin(tkwin, legendPtr->activeBg,
+ xOrigin - legendPtr->x, yOrigin - legendPtr->y);
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->activeFgColor);
+ Blt_FillBackgroundRectangle(tkwin, pixmap, legendPtr->activeBg,
+ x, y, legendPtr->entryWidth, legendPtr->entryHeight,
+ legendPtr->entryBW, legendPtr->activeRelief);
+ Blt_SetBackgroundOrigin(tkwin, legendPtr->activeBg,
+ xOrigin, yOrigin);
+ } else if (isSelected) {
+ int xOrigin, yOrigin;
+ Blt_Background bg;
+ XColor *fg;
+
+ fg = (legendPtr->flags & FOCUS) ?
+ legendPtr->selInFocusFgColor : legendPtr->selOutFocusFgColor;
+ bg = (legendPtr->flags & FOCUS) ?
+ legendPtr->selInFocusBg : legendPtr->selOutFocusBg;
+ Blt_GetBackgroundOrigin(bg, &xOrigin, &yOrigin);
+ Blt_SetBackgroundOrigin(tkwin, bg, xOrigin - legendPtr->x,
+ yOrigin - legendPtr->y);
+ Blt_Ts_SetForeground(legendPtr->style, fg);
+ Blt_FillBackgroundRectangle(tkwin, pixmap, bg, x, y,
+ legendPtr->entryWidth, legendPtr->entryHeight,
+ legendPtr->selBW, legendPtr->selRelief);
+ Blt_SetBackgroundOrigin(tkwin, bg, xOrigin, yOrigin);
+ } else {
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->fgColor);
+ if (elemPtr->legendRelief != TK_RELIEF_FLAT) {
+ Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->normalBg,
+ x, y, legendPtr->entryWidth,
+ legendPtr->entryHeight, legendPtr->entryBW,
+ elemPtr->legendRelief);
+ }
+ }
+ (*elemPtr->procsPtr->drawSymbolProc) (graphPtr, pixmap, elemPtr,
+ x + xSymbol, y + ySymbol, symbolSize);
+ Blt_DrawText(tkwin, pixmap, elemPtr->label, &legendPtr->style,
+ x + xLabel,
+ y + legendPtr->entryBW + legendPtr->iyPad);
+ count++;
+ if (legendPtr->focusPtr == elemPtr) { /* Focus outline */
+ if (isSelected) {
+ XColor *color;
+
+ color = (legendPtr->flags & FOCUS) ?
+ legendPtr->selInFocusFgColor :
+ legendPtr->selOutFocusFgColor;
+ XSetForeground(graphPtr->display, legendPtr->focusGC,
+ color->pixel);
+ }
+ XDrawRectangle(graphPtr->display, pixmap, legendPtr->focusGC,
+ x + 1, y + 1, legendPtr->entryWidth - 3,
+ legendPtr->entryHeight - 3);
+ if (isSelected) {
+ XSetForeground(graphPtr->display, legendPtr->focusGC,
+ legendPtr->focusColor->pixel);
+ }
+ }
+ /* Check when to move to the next column */
+ if ((count % legendPtr->nRows) > 0) {
+ y += legendPtr->entryHeight;
+ } else {
+ x += legendPtr->entryWidth;
+ y = yStart;
+ }
+ }
+ /*
+ * Draw the border and/or background of the legend.
+ */
+ bg = legendPtr->normalBg;
+ if (bg == NULL) {
+ bg = graphPtr->normalBg;
+ }
+ /* Disable crosshairs before redisplaying to the screen */
+ if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
+ Blt_DisableCrosshairs(graphPtr);
+ }
+ Blt_DrawBackgroundRectangle(tkwin, pixmap, bg, 0, 0, w, h,
+ legendPtr->borderWidth, legendPtr->relief);
+ XCopyArea(graphPtr->display, pixmap, drawable, graphPtr->drawGC, 0, 0, w, h,
+ legendPtr->x, legendPtr->y);
+ if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
+ Blt_EnableCrosshairs(graphPtr);
+ }
+ Tk_FreePixmap(graphPtr->display, pixmap);
+ graphPtr->flags &= ~DRAW_LEGEND;
}
-/*
- *---------------------------------------------------------------------------
- *
- * SelectionMarkOp --
- *
- * Sets the selection mark to the element given by a index. The
- * selection anchor is the end of the selection that is movable while
- * dragging out a selection with the mouse. The index "mark" may be used
- * to refer to the anchor element.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The selection changes.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SelectionMarkOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
+void Blt_LegendToPostScript(Graph *graphPtr, Blt_Ps ps)
{
- Legend *legendPtr = graphPtr->legend;
+ Legend *legendPtr = graphPtr->legend;
+ double x, y, yStart;
+ int xLabel, xSymbol, ySymbol;
+ int count;
+ Blt_ChainLink link;
+ int symbolSize, xMid, yMid;
+ int width, height;
+ Tk_FontMetrics fontMetrics;
+
+ if ((legendPtr->hide) || (legendPtr->nEntries == 0)) {
+ return;
+ }
+ SetLegendOrigin(legendPtr);
+
+ x = legendPtr->x, y = legendPtr->y;
+ width = legendPtr->width - 2*legendPtr->xPad;
+ height = legendPtr->height - 2*legendPtr->yPad;
+
+ Blt_Ps_Append(ps, "% Legend\n");
+ graphPtr = legendPtr->graphPtr;
+ if (graphPtr->pageSetup->flags & PS_DECORATIONS) {
+ if (legendPtr->normalBg != NULL) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(legendPtr->normalBg);
+ Blt_Ps_Fill3DRectangle(ps, border, x, y, width, height,
+ legendPtr->borderWidth, legendPtr->relief);
+ } else {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(graphPtr->normalBg);
+ Blt_Ps_Draw3DRectangle(ps, border, x, y, width, height,
+ legendPtr->borderWidth, legendPtr->relief);
+ }
+ } else {
+ Blt_Ps_SetClearBackground(ps);
+ Blt_Ps_XFillRectangle(ps, x, y, width, height);
+ }
+ Tk_GetFontMetrics(legendPtr->style.font, &fontMetrics);
+ symbolSize = fontMetrics.ascent;
+ xMid = symbolSize + 1 + legendPtr->entryBW;
+ yMid = (symbolSize / 2) + 1 + legendPtr->entryBW;
+ xLabel = 2 * symbolSize + legendPtr->entryBW + legendPtr->ixPad + 5;
+ xSymbol = xMid + legendPtr->ixPad;
+ ySymbol = yMid + legendPtr->iyPad;
+
+ x += legendPtr->borderWidth;
+ y += legendPtr->borderWidth;
+ Blt_Ps_DrawText(ps, legendPtr->title, &legendPtr->titleStyle, x, y);
+ if (legendPtr->titleHeight > 0) {
+ y += legendPtr->titleHeight + legendPtr->yPad;
+ }
+
+ count = 0;
+ yStart = y;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
Element *elemPtr;
- if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
- return TCL_ERROR;
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue; /* Skip this label */
}
- if (legendPtr->selAnchorPtr == NULL) {
- Tcl_AppendResult(interp, "selection anchor must be set first",
- (char *)NULL);
- return TCL_ERROR;
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(legendPtr->activeBg);
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->activeFgColor);
+ Blt_Ps_Fill3DRectangle(ps, border, x, y, legendPtr->entryWidth,
+ legendPtr->entryHeight, legendPtr->entryBW,
+ legendPtr->activeRelief);
+ } else {
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->fgColor);
+ if (elemPtr->legendRelief != TK_RELIEF_FLAT) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(graphPtr->normalBg);
+ Blt_Ps_Draw3DRectangle(ps, border, x, y, legendPtr->entryWidth,
+ legendPtr->entryHeight, legendPtr->entryBW,
+ elemPtr->legendRelief);
+ }
+ }
+ (*elemPtr->procsPtr->printSymbolProc) (graphPtr, ps, elemPtr,
+ x + xSymbol, y + ySymbol, symbolSize);
+ Blt_Ps_DrawText(ps, elemPtr->label, &legendPtr->style,
+ x + xLabel, y + legendPtr->entryBW + legendPtr->iyPad);
+ count++;
+ if ((count % legendPtr->nRows) > 0) {
+ y += legendPtr->entryHeight;
+ } else {
+ x += legendPtr->entryWidth;
+ y = yStart;
}
- if (legendPtr->selMarkPtr != elemPtr) {
- Blt_ChainLink link, next;
+ }
+}
+
+static Element *GetNextRow(Graph *graphPtr, Element *focusPtr)
+{
+ Blt_ChainLink link;
+ int row, col;
- /* Deselect entry from the list all the way back to the anchor. */
- for (link = Blt_Chain_LastLink(legendPtr->selected); link != NULL;
- link = next) {
- Element *selectPtr;
+ col = focusPtr->col;
+ row = focusPtr->row + 1;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
- next = Blt_Chain_PrevLink(link);
- selectPtr = Blt_Chain_GetValue(link);
- if (selectPtr == legendPtr->selAnchorPtr) {
- break;
- }
- DeselectElement(legendPtr, selectPtr);
- }
- legendPtr->flags &= ~SELECT_BLTMASK;
- legendPtr->flags |= SELECT_SET;
- SelectRange(legendPtr, legendPtr->selAnchorPtr, elemPtr);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name, -1);
- legendPtr->selMarkPtr = elemPtr;
-
- Blt_Legend_EventuallyRedraw(graphPtr);
- if (legendPtr->selectCmd != NULL) {
- EventuallyInvokeSelectCmd(legendPtr);
- }
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
}
- return TCL_OK;
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr;
+ }
+ }
+ return NULL;
}
-/*
- *---------------------------------------------------------------------------
- *
- * SelectionPresentOp
- *
- * Returns 1 if there is a selection and 0 if it isn't.
- *
- * Results:
- * A standard TCL result. interp->result will contain a boolean string
- * indicating if there is a selection.
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SelectionPresentOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
+static Element *GetNextColumn(Graph *graphPtr, Element *focusPtr)
{
- Legend *legendPtr = graphPtr->legend;
- int bool;
+ Blt_ChainLink link;
+ int row, col;
- bool = (Blt_Chain_GetLength(legendPtr->selected) > 0);
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
- return TCL_OK;
+ col = focusPtr->col + 1;
+ row = focusPtr->row;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
+ }
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr; /* Don't go beyond legend boundaries. */
+ }
+ }
+ return NULL;
}
-/*
- *---------------------------------------------------------------------------
- *
- * SelectionSetOp
- *
- * Selects, deselects, or toggles all of the elements in the range
- * between first and last, inclusive, without affecting the selection
- * state of elements outside that range.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The selection changes.
- *
- * .g legend selection set first last
- *
- *---------------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SelectionSetOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
+static Element *GetPreviousRow(Graph *graphPtr, Element *focusPtr)
{
- Legend *legendPtr = graphPtr->legend;
- Element *firstPtr, *lastPtr;
- const char *string;
+ Blt_ChainLink link;
+ int row, col;
- legendPtr->flags &= ~SELECT_BLTMASK;
- string = Tcl_GetString(objv[3]);
- switch (string[0]) {
- case 's':
- legendPtr->flags |= SELECT_SET;
- break;
- case 'c':
- legendPtr->flags |= SELECT_CLEAR;
- break;
- case 't':
- legendPtr->flags |= SELECT_TOGGLE;
- break;
- }
- if (GetElementFromObj(graphPtr, objv[4], &firstPtr) != TCL_OK) {
- return TCL_ERROR;
+ col = focusPtr->col;
+ row = focusPtr->row - 1;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
}
- if ((firstPtr->flags & HIDE) && ((legendPtr->flags & SELECT_CLEAR)==0)) {
- Tcl_AppendResult(interp, "can't select hidden node \"",
- Tcl_GetString(objv[4]), "\"", (char *)NULL);
- return TCL_ERROR;
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr;
}
- lastPtr = firstPtr;
- if (objc > 5) {
- if (GetElementFromObj(graphPtr, objv[5], &lastPtr) != TCL_OK) {
- return TCL_ERROR;
- }
- if ((lastPtr->flags & HIDE) &&
- ((legendPtr->flags & SELECT_CLEAR) == 0)) {
- Tcl_AppendResult(interp, "can't select hidden node \"",
- Tcl_GetString(objv[5]), "\"", (char *)NULL);
- return TCL_ERROR;
- }
- }
- if (firstPtr == lastPtr) {
- SelectEntry(legendPtr, firstPtr);
- } else {
- SelectRange(legendPtr, firstPtr, lastPtr);
+ }
+ return NULL;
+}
+
+static Element *GetPreviousColumn(Graph *graphPtr, Element *focusPtr)
+{
+ Blt_ChainLink link;
+ int row, col;
+
+ col = focusPtr->col - 1;
+ row = focusPtr->row;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
}
- /* Set both the anchor and the mark. Indicates that a single entry is
- * selected. */
- if (legendPtr->selAnchorPtr == NULL) {
- legendPtr->selAnchorPtr = firstPtr;
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr;
}
- if (legendPtr->flags & SELECT_EXPORT) {
- Tk_OwnSelection(legendPtr->tkwin, XA_PRIMARY, LostSelectionProc,
- legendPtr);
+ }
+ return NULL;
+}
+
+static Element *GetFirstElement(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label != NULL) {
+ return elemPtr;
}
- Blt_Legend_EventuallyRedraw(graphPtr);
- if (legendPtr->selectCmd != NULL) {
- EventuallyInvokeSelectCmd(legendPtr);
+ }
+ return NULL;
+}
+
+static Element *GetLastElement(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label != NULL) {
+ return elemPtr;
}
- return TCL_OK;
+ }
+ return NULL;
}
/*
*---------------------------------------------------------------------------
*
- * SelectionOp --
+ * GetElementFromObj --
*
- * This procedure handles the individual options for text selections.
- * The selected text is designated by start and end indices into the text
- * pool. The selected segment has both a anchored and unanchored ends.
+ * Parse an index into an entry and return either its value or an error.
*
* Results:
- * None.
+ * A standard TCL result. If all went well, then *indexPtr is filled in
+ * with the character index (into entryPtr) corresponding to string. The
+ * index value is guaranteed to lie between 0 and the number of characters
+ * in the string, inclusive. If an error occurs then an error message is
+ * left in the interp's result.
*
* Side effects:
- * The selection changes.
+ * None.
*
- * .g legend selection anchor
*---------------------------------------------------------------------------
*/
-static Blt_OpSpec selectionOps[] =
+static int GetElementFromObj(Graph *graphPtr, Tcl_Obj *objPtr,
+ Element **elemPtrPtr)
{
- {"anchor", 1, SelectionAnchorOp, 5, 5, "elem",},
- {"clear", 5, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
- {"clearall", 6, SelectionClearallOp, 4, 4, "",},
- {"includes", 1, SelectionIncludesOp, 5, 5, "elem",},
- {"mark", 1, SelectionMarkOp, 5, 5, "elem",},
- {"present", 1, SelectionPresentOp, 4, 4, "",},
- {"set", 1, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
- {"toggle", 1, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
-};
-static int nSelectionOps = sizeof(selectionOps) / sizeof(Blt_OpSpec);
-
-static int
-SelectionOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
-{
- GraphLegendProc *proc;
- int result;
-
- proc = Blt_GetOpFromObj(interp, nSelectionOps, selectionOps, BLT_OP_ARG3,
- objc, objv, 0);
- if (proc == NULL) {
- return TCL_ERROR;
- }
- result = (*proc) (graphPtr, interp, objc, objv);
- return result;
+ Element *elemPtr;
+ Legend *legendPtr;
+ Tcl_Interp *interp;
+ char c;
+ const char *string;
+ int last;
+
+ legendPtr = graphPtr->legend;
+ interp = graphPtr->interp;
+ string = Tcl_GetString(objPtr);
+ c = string[0];
+ elemPtr = NULL;
+
+ last = Blt_Chain_GetLength(graphPtr->elements.displayList) - 1;
+ if ((c == 'a') && (strcmp(string, "anchor") == 0)) {
+ elemPtr = legendPtr->selAnchorPtr;
+ } else if ((c == 'c') && (strcmp(string, "current") == 0)) {
+ elemPtr = (Element *)Blt_GetCurrentItem(legendPtr->bindTable);
+ } else if ((c == 'f') && (strcmp(string, "first") == 0)) {
+ elemPtr = GetFirstElement(graphPtr);
+ } else if ((c == 'f') && (strcmp(string, "focus") == 0)) {
+ elemPtr = legendPtr->focusPtr;
+ } else if ((c == 'l') && (strcmp(string, "last") == 0)) {
+ elemPtr = GetLastElement(graphPtr);
+ } else if ((c == 'e') && (strcmp(string, "end") == 0)) {
+ elemPtr = GetLastElement(graphPtr);
+ } else if ((c == 'n') && (strcmp(string, "next.row") == 0)) {
+ elemPtr = GetNextRow(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 'n') && (strcmp(string, "next.column") == 0)) {
+ elemPtr = GetNextColumn(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 'p') && (strcmp(string, "previous.row") == 0)) {
+ elemPtr = GetPreviousRow(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 'p') && (strcmp(string, "previous.column") == 0)) {
+ elemPtr = GetPreviousColumn(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 's') && (strcmp(string, "sel.first") == 0)) {
+ elemPtr = legendPtr->selFirstPtr;
+ } else if ((c == 's') && (strcmp(string, "sel.last") == 0)) {
+ elemPtr = legendPtr->selLastPtr;
+ } else if (c == '@') {
+ int x, y;
+
+ if (Blt_GetXY(interp, legendPtr->tkwin, string, &x, &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ elemPtr = (Element *)PickEntryProc(graphPtr, x, y, NULL);
+ } else {
+ if (Blt_GetElement(interp, graphPtr, objPtr, &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (elemPtr->link == NULL) {
+ Tcl_AppendResult(interp, "bad legend index \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (elemPtr->label == NULL) {
+ elemPtr = NULL;
+ }
+ }
+ *elemPtrPtr = elemPtr;
+ return TCL_OK;
}
/*
*---------------------------------------------------------------------------
*
- * Blt_LegendOp --
+ * SelectRange --
*
- * Results:
- * A standard TCL result.
+ * Sets the selection flag for a range of nodes. The range is determined
+ * by two pointers which designate the first/last nodes of the range.
*
- * Side Effects:
- * Legend is possibly redrawn.
+ * Results:
+ * Always returns TCL_OK.
*
*---------------------------------------------------------------------------
*/
-
-static Blt_OpSpec legendOps[] =
+static int SelectRange(Legend *legendPtr, Element *fromPtr, Element *toPtr)
{
- {"activate", 1, ActivateOp, 3, 0, "?pattern?...",},
- {"bind", 1, BindOp, 3, 6, "elem sequence command",},
- {"cget", 2, CgetOp, 4, 4, "option",},
- {"configure", 2, ConfigureOp, 3, 0, "?option value?...",},
- {"curselection", 2, CurselectionOp, 3, 3, "",},
- {"deactivate", 1, ActivateOp, 3, 0, "?pattern?...",},
- {"focus", 1, FocusOp, 4, 4, "elem",},
- {"get", 1, GetOp, 4, 4, "elem",},
- // {"icon", 1, IconOp, 5, 5, "elem image",},
- {"selection", 1, SelectionOp, 3, 0, "args"},
-};
-static int nLegendOps = sizeof(legendOps) / sizeof(Blt_OpSpec);
-int
-Blt_LegendOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
- Tcl_Obj *const *objv)
-{
- GraphLegendProc *proc;
+ if (Blt_Chain_IsBefore(fromPtr->link, toPtr->link)) {
+ Blt_ChainLink link;
- proc = Blt_GetOpFromObj(interp, nLegendOps, legendOps, BLT_OP_ARG2,
- objc, objv,0);
- if (proc == NULL) {
- return TCL_ERROR;
+ for (link = fromPtr->link; link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ SelectEntry(legendPtr, elemPtr);
+ if (link == toPtr->link) {
+ break;
+ }
}
- return (*proc) (graphPtr, interp, objc, objv);
+ } else {
+ Blt_ChainLink link;
+
+ for (link = fromPtr->link; link != NULL;
+ link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ SelectEntry(legendPtr, elemPtr);
+ if (link == toPtr->link) {
+ break;
+ }
+ }
+ }
+ return TCL_OK;
}
-int
-Blt_Legend_Site(Graph *graphPtr)
+int Blt_Legend_Site(Graph *graphPtr)
{
return graphPtr->legend->site;
}
-int
-Blt_Legend_Width(Graph *graphPtr)
+int Blt_Legend_Width(Graph *graphPtr)
{
return graphPtr->legend->width;
}
-int
-Blt_Legend_Height(Graph *graphPtr)
+int Blt_Legend_Height(Graph *graphPtr)
{
return graphPtr->legend->height;
}
-int
-Blt_Legend_IsHidden(Graph *graphPtr)
+int Blt_Legend_IsHidden(Graph *graphPtr)
{
- return (graphPtr->legend->flags & HIDE);
+ return (graphPtr->legend->hide);
}
-int
-Blt_Legend_IsRaised(Graph *graphPtr)
+int Blt_Legend_IsRaised(Graph *graphPtr)
{
- return (graphPtr->legend->flags & RAISED);
+ return 0;
}
-int
-Blt_Legend_X(Graph *graphPtr)
+int Blt_Legend_X(Graph *graphPtr)
{
return graphPtr->legend->x;
}
-int
-Blt_Legend_Y(Graph *graphPtr)
+int Blt_Legend_Y(Graph *graphPtr)
{
return graphPtr->legend->y;
}
-void
-Blt_Legend_RemoveElement(Graph *graphPtr, Element *elemPtr)
+void Blt_Legend_RemoveElement(Graph *graphPtr, Element *elemPtr)
{
Blt_DeleteBindings(graphPtr->legend->bindTable, elemPtr);
}
@@ -2734,62 +2318,53 @@ Blt_Legend_RemoveElement(Graph *graphPtr, Element *elemPtr)
*
*---------------------------------------------------------------------------
*/
-static int
-SelectionProc(
- ClientData clientData, /* Information about the widget. */
- int offset, /* Offset within selection of first
- * character to be returned. */
- char *buffer, /* Location in which to place
- * selection. */
- int maxBytes) /* Maximum number of bytes to place at
- * buffer, not including terminating
- * NULL character. */
+static int SelectionProc(ClientData clientData, int offset,
+ char *buffer, int maxBytes)
{
- Legend *legendPtr = clientData;
- int nBytes;
- Tcl_DString dString;
+ Legend *legendPtr = clientData;
+ int nBytes;
+ Tcl_DString dString;
+
+ if ((legendPtr->exportSelection) == 0) {
+ return -1;
+ }
+ /* Retrieve the names of the selected entries. */
+ Tcl_DStringInit(&dString);
+ if (legendPtr->flags & SELECT_SORTED) {
+ Blt_ChainLink link;
- if ((legendPtr->flags & SELECT_EXPORT) == 0) {
- return -1;
- }
- /* Retrieve the names of the selected entries. */
- Tcl_DStringInit(&dString);
- if (legendPtr->flags & SELECT_SORTED) {
- Blt_ChainLink link;
+ for (link = Blt_Chain_FirstLink(legendPtr->selected);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
- for (link = Blt_Chain_FirstLink(legendPtr->selected);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
+ elemPtr = Blt_Chain_GetValue(link);
+ Tcl_DStringAppend(&dString, elemPtr->obj.name, -1);
+ Tcl_DStringAppend(&dString, "\n", -1);
+ }
+ } else {
+ Blt_ChainLink link;
+ Graph *graphPtr;
- elemPtr = Blt_Chain_GetValue(link);
- Tcl_DStringAppend(&dString, elemPtr->obj.name, -1);
- Tcl_DStringAppend(&dString, "\n", -1);
- }
- } else {
- Blt_ChainLink link;
- Graph *graphPtr;
-
- graphPtr = legendPtr->graphPtr;
- /* List of selected entries is in stacking order. */
- for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
- link != NULL; link = Blt_Chain_NextLink(link)) {
- Element *elemPtr;
+ graphPtr = legendPtr->graphPtr;
+ /* List of selected entries is in stacking order. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
- elemPtr = Blt_Chain_GetValue(link);
- if (EntryIsSelected(legendPtr, elemPtr)) {
- Tcl_DStringAppend(&dString, elemPtr->obj.name, -1);
- Tcl_DStringAppend(&dString, "\n", -1);
- }
- }
- }
- nBytes = Tcl_DStringLength(&dString) - offset;
- strncpy(buffer, Tcl_DStringValue(&dString) + offset, maxBytes);
- Tcl_DStringFree(&dString);
- buffer[maxBytes] = '\0';
- return MIN(nBytes, maxBytes);
+ elemPtr = Blt_Chain_GetValue(link);
+ if (EntryIsSelected(legendPtr, elemPtr)) {
+ Tcl_DStringAppend(&dString, elemPtr->obj.name, -1);
+ Tcl_DStringAppend(&dString, "\n", -1);
+ }
+ }
+ }
+ nBytes = Tcl_DStringLength(&dString) - offset;
+ strncpy(buffer, Tcl_DStringValue(&dString) + offset, maxBytes);
+ Tcl_DStringFree(&dString);
+ buffer[maxBytes] = '\0';
+ return MIN(nBytes, maxBytes);
}
-
/*
*---------------------------------------------------------------------------
*
@@ -2807,23 +2382,22 @@ SelectionProc(
*
*---------------------------------------------------------------------------
*/
-static void
-BlinkCursorProc(ClientData clientData)
+static void BlinkCursorProc(ClientData clientData)
{
- Graph *graphPtr = clientData;
- Legend *legendPtr;
-
- legendPtr = graphPtr->legend;
- if (!(legendPtr->flags & FOCUS) || (legendPtr->offTime == 0)) {
- return;
- }
- if (legendPtr->active) {
- int time;
-
- legendPtr->cursorOn ^= 1;
- time = (legendPtr->cursorOn) ? legendPtr->onTime : legendPtr->offTime;
- legendPtr->timerToken = Tcl_CreateTimerHandler(time, BlinkCursorProc,
- graphPtr);
- Blt_Legend_EventuallyRedraw(graphPtr);
- }
+ Graph *graphPtr = clientData;
+ Legend *legendPtr;
+
+ legendPtr = graphPtr->legend;
+ if (!(legendPtr->flags & FOCUS) || (legendPtr->offTime == 0)) {
+ return;
+ }
+ if (legendPtr->active) {
+ int time;
+
+ legendPtr->cursorOn ^= 1;
+ time = (legendPtr->cursorOn) ? legendPtr->onTime : legendPtr->offTime;
+ legendPtr->timerToken = Tcl_CreateTimerHandler(time, BlinkCursorProc,
+ graphPtr);
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
}
diff --git a/src/bltGrLegd.h b/src/bltGrLegd.h
index 7dcb0df..d46f630 100644
--- a/src/bltGrLegd.h
+++ b/src/bltGrLegd.h
@@ -48,7 +48,11 @@
#define LEGEND_PLOTAREA_MASK (LEGEND_PLOT | LEGEND_XY)
extern int Blt_CreateLegend(Graph *graphPtr);
+extern int Blt_ConfigureObjLegend(Graph *graphPtr,
+ int objc, Tcl_Obj* const objv[]);
+extern void Blt_DeleteLegend(Graph* graphPtr);
extern void Blt_DestroyLegend(Graph *graphPtr);
+
extern void Blt_DrawLegend(Graph *graphPtr, Drawable drawable);
extern void Blt_MapLegend(Graph *graphPtr, int width, int height);
extern int Blt_LegendOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
diff --git a/src/bltGraph.C b/src/bltGraph.C
index 6f78cb4..6ff51c6 100644
--- a/src/bltGraph.C
+++ b/src/bltGraph.C
@@ -107,7 +107,8 @@ static const char* objectClassNames[] = {
#define DEF_GRAPH_TITLE_COLOR STD_NORMAL_FOREGROUND
#define DEF_GRAPH_WIDTH "5i"
-static char* barmodeObjOption[] = {"normal", "stacked", "aligned", "overlap"};
+static char* barmodeObjOption[] =
+ {"normal", "stacked", "aligned", "overlap", NULL};
static Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_DOUBLE, "-aspect", "aspect", "Aspect",
@@ -387,10 +388,11 @@ static int NewGraph(ClientData clientData, Tcl_Interp*interp,
PickEntry, Blt_GraphTags);
if (Blt_CreateCrosshairs(graphPtr) != TCL_OK)
goto error;
- if (Blt_CreatePageSetup(graphPtr) != TCL_OK)
- goto error;
if (Blt_CreateLegend(graphPtr) != TCL_OK)
goto error;
+
+ if (Blt_CreatePageSetup(graphPtr) != TCL_OK)
+ goto error;
if (Blt_CreatePen(graphPtr, "activeLine", CID_ELEM_LINE, 0, NULL) == NULL)
goto error;
if (Blt_CreatePen(graphPtr, "activeBar", CID_ELEM_BAR, 0, NULL) == NULL)
@@ -406,10 +408,11 @@ static int NewGraph(ClientData clientData, Tcl_Interp*interp,
if (Blt_ConfigureObjCrosshairs(graphPtr, objc, objv) != TCL_OK)
goto error;
+ if (Blt_ConfigureObjLegend(graphPtr, objc, objv) != TCL_OK)
+ goto error;
+
if (Blt_ConfigurePageSetup(graphPtr) != TCL_OK)
goto error;
- Blt_ConfigureLegend(graphPtr);
-
if (Blt_DefaultAxes(graphPtr) != TCL_OK)
goto error;
AdjustAxisPointers(graphPtr);
@@ -572,10 +575,6 @@ static void ConfigureGraph(Graph* graphPtr)
Tk_FreePixmap(graphPtr->display, graphPtr->cache);
graphPtr->cache = None;
}
-
- // Reconfigure the crosshairs, just in case the background color of the
- // plotarea has been changed.
- // Blt_ConfigureCrosshairs(graphPtr);
}
static void DisplayGraph(ClientData clientData)
@@ -709,6 +708,7 @@ static void GraphEventProc(ClientData clientData, XEvent* eventPtr)
Tk_FreeConfigOptions((char*)graphPtr, graphPtr->optionTable,
graphPtr->tkwin);
Blt_DeleteCrosshairs(graphPtr);
+ Blt_DeleteLegend(graphPtr);
graphPtr->tkwin = NULL;
Tcl_DeleteCommandFromToken(graphPtr->interp, graphPtr->cmdToken);
@@ -743,7 +743,7 @@ static void DestroyGraph(char* dataPtr)
Blt_DestroyCrosshairs(graphPtr);
Blt_DestroyMarkers(graphPtr);
- Blt_DestroyElements(graphPtr);
+ Blt_DestroyElements(graphPtr); // must come before legend and others
Blt_DestroyLegend(graphPtr);
Blt_DestroyAxes(graphPtr);
Blt_DestroyPens(graphPtr);
@@ -1448,8 +1448,8 @@ int Blt_GraphType(Graph* graphPtr)
void Blt_ReconfigureGraph(Graph* graphPtr)
{
ConfigureGraph(graphPtr);
- Blt_ConfigureLegend(graphPtr);
- Blt_ConfigureElements(graphPtr);
- Blt_ConfigureAxes(graphPtr);
- Blt_ConfigureMarkers(graphPtr);
+ // Blt_ConfigureLegend(graphPtr);
+ // Blt_ConfigureElements(graphPtr);
+ // Blt_ConfigureAxes(graphPtr);
+ // Blt_ConfigureMarkers(graphPtr);
}
diff --git a/src/bltGraph.h b/src/bltGraph.h
index 0d83e4e..2c8cd8a 100644
--- a/src/bltGraph.h
+++ b/src/bltGraph.h
@@ -534,10 +534,6 @@ extern int Blt_PolyRectClip(Region2d *extsPtr, Point2d *inputPts,
extern void Blt_ComputeBarStacks(Graph *graphPtr);
-extern void Blt_ConfigureLegend(Graph *graphPtr);
-extern void Blt_ConfigureElements(Graph *graphPtr);
-extern void Blt_ConfigureAxes(Graph *graphPtr);
-extern void Blt_ConfigureMarkers(Graph *graphPtr);
extern void Blt_ReconfigureGraph(Graph *graphPtr);
extern void Blt_DestroyAxes(Graph *graphPtr);