diff options
author | joye <joye> | 2014-04-08 18:50:10 (GMT) |
---|---|---|
committer | joye <joye> | 2014-04-08 18:50:10 (GMT) |
commit | e9b261c35ce151313f26402ab0dcbb104f3523b5 (patch) | |
tree | 196aac8d5ff03b2ad04cae4696167b0d9a5aeb7f /src | |
parent | 73f434743c46ad0f281c488e1912ea96cc48c77e (diff) | |
download | blt-e9b261c35ce151313f26402ab0dcbb104f3523b5.zip blt-e9b261c35ce151313f26402ab0dcbb104f3523b5.tar.gz blt-e9b261c35ce151313f26402ab0dcbb104f3523b5.tar.bz2 |
*** empty log message ***
Diffstat (limited to 'src')
-rw-r--r-- | src/bltGrLegd.C | 551 | ||||
-rw-r--r-- | src/bltGrLegd.h | 16 | ||||
-rw-r--r-- | src/bltGrLegdOp.C | 527 | ||||
-rw-r--r-- | src/bltGraph.C | 4 |
4 files changed, 555 insertions, 543 deletions
diff --git a/src/bltGrLegd.C b/src/bltGrLegd.C index c85bd86..ea8a781 100644 --- a/src/bltGrLegd.C +++ b/src/bltGrLegd.C @@ -37,22 +37,6 @@ extern "C" { #include "bltGrElem.h" #include "bltGrElemOp.h" -// Selection related flags: -// SELECT_PENDING A "selection" command idle task is pending. -// SELECT_CLEAR Clear selection flag of entry. -// SELECT_SET Set selection flag of entry. -// SELECT_TOGGLE Toggle selection flag of entry. -// Mask of selection set/clear/toggle flags. -// SELECT_SORTED Indicates if the entries in the selection -// should be sorted or displayed in the order -// they were selected. - -#define SELECT_CLEAR (1<<24) -#define SELECT_PENDING (1<<25) -#define SELECT_SET (1<<26) -#define SELECT_SORTED (1<<27) -#define SELECT_TOGGLE (SELECT_SET | SELECT_CLEAR) - #define LABEL_PAD 2 // Defs @@ -61,19 +45,9 @@ extern "C" { Tcl_ObjCmdProc Blt_GraphInstCmdProc; }; -static int SelectionOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]); -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); +extern int EntryIsSelected(Legend* legendPtr, Element* elemPtr); +extern void DeselectElement(Legend* legendPtr, Element* elemPtr); +extern void SelectEntry(Legend* legendPtr, Element* elemPtr); static int CreateLegendWindow(Tcl_Interp* interp, Legend* legendPtr, const char *pathName); @@ -81,12 +55,8 @@ static Tcl_IdleProc DisplayLegend; static Blt_BindPickProc PickEntryProc; static Tk_EventProc LegendEventProc; static Tcl_TimerProc BlinkCursorProc; -static Tk_LostSelProc LostSelectionProc; static Tk_SelectionProc SelectionProc; -typedef int (GraphLegendProc)(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]); - // OptionSpecs static const char* selectmodeObjOption[] = {"single", "multiple", NULL}; @@ -420,88 +390,7 @@ static void LegendEventProc(ClientData clientData, XEvent *eventPtr) // Configure -static int CgetOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - 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 int ConfigureOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - 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 int LegendObjConfigure(Tcl_Interp* interp, Graph* graphPtr, - int objc, Tcl_Obj* const objv[]) -{ - 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); - } - - graphPtr->flags |= mask; - graphPtr->flags |= (RESET_WORLD | CACHE_DIRTY); - ConfigureLegend(graphPtr); - Blt_EventuallyRedrawGraph(graphPtr); - - break; - } - - if (!error) { - Tk_FreeSavedOptions(&savedOptions); - return TCL_OK; - } - else { - Tcl_SetObjResult(interp, errorResult); - Tcl_DecrRefCount(errorResult); - return TCL_ERROR; - } -} - -static void ConfigureLegend(Graph* graphPtr) +void ConfigureLegend(Graph* graphPtr) { Legend* legendPtr = graphPtr->legend; @@ -522,384 +411,6 @@ static void ConfigureLegend(Graph* graphPtr) legendPtr->focusGC = newGC; } -// Ops - -static int ActivateOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - 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 = 0; - 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 = (Element*)Blt_Chain_GetValue(link); - if (Tcl_StringMatch(elemPtr->name(), pattern)) { - fprintf(stderr, "legend %s(%s) %s is currently %d\n", - string, pattern, elemPtr->name(), - (elemPtr->flags & LABEL_ACTIVE)); - if (active) { - if ((elemPtr->flags & LABEL_ACTIVE) == 0) { - elemPtr->flags |= LABEL_ACTIVE; - redraw = 1; - } - } else { - if (elemPtr->flags & LABEL_ACTIVE) { - elemPtr->flags &= ~LABEL_ACTIVE; - redraw = 1; - } - } - fprintf(stderr, "legend %s(%s) %s is now %d\n", - string, pattern, elemPtr->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 = (Element*)Blt_Chain_GetValue(link); - if (elemPtr->flags & LABEL_ACTIVE) { - Tcl_Obj *objPtr; - - objPtr = Tcl_NewStringObj(elemPtr->name(), -1); - Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); - } - } - Tcl_SetObjResult(interp, listObjPtr); - } - return TCL_OK; -} - -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; - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL); - for (hPtr = Tcl_FirstHashEntry(&graphPtr->elements.tagTable, &iter); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&iter)) { - const char *tagName = - (const char*)Tcl_GetHashKey(&graphPtr->elements.tagTable, hPtr); - Tcl_Obj *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); -} - -static int CurselectionOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - Legend* legendPtr = graphPtr->legend; - Tcl_Obj *listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL); - if (legendPtr->flags & SELECT_SORTED) { - Blt_ChainLink link; - - for (link = Blt_Chain_FirstLink(legendPtr->selected); link != NULL; - link = Blt_Chain_NextLink(link)) { - Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - Tcl_Obj *objPtr = Tcl_NewStringObj(elemPtr->name(), -1); - Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); - } - } - else { - /* List of selected entries is in stacking order. */ - for (Blt_ChainLink link = Blt_Chain_FirstLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_NextLink(link)) { - Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - - if (EntryIsSelected(legendPtr, elemPtr)) { - Tcl_Obj *objPtr; - - objPtr = Tcl_NewStringObj(elemPtr->name(), -1); - Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); - } - } - } - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -static int FocusOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - Legend* legendPtr = graphPtr->legend; - - if (objc == 4) { - Element* elemPtr; - - 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) { - Tcl_SetStringObj(Tcl_GetObjResult(interp), - legendPtr->focusPtr->name(), -1); - } - return TCL_OK; -} - -static int GetOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - Legend* legendPtr = graphPtr->legend; - - if (((legendPtr->hide) == 0) && (legendPtr->nEntries > 0)) { - Element* elemPtr; - - if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) { - return TCL_ERROR; - } - if (elemPtr) { - Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->name(),-1); - } - } - return TCL_OK; -} - -static Blt_OpSpec legendOps[] = - { - {"activate", 1, (void*)ActivateOp, 3, 0, "?pattern?...",}, - {"bind", 1, (void*)BindOp, 3, 6, "elem sequence command",}, - {"cget", 2, (void*)CgetOp, 4, 4, "option",}, - {"configure", 2, (void*)ConfigureOp, 3, 0, "?option value?...",}, - {"curselection", 2, (void*)CurselectionOp, 3, 3, "",}, - {"deactivate", 1, (void*)ActivateOp, 3, 0, "?pattern?...",}, - {"focus", 1, (void*)FocusOp, 4, 4, "elem",}, - {"get", 1, (void*)GetOp, 4, 4, "elem",}, - {"selection", 1, (void*)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 = (GraphLegendProc*)Blt_GetOpFromObj(interp, nLegendOps, legendOps, BLT_OP_ARG2, objc, objv,0); - if (proc == NULL) - return TCL_ERROR; - - return (*proc)(graphPtr, interp, objc, objv); -} - -// Selection Widget Ops - -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) { - Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->name(), -1); - } - Blt_Legend_EventuallyRedraw(graphPtr); - return TCL_OK; -} - -static int SelectionClearallOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - Legend* legendPtr = graphPtr->legend; - - ClearSelection(legendPtr); - return TCL_OK; -} - -static int SelectionIncludesOp(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; - - int boo = EntryIsSelected(legendPtr, elemPtr); - Tcl_SetBooleanObj(Tcl_GetObjResult(interp), boo); - return TCL_OK; -} - -static int SelectionMarkOp(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; - } - 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) { - next = Blt_Chain_PrevLink(link); - Element *selectPtr = (Element*)Blt_Chain_GetValue(link); - if (selectPtr == legendPtr->selAnchorPtr) { - break; - } - DeselectElement(legendPtr, selectPtr); - } - legendPtr->flags &= ~SELECT_TOGGLE; - legendPtr->flags |= SELECT_SET; - SelectRange(legendPtr, legendPtr->selAnchorPtr, elemPtr); - Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->name(), -1); - legendPtr->selMarkPtr = elemPtr; - - Blt_Legend_EventuallyRedraw(graphPtr); - if (legendPtr->selectCmd) { - EventuallyInvokeSelectCmd(legendPtr); - } - } - return TCL_OK; -} - -static int SelectionPresentOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - Legend* legendPtr = graphPtr->legend; - int boo = (Blt_Chain_GetLength(legendPtr->selected) > 0); - Tcl_SetBooleanObj(Tcl_GetObjResult(interp), boo); - return TCL_OK; -} - -static int SelectionSetOp(Graph* graphPtr, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[]) -{ - Legend* legendPtr = graphPtr->legend; - Element *firstPtr, *lastPtr; - const char *string; - - legendPtr->flags &= ~SELECT_TOGGLE; - 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->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->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) { - EventuallyInvokeSelectCmd(legendPtr); - } - return TCL_OK; -} - -static Blt_OpSpec selectionOps[] = - { - {"anchor", 1, (void*)SelectionAnchorOp, 5, 5, "elem",}, - {"clear", 5, (void*)SelectionSetOp, 5, 6, "firstElem ?lastElem?",}, - {"clearall", 6, (void*)SelectionClearallOp, 4, 4, "",}, - {"includes", 1, (void*)SelectionIncludesOp, 5, 5, "elem",}, - {"mark", 1, (void*)SelectionMarkOp, 5, 5, "elem",}, - {"present", 1, (void*)SelectionPresentOp, 4, 4, "",}, - {"set", 1, (void*)SelectionSetOp, 5, 6, "firstElem ?lastElem?",}, - {"toggle", 1, (void*)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 = (GraphLegendProc*)Blt_GetOpFromObj(interp, nSelectionOps, selectionOps, BLT_OP_ARG3, objc, objv, 0); - if (proc == NULL) - return TCL_ERROR; - - return (*proc)(graphPtr, interp, objc, objv); -} - // Support static void DisplayLegend(ClientData clientData) @@ -936,50 +447,6 @@ void Blt_Legend_EventuallyRedraw(Graph* graphPtr) } } -static void SelectCmdProc(ClientData clientData) -{ - Legend* legendPtr = (Legend*)clientData; - - Tcl_Preserve(legendPtr); - legendPtr->flags &= ~SELECT_PENDING; - if (legendPtr->selectCmd) { - Tcl_Interp* interp; - - interp = legendPtr->graphPtr->interp; - if (Tcl_GlobalEval(interp, legendPtr->selectCmd) != TCL_OK) { - Tcl_BackgroundError(interp); - } - } - Tcl_Release(legendPtr); -} - -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) { - EventuallyInvokeSelectCmd(legendPtr); - } -} - -static void LostSelectionProc(ClientData clientData) -{ - Legend* legendPtr = (Legend*)clientData; - - if (legendPtr->exportSelection) - ClearSelection(legendPtr); -} - static int CreateLegendWindow(Tcl_Interp* interp, Legend* legendPtr, const char *pathName) { @@ -1138,7 +605,7 @@ static void SetLegendOrigin(Legend* legendPtr) legendPtr->y = y + legendPtr->yPad; } -static int EntryIsSelected(Legend* legendPtr, Element* elemPtr) +int EntryIsSelected(Legend* legendPtr, Element* elemPtr) { Tcl_HashEntry*hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr); @@ -1156,7 +623,7 @@ static void SelectElement(Legend* legendPtr, Element* elemPtr) } } -static void DeselectElement(Legend* legendPtr, Element* elemPtr) +void DeselectElement(Legend* legendPtr, Element* elemPtr) { Tcl_HashEntry* hPtr = Tcl_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr); @@ -1167,7 +634,7 @@ static void DeselectElement(Legend* legendPtr, Element* elemPtr) } } -static void SelectEntry(Legend* legendPtr, Element* elemPtr) +void SelectEntry(Legend* legendPtr, Element* elemPtr) { Tcl_HashEntry *hPtr; @@ -1742,7 +1209,7 @@ static Element *GetLastElement(Graph* graphPtr) return NULL; } -static int GetElementFromObj(Graph* graphPtr, Tcl_Obj *objPtr, +int GetElementFromObj(Graph* graphPtr, Tcl_Obj *objPtr, Element **elemPtrPtr) { Element* elemPtr; @@ -1808,7 +1275,7 @@ static int GetElementFromObj(Graph* graphPtr, Tcl_Obj *objPtr, return TCL_OK; } -static int SelectRange(Legend* legendPtr, Element *fromPtr, Element *toPtr) +int SelectRange(Legend* legendPtr, Element *fromPtr, Element *toPtr) { if (Blt_Chain_IsBefore(fromPtr->link, toPtr->link)) { for (Blt_ChainLink link = fromPtr->link; link != NULL; diff --git a/src/bltGrLegd.h b/src/bltGrLegd.h index a0b8bff..d198aff 100644 --- a/src/bltGrLegd.h +++ b/src/bltGrLegd.h @@ -52,6 +52,22 @@ extern "C" { #define LEGEND_MARGIN_MASK (LEGEND_RIGHT|LEGEND_LEFT|LEGEND_BOTTOM|LEGEND_TOP) #define LEGEND_PLOTAREA_MASK (LEGEND_PLOT | LEGEND_XY) +// Selection related flags: +// SELECT_PENDING A "selection" command idle task is pending. +// SELECT_CLEAR Clear selection flag of entry. +// SELECT_SET Set selection flag of entry. +// SELECT_TOGGLE Toggle selection flag of entry. +// Mask of selection set/clear/toggle flags. +// SELECT_SORTED Indicates if the entries in the selection +// should be sorted or displayed in the order +// they were selected. + +#define SELECT_CLEAR (1<<24) +#define SELECT_PENDING (1<<25) +#define SELECT_SET (1<<26) +#define SELECT_SORTED (1<<27) +#define SELECT_TOGGLE (SELECT_SET | SELECT_CLEAR) + typedef enum { SELECT_MODE_SINGLE, SELECT_MODE_MULTIPLE } SelectMode; diff --git a/src/bltGrLegdOp.C b/src/bltGrLegdOp.C index 5301c06..3c2ea59 100644 --- a/src/bltGrLegdOp.C +++ b/src/bltGrLegdOp.C @@ -33,3 +33,530 @@ extern "C" { }; #include "bltGrLegd.h" +#include "bltGrElem.h" + +extern void SelectEntry(Legend* legendPtr, Element* elemPtr); +extern void DeselectElement(Legend* legendPtr, Element* elemPtr); +extern int EntryIsSelected(Legend* legendPtr, Element* elemPtr); +extern void ConfigureLegend(Graph* graphPtr); +extern int GetElementFromObj(Graph* graphPtr, Tcl_Obj *objPtr, + Element **elemPtrPtr); +extern int SelectRange(Legend* legendPtr, Element *fromPtr, Element *toPtr); + +static void SelectCmdProc(ClientData clientData); +static void EventuallyInvokeSelectCmd(Legend* legendPtr); +static int SelectionOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]); +static int LegendObjConfigure(Tcl_Interp* interp, Graph* graphPtr, + int objc, Tcl_Obj* const objv[]); +static void ClearSelection(Legend* legendPtr); +static Tk_LostSelProc LostSelectionProc; + +typedef int (GraphLegendProc)(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]); + + +static int CgetOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + 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 int ConfigureOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + 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 int LegendObjConfigure(Tcl_Interp* interp, Graph* graphPtr, + int objc, Tcl_Obj* const objv[]) +{ + 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); + } + + graphPtr->flags |= mask; + graphPtr->flags |= (RESET_WORLD | CACHE_DIRTY); + ConfigureLegend(graphPtr); + Blt_EventuallyRedrawGraph(graphPtr); + + break; + } + + if (!error) { + Tk_FreeSavedOptions(&savedOptions); + return TCL_OK; + } + else { + Tcl_SetObjResult(interp, errorResult); + Tcl_DecrRefCount(errorResult); + return TCL_ERROR; + } +} + +// Ops + +static int ActivateOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + 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 = 0; + 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 = (Element*)Blt_Chain_GetValue(link); + if (Tcl_StringMatch(elemPtr->name(), pattern)) { + fprintf(stderr, "legend %s(%s) %s is currently %d\n", + string, pattern, elemPtr->name(), + (elemPtr->flags & LABEL_ACTIVE)); + if (active) { + if ((elemPtr->flags & LABEL_ACTIVE) == 0) { + elemPtr->flags |= LABEL_ACTIVE; + redraw = 1; + } + } else { + if (elemPtr->flags & LABEL_ACTIVE) { + elemPtr->flags &= ~LABEL_ACTIVE; + redraw = 1; + } + } + fprintf(stderr, "legend %s(%s) %s is now %d\n", + string, pattern, elemPtr->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 = (Element*)Blt_Chain_GetValue(link); + if (elemPtr->flags & LABEL_ACTIVE) { + Tcl_Obj *objPtr; + + objPtr = Tcl_NewStringObj(elemPtr->name(), -1); + Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); + } + } + Tcl_SetObjResult(interp, listObjPtr); + } + return TCL_OK; +} + +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; + + listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL); + for (hPtr = Tcl_FirstHashEntry(&graphPtr->elements.tagTable, &iter); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&iter)) { + const char *tagName = + (const char*)Tcl_GetHashKey(&graphPtr->elements.tagTable, hPtr); + Tcl_Obj *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); +} + +static int CurselectionOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + Legend* legendPtr = graphPtr->legend; + Tcl_Obj *listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL); + if (legendPtr->flags & SELECT_SORTED) { + Blt_ChainLink link; + + for (link = Blt_Chain_FirstLink(legendPtr->selected); link != NULL; + link = Blt_Chain_NextLink(link)) { + Element* elemPtr = (Element*)Blt_Chain_GetValue(link); + Tcl_Obj *objPtr = Tcl_NewStringObj(elemPtr->name(), -1); + Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); + } + } + else { + /* List of selected entries is in stacking order. */ + for (Blt_ChainLink link = Blt_Chain_FirstLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_NextLink(link)) { + Element* elemPtr = (Element*)Blt_Chain_GetValue(link); + + if (EntryIsSelected(legendPtr, elemPtr)) { + Tcl_Obj *objPtr; + + objPtr = Tcl_NewStringObj(elemPtr->name(), -1); + Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); + } + } + } + Tcl_SetObjResult(interp, listObjPtr); + return TCL_OK; +} + +static int FocusOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + Legend* legendPtr = graphPtr->legend; + + if (objc == 4) { + Element* elemPtr; + + 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) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), + legendPtr->focusPtr->name(), -1); + } + return TCL_OK; +} + +static int GetOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + Legend* legendPtr = graphPtr->legend; + + if (((legendPtr->hide) == 0) && (legendPtr->nEntries > 0)) { + Element* elemPtr; + + if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) { + return TCL_ERROR; + } + if (elemPtr) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->name(),-1); + } + } + return TCL_OK; +} + +static Blt_OpSpec legendOps[] = + { + {"activate", 1, (void*)ActivateOp, 3, 0, "?pattern?...",}, + {"bind", 1, (void*)BindOp, 3, 6, "elem sequence command",}, + {"cget", 2, (void*)CgetOp, 4, 4, "option",}, + {"configure", 2, (void*)ConfigureOp, 3, 0, "?option value?...",}, + {"curselection", 2, (void*)CurselectionOp, 3, 3, "",}, + {"deactivate", 1, (void*)ActivateOp, 3, 0, "?pattern?...",}, + {"focus", 1, (void*)FocusOp, 4, 4, "elem",}, + {"get", 1, (void*)GetOp, 4, 4, "elem",}, + {"selection", 1, (void*)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 = (GraphLegendProc*)Blt_GetOpFromObj(interp, nLegendOps, legendOps, BLT_OP_ARG2, objc, objv,0); + if (proc == NULL) + return TCL_ERROR; + + return (*proc)(graphPtr, interp, objc, objv); +} + +// Selection Widget Ops + +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) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->name(), -1); + } + Blt_Legend_EventuallyRedraw(graphPtr); + return TCL_OK; +} + +static int SelectionClearallOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + Legend* legendPtr = graphPtr->legend; + + ClearSelection(legendPtr); + return TCL_OK; +} + +static int SelectionIncludesOp(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; + + int boo = EntryIsSelected(legendPtr, elemPtr); + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), boo); + return TCL_OK; +} + +static int SelectionMarkOp(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; + } + 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) { + next = Blt_Chain_PrevLink(link); + Element *selectPtr = (Element*)Blt_Chain_GetValue(link); + if (selectPtr == legendPtr->selAnchorPtr) { + break; + } + DeselectElement(legendPtr, selectPtr); + } + legendPtr->flags &= ~SELECT_TOGGLE; + legendPtr->flags |= SELECT_SET; + SelectRange(legendPtr, legendPtr->selAnchorPtr, elemPtr); + Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->name(), -1); + legendPtr->selMarkPtr = elemPtr; + + Blt_Legend_EventuallyRedraw(graphPtr); + if (legendPtr->selectCmd) { + EventuallyInvokeSelectCmd(legendPtr); + } + } + return TCL_OK; +} + +static int SelectionPresentOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + Legend* legendPtr = graphPtr->legend; + int boo = (Blt_Chain_GetLength(legendPtr->selected) > 0); + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), boo); + return TCL_OK; +} + +static int SelectionSetOp(Graph* graphPtr, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) +{ + Legend* legendPtr = graphPtr->legend; + Element *firstPtr, *lastPtr; + const char *string; + + legendPtr->flags &= ~SELECT_TOGGLE; + 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->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->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) { + EventuallyInvokeSelectCmd(legendPtr); + } + return TCL_OK; +} + +static Blt_OpSpec selectionOps[] = + { + {"anchor", 1, (void*)SelectionAnchorOp, 5, 5, "elem",}, + {"clear", 5, (void*)SelectionSetOp, 5, 6, "firstElem ?lastElem?",}, + {"clearall", 6, (void*)SelectionClearallOp, 4, 4, "",}, + {"includes", 1, (void*)SelectionIncludesOp, 5, 5, "elem",}, + {"mark", 1, (void*)SelectionMarkOp, 5, 5, "elem",}, + {"present", 1, (void*)SelectionPresentOp, 4, 4, "",}, + {"set", 1, (void*)SelectionSetOp, 5, 6, "firstElem ?lastElem?",}, + {"toggle", 1, (void*)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 = (GraphLegendProc*)Blt_GetOpFromObj(interp, nSelectionOps, selectionOps, BLT_OP_ARG3, objc, objv, 0); + if (proc == NULL) + return TCL_ERROR; + + return (*proc)(graphPtr, interp, objc, objv); +} + +static void LostSelectionProc(ClientData clientData) +{ + Legend* legendPtr = (Legend*)clientData; + + if (legendPtr->exportSelection) + ClearSelection(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) { + EventuallyInvokeSelectCmd(legendPtr); + } +} + +static void EventuallyInvokeSelectCmd(Legend* legendPtr) +{ + if ((legendPtr->flags & SELECT_PENDING) == 0) { + legendPtr->flags |= SELECT_PENDING; + Tcl_DoWhenIdle(SelectCmdProc, legendPtr); + } +} + +static void SelectCmdProc(ClientData clientData) +{ + Legend* legendPtr = (Legend*)clientData; + + Tcl_Preserve(legendPtr); + legendPtr->flags &= ~SELECT_PENDING; + if (legendPtr->selectCmd) { + Tcl_Interp* interp; + + interp = legendPtr->graphPtr->interp; + if (Tcl_GlobalEval(interp, legendPtr->selectCmd) != TCL_OK) { + Tcl_BackgroundError(interp); + } + } + Tcl_Release(legendPtr); +} + + diff --git a/src/bltGraph.C b/src/bltGraph.C index e685ba2..8dc0977 100644 --- a/src/bltGraph.C +++ b/src/bltGraph.C @@ -74,6 +74,8 @@ extern "C" { Tcl_ObjCmdProc Blt_GraphInstCmdProc; }; +extern void ConfigureLegend(Graph* graphPtr); + static Tcl_IdleProc DisplayGraph; static Tcl_FreeProc DestroyGraph; static Tk_EventProc GraphEventProc; @@ -1295,7 +1297,7 @@ Graph* Blt_GetGraphFromWindowData(Tk_Window tkwin) void Blt_ReconfigureGraph(Graph* graphPtr) { ConfigureGraph(graphPtr); - // Blt_ConfigureLegend(graphPtr); + ConfigureLegend(graphPtr); // Blt_ConfigureElements(graphPtr); Blt_ConfigureAxes(graphPtr); Blt::ConfigureMarkers(graphPtr); |