diff options
-rwxr-xr-x | configure | 4 | ||||
-rwxr-xr-x | configure.in | 4 | ||||
-rw-r--r-- | src/bltGrElemBar.C | 74 | ||||
-rw-r--r-- | src/bltGraph.C | 363 | ||||
-rw-r--r-- | src/bltGraph.h | 42 | ||||
-rw-r--r-- | src/bltGraphBar.C | 334 | ||||
-rw-r--r-- | src/bltGraphBar.h | 110 | ||||
-rw-r--r-- | src/bltGraphLine.C | 277 | ||||
-rw-r--r-- | src/bltGraphLine.h | 77 | ||||
-rw-r--r-- | src/bltGraphOp.C | 7 |
10 files changed, 890 insertions, 402 deletions
@@ -5557,8 +5557,10 @@ done bltGrPenLine.C bltGrPs.C bltGraph.C - bltGraphSup.C + bltGraphBar.C + bltGraphLine.C bltGraphOp.C + bltGraphSup.C bltInt.C bltList.C bltNsUtil.C diff --git a/configure.in b/configure.in index 16029d7..17b3d99 100755 --- a/configure.in +++ b/configure.in @@ -102,8 +102,10 @@ TEA_ADD_SOURCES([ bltGrPenLine.C bltGrPs.C bltGraph.C - bltGraphSup.C + bltGraphBar.C + bltGraphLine.C bltGraphOp.C + bltGraphSup.C bltInt.C bltList.C bltNsUtil.C diff --git a/src/bltGrElemBar.C b/src/bltGrElemBar.C index d755566..ea193db 100644 --- a/src/bltGrElemBar.C +++ b/src/bltGrElemBar.C @@ -31,6 +31,7 @@ extern "C" { #include "bltInt.h" +#include "bltGraphBar.h" }; #include "bltGrElemBar.h" @@ -257,8 +258,9 @@ int BarElement::configure() void BarElement::map() { + BarGraph* barGraphPtr_ = (BarGraph*)graphPtr_; BarElementOptions* ops = (BarElementOptions*)ops_; - GraphOptions* gops = (GraphOptions*)graphPtr_->ops_; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr_->ops_; if (!link) return; @@ -308,7 +310,7 @@ void BarElement::map() * coordinates of the two corners. */ - if ((graphPtr_->nBarGroups_ > 0) && (gops->barMode != BARS_INFRONT) && + if ((barGraphPtr_->nBarGroups_ > 0) && (gops->barMode != BARS_INFRONT) && (!gops->stackAxes)) { Tcl_HashEntry *hPtr; BarSetKey key; @@ -316,7 +318,7 @@ void BarElement::map() key.value = (float)x[i]; key.axes = ops->axes; key.axes.y = NULL; - hPtr = Tcl_FindHashEntry(&graphPtr_->setTable_, (char *)&key); + hPtr = Tcl_FindHashEntry(&barGraphPtr_->setTable_, (char *)&key); if (hPtr) { Tcl_HashTable *tablePtr = (Tcl_HashTable*)Tcl_GetHashValue(hPtr); @@ -327,9 +329,9 @@ void BarElement::map() double slice, width, offset; BarGroup *groupPtr = (BarGroup*)Tcl_GetHashValue(hPtr); - slice = barWidth / (double)graphPtr_->maxBarSetSize_; + slice = barWidth / (double)barGraphPtr_->maxBarSetSize_; offset = (slice * groupPtr->index); - if (graphPtr_->maxBarSetSize_ > 1) { + if (barGraphPtr_->maxBarSetSize_ > 1) { offset += slice * 0.05; slice *= 0.90; } @@ -483,8 +485,9 @@ void BarElement::map() void BarElement::extents(Region2d *regPtr) { + BarGraph* barGraphPtr_ = (BarGraph*)graphPtr_; BarElementOptions* ops = (BarElementOptions*)ops_; - GraphOptions* gops = (GraphOptions*)graphPtr_->ops_; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr_->ops_; regPtr->top = regPtr->left = DBL_MAX; regPtr->bottom = regPtr->right = -DBL_MAX; @@ -510,7 +513,7 @@ void BarElement::extents(Region2d *regPtr) // Handle stacked bar elements specially. // If element is stacked, the sum of its ordinates may be outside the // minimum/maximum limits of the element's data points. - if ((gops->barMode == BARS_STACKED) && (graphPtr_->nBarGroups_ > 0)) + if ((gops->barMode == BARS_STACKED) && (barGraphPtr_->nBarGroups_ > 0)) CheckBarStacks(&ops->axes, ®Ptr->top, ®Ptr->bottom); // Warning: You get what you deserve if the x-axis is logScale @@ -614,7 +617,7 @@ void BarElement::extents(Region2d *regPtr) void BarElement::closest() { BarElementOptions* ops = (BarElementOptions*)ops_; - GraphOptions* gops = (GraphOptions*)graphPtr_->ops_; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr_->ops_; ClosestSearch* searchPtr = &gops->search; double minDist = searchPtr->dist; @@ -888,12 +891,13 @@ void BarElement::ResetStylePalette(Blt_Chain stylePalette) void BarElement::CheckBarStacks(Axis2d *pairPtr, double *minPtr, double *maxPtr) { - GraphOptions* gops = (GraphOptions*)graphPtr_->ops_; - if ((gops->barMode != BARS_STACKED) || (graphPtr_->nBarGroups_ == 0)) + BarGraph* barGraphPtr_ = (BarGraph*)graphPtr_; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr_->ops_; + if ((gops->barMode != BARS_STACKED) || barGraphPtr_->nBarGroups_ == 0) return; BarGroup *gp, *gend; - for (gp = graphPtr_->barGroups_, gend = gp + graphPtr_->nBarGroups_; gp < gend; + for (gp = barGraphPtr_->barGroups_, gend = gp + barGraphPtr_->nBarGroups_; gp < gend; gp++) { if ((gp->axes.x == pairPtr->x) && (gp->axes.y == pairPtr->y)) { @@ -1305,7 +1309,7 @@ void BarElement::DrawBarValues(Drawable drawable, BarPen* penPtr, { BarElementOptions* ops = (BarElementOptions*)ops_; BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - GraphOptions* gops = (GraphOptions*)graphPtr_->ops_; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr_->ops_; const char *fmt = penOps->valueFormat; if (!fmt) @@ -1393,7 +1397,7 @@ void BarElement::BarValuesToPostScript(Blt_Ps ps, BarPen* penPtr, { BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); BarElementOptions* ops = (BarElementOptions*)ops_; - GraphOptions* gops = (GraphOptions*)graphPtr_->ops_; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr_->ops_; XRectangle *rp, *rend; char string[TCL_DOUBLE_SPACE * 2 + 2]; @@ -1440,7 +1444,8 @@ void BarElement::BarValuesToPostScript(Blt_Ps ps, BarPen* penPtr, void Blt_InitBarSetTable(Graph* graphPtr) { - GraphOptions* gops = (GraphOptions*)graphPtr->ops_; + BarGraph* barGraphPtr = (BarGraph*)graphPtr; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr->ops_; Blt_ChainLink link; int nStacks, nSegs; Tcl_HashTable setTable; @@ -1455,7 +1460,7 @@ void Blt_InitBarSetTable(Graph* graphPtr) Blt_DestroyBarSets(graphPtr); if (gops->barMode == BARS_INFRONT) return; - Tcl_InitHashTable(&graphPtr->setTable_, sizeof(BarSetKey) / sizeof(int)); + Tcl_InitHashTable(&barGraphPtr->setTable_, sizeof(BarSetKey) / sizeof(int)); /* * Initialize a hash table and fill it with unique abscissas. Keep track @@ -1522,7 +1527,7 @@ void Blt_InitBarSetTable(Graph* graphPtr) int isNew; keyPtr = (BarSetKey *)Tcl_GetHashKey(&setTable, hPtr); - hPtr2 = Tcl_CreateHashEntry(&graphPtr->setTable_, (char *)keyPtr,&isNew); + hPtr2 = Tcl_CreateHashEntry(&barGraphPtr->setTable_, (char *)keyPtr,&isNew); Tcl_HashTable *tablePtr = (Tcl_HashTable*)Tcl_GetHashValue(hPtr); Tcl_SetHashValue(hPtr2, tablePtr); if (max < tablePtr->numEntries) { @@ -1535,9 +1540,9 @@ void Blt_InitBarSetTable(Graph* graphPtr) Tcl_HashEntry *hPtr; Tcl_HashSearch iter; - graphPtr->barGroups_ = (BarGroup*)calloc(sum, sizeof(BarGroup)); - BarGroup* groupPtr = graphPtr->barGroups_; - for (hPtr = Tcl_FirstHashEntry(&graphPtr->setTable_, &iter); + barGraphPtr->barGroups_ = (BarGroup*)calloc(sum, sizeof(BarGroup)); + BarGroup* groupPtr = barGraphPtr->barGroups_; + for (hPtr = Tcl_FirstHashEntry(&barGraphPtr->setTable_, &iter); hPtr; hPtr = Tcl_NextHashEntry(&iter)) { BarSetKey *keyPtr; Tcl_HashEntry *hPtr2; @@ -1560,22 +1565,23 @@ void Blt_InitBarSetTable(Graph* graphPtr) } } } - graphPtr->maxBarSetSize_ = max; - graphPtr->nBarGroups_ = sum; + barGraphPtr->maxBarSetSize_ = max; + barGraphPtr->nBarGroups_ = sum; } void Blt_ComputeBarStacks(Graph* graphPtr) { - GraphOptions* gops = (GraphOptions*)graphPtr->ops_; + BarGraph* barGraphPtr = (BarGraph*)graphPtr; + BarGraphOptions* gops = (BarGraphOptions*)graphPtr->ops_; Blt_ChainLink link; - if ((gops->barMode != BARS_STACKED) || (graphPtr->nBarGroups_ == 0)) + if ((gops->barMode != BARS_STACKED) || (barGraphPtr->nBarGroups_ == 0)) return; /* Initialize the stack sums to zero. */ { BarGroup *gp, *gend; - for (gp = graphPtr->barGroups_, gend = gp + graphPtr->nBarGroups_; + for (gp = barGraphPtr->barGroups_, gend = gp + barGraphPtr->nBarGroups_; gp < gend; gp++) { gp->sum = 0.0; } @@ -1603,7 +1609,7 @@ void Blt_ComputeBarStacks(Graph* graphPtr) key.value = *x; key.axes = ops->axes; key.axes.y = NULL; - hPtr = Tcl_FindHashEntry(&graphPtr->setTable_, (char *)&key); + hPtr = Tcl_FindHashEntry(&barGraphPtr->setTable_, (char *)&key); if (!hPtr) continue; @@ -1622,9 +1628,10 @@ void Blt_ComputeBarStacks(Graph* graphPtr) void Blt_ResetBarGroups(Graph* graphPtr) { + BarGraph* barGraphPtr = (BarGraph*)graphPtr; BarGroup* gp; BarGroup* gend; - for (gp = graphPtr->barGroups_, gend = gp + graphPtr->nBarGroups_; gp < gend; + for (gp = barGraphPtr->barGroups_, gend = gp + barGraphPtr->nBarGroups_; gp < gend; gp++) { gp->lastY = 0.0; gp->count = 0; @@ -1633,19 +1640,20 @@ void Blt_ResetBarGroups(Graph* graphPtr) void Blt_DestroyBarSets(Graph* graphPtr) { - if (graphPtr->barGroups_) { - free(graphPtr->barGroups_); - graphPtr->barGroups_ = NULL; + BarGraph* barGraphPtr = (BarGraph*)graphPtr; + if (barGraphPtr->barGroups_) { + free(barGraphPtr->barGroups_); + barGraphPtr->barGroups_ = NULL; } - graphPtr->nBarGroups_ = 0; + barGraphPtr->nBarGroups_ = 0; Tcl_HashSearch iter; - for (Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(&graphPtr->setTable_, &iter); + for (Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(&barGraphPtr->setTable_, &iter); hPtr; hPtr = Tcl_NextHashEntry(&iter)) { Tcl_HashTable* tablePtr = (Tcl_HashTable*)Tcl_GetHashValue(hPtr); Tcl_DeleteHashTable(tablePtr); free(tablePtr); } - Tcl_DeleteHashTable(&graphPtr->setTable_); - Tcl_InitHashTable(&graphPtr->setTable_, sizeof(BarSetKey) / sizeof(int)); + Tcl_DeleteHashTable(&barGraphPtr->setTable_); + Tcl_InitHashTable(&barGraphPtr->setTable_, sizeof(BarSetKey) / sizeof(int)); } diff --git a/src/bltGraph.C b/src/bltGraph.C index 7c65b39..463c2e6 100644 --- a/src/bltGraph.C +++ b/src/bltGraph.C @@ -66,140 +66,8 @@ static Blt_BindPickProc PickEntry; // OptionSpecs -static const char* barmodeObjOption[] = - {"normal", "stacked", "aligned", "overlap", NULL}; -const char* searchModeObjOption[] = {"points", "traces", "auto", NULL}; -const char* searchAlongObjOption[] = {"x", "y", "both", NULL}; - -static Tk_OptionSpec optionSpecs[] = { - {TK_OPTION_DOUBLE, "-aspect", "aspect", "Aspect", - "0", -1, Tk_Offset(GraphOptions, aspect), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_BORDER, "-background", "background", "Background", - STD_NORMAL_BACKGROUND, -1, Tk_Offset(GraphOptions, normalBg), - 0, NULL, CACHE_DIRTY}, - {TK_OPTION_STRING_TABLE, "-barmode", "barMode", "BarMode", - "normal", -1, Tk_Offset(GraphOptions, barMode), - 0, &barmodeObjOption, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_DOUBLE, "-barwidth", "barWidth", "BarWidth", - ".9", -1, Tk_Offset(GraphOptions, barWidth), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_DOUBLE, "-baseline", "baseline", "Baseline", - "0", -1, Tk_Offset(GraphOptions, baseline), 0, NULL, 0}, - {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, -1, 0, 0, "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, -1, 0, 0, "-background", 0}, - {TK_OPTION_SYNONYM, "-bm", NULL, NULL, NULL, -1, 0, 0, "-bottommargin", 0}, - {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - STD_BORDERWIDTH, -1, Tk_Offset(GraphOptions, borderWidth), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_PIXELS, "-bottommargin", "bottomMargin", "BottomMargin", - "0", -1, Tk_Offset(GraphOptions, bottomMargin.reqSize), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_STRING, "-bottomvariable", "bottomVariable", "BottomVariable", - NULL, -1, Tk_Offset(GraphOptions, bottomMargin.varName), - TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_BOOLEAN, "-bufferelements", "bufferElements", "BufferElements", - "yes", -1, Tk_Offset(GraphOptions, backingStore), 0, NULL, 0}, - {TK_OPTION_BOOLEAN, "-buffergraph", "bufferGraph", "BufferGraph", - "yes", -1, Tk_Offset(GraphOptions, doubleBuffer), 0, NULL, 0}, - {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - "crosshair", -1, Tk_Offset(GraphOptions, cursor), - TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, - {TK_OPTION_FONT, "-font", "font", "Font", - STD_FONT_MEDIUM, -1, Tk_Offset(GraphOptions, titleTextStyle.font), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - STD_NORMAL_FOREGROUND, -1, Tk_Offset(GraphOptions, titleTextStyle.color), - 0, NULL, - CACHE_DIRTY}, - {TK_OPTION_SYNONYM, "-halo", NULL, NULL, NULL, -1, 0, 0, "-searchhalo", 0}, - {TK_OPTION_PIXELS, "-height", "height", "Height", - "4i", -1, Tk_Offset(GraphOptions, reqHeight), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", - "HighlightBackground", - STD_NORMAL_BACKGROUND, -1, Tk_Offset(GraphOptions, highlightBgColor), - 0, NULL, - CACHE_DIRTY}, - {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - STD_NORMAL_FOREGROUND, -1, Tk_Offset(GraphOptions, highlightColor), - 0, NULL, 0}, - {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", - "HighlightThickness", - "2", -1, Tk_Offset(GraphOptions, highlightWidth), 0, NULL, 0}, - {TK_OPTION_BOOLEAN, "-invertxy", "invertXY", "InvertXY", - "no", -1, Tk_Offset(GraphOptions, inverted), 0, NULL, - RESET_WORLD | CACHE_DIRTY | RESET_AXES}, - {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - "center", -1, Tk_Offset(GraphOptions, titleTextStyle.justify), 0, NULL, 0}, - {TK_OPTION_PIXELS, "-leftmargin", "leftMargin", "Margin", - "0", -1, Tk_Offset(GraphOptions, leftMargin.reqSize), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_STRING, "-leftvariable", "leftVariable", "LeftVariable", - NULL, -1, Tk_Offset(GraphOptions, leftMargin.varName), - TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_SYNONYM, "-lm", NULL, NULL, NULL, -1, 0, 0, "-leftmargin", 0}, - {TK_OPTION_BORDER, "-plotbackground", "plotbackground", "PlotBackground", - STD_NORMAL_BACKGROUND, -1, Tk_Offset(GraphOptions, plotBg), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_PIXELS, "-plotborderwidth", "plotBorderWidth", "PlotBorderWidth", - STD_BORDERWIDTH, -1, Tk_Offset(GraphOptions, plotBW), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_PIXELS, "-plotpadx", "plotPadX", "PlotPad", - "0", -1, Tk_Offset(GraphOptions, xPad), 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_PIXELS, "-plotpady", "plotPadY", "PlotPad", - "0", -1, Tk_Offset(GraphOptions, yPad), 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_RELIEF, "-plotrelief", "plotRelief", "Relief", - "flat", -1, Tk_Offset(GraphOptions, plotRelief), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - "flat", -1, Tk_Offset(GraphOptions, relief), 0, NULL, 0}, - {TK_OPTION_PIXELS, "-rightmargin", "rightMargin", "Margin", - "0", -1, Tk_Offset(GraphOptions, rightMargin.reqSize), 0, NULL, - RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_STRING, "-rightvariable", "rightVariable", "RightVariable", - NULL, -1, Tk_Offset(GraphOptions, rightMargin.varName), - TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_SYNONYM, "-rm", NULL, NULL, NULL, -1, 0, 0, "-rightmargin", 0}, - {TK_OPTION_PIXELS, "-searchhalo", "searchhalo", "SearchHalo", - "2m", -1, Tk_Offset(GraphOptions, search.halo), 0, NULL, 0}, - {TK_OPTION_STRING_TABLE, "-searchmode", "searchMode", "SearchMode", - "points", -1, Tk_Offset(GraphOptions, search.mode), - 0, &searchModeObjOption, 0}, - {TK_OPTION_STRING_TABLE, "-searchalong", "searchAlong", "SearchAlong", - "both", -1, Tk_Offset(GraphOptions, search.along), - 0, &searchAlongObjOption, 0}, - {TK_OPTION_BOOLEAN, "-stackaxes", "stackAxes", "StackAxes", - "no", -1, Tk_Offset(GraphOptions, stackAxes), 0, NULL, 0}, - {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - NULL, -1, Tk_Offset(GraphOptions, takeFocus), TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_STRING, "-title", "title", "Title", - NULL, -1, Tk_Offset(GraphOptions, title), - TK_OPTION_NULL_OK, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_SYNONYM, "-tm", NULL, NULL, NULL, -1, 0, 0, "-topmargin", 0}, - {TK_OPTION_PIXELS, "-topmargin", "topMargin", "TopMargin", - "0", -1, Tk_Offset(GraphOptions, topMargin.reqSize), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_STRING, "-topvariable", "topVariable", "TopVariable", - NULL, -1, Tk_Offset(GraphOptions, topMargin.varName), - TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_PIXELS, "-width", "width", "Width", - "5i", -1, Tk_Offset(GraphOptions, reqWidth), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_PIXELS, "-plotwidth", "plotWidth", "PlotWidth", - "0", -1, Tk_Offset(GraphOptions, reqPlotWidth), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_PIXELS, "-plotheight", "plotHeight", "PlotHeight", - "0", -1, Tk_Offset(GraphOptions, reqPlotHeight), - 0, NULL, RESET_WORLD | CACHE_DIRTY}, - {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} -}; - -// Create - Graph::Graph(ClientData clientData, Tcl_Interp* interp, - int objc, Tcl_Obj* const objv[], ClassId classId) + int objc, Tcl_Obj* const objv[]) { valid_ =1; interp_ = interp; @@ -215,22 +83,7 @@ Graph::Graph(ClientData clientData, Tcl_Interp* interp, cmdToken_ = Tcl_CreateObjCommand(interp_, Tk_PathName(tkwin_), GraphInstCmdProc, this, GraphInstCmdDeleteProc); - optionTable_ = Tk_CreateOptionTable(interp_, optionSpecs); - ops_ = (GraphOptions*)calloc(1, sizeof(GraphOptions)); - GraphOptions* ops = (GraphOptions*)ops_; - switch (classId) { - case CID_ELEM_LINE: - Tk_SetClass(tkwin_, "Graph"); - break; - case CID_ELEM_BAR: - Tk_SetClass(tkwin_, "Barchart"); - break; - default: - break; - } - - classId_ = classId; flags = MAP_WORLD | REDRAW_WORLD; nextMarkerId_ = 1; @@ -261,18 +114,6 @@ Graph::Graph(ClientData clientData, Tcl_Interp* interp, cacheWidth_ =0; cacheHeight_ =0; - barGroups_ =NULL; - nBarGroups_ =0; - maxBarSetSize_ =0; - - ops->bottomMargin.site = MARGIN_BOTTOM; - ops->leftMargin.site = MARGIN_LEFT; - ops->topMargin.site = MARGIN_TOP; - ops->rightMargin.site = MARGIN_RIGHT; - - Blt_Ts_InitStyle(ops->titleTextStyle); - ops->titleTextStyle.anchor = TK_ANCHOR_N; - Tcl_InitHashTable(&axes_.table, TCL_STRING_KEYS); Tcl_InitHashTable(&axes_.tagTable, TCL_STRING_KEYS); Tcl_InitHashTable(&elements_.table, TCL_STRING_KEYS); @@ -280,7 +121,7 @@ Graph::Graph(ClientData clientData, Tcl_Interp* interp, Tcl_InitHashTable(&markers_.table, TCL_STRING_KEYS); Tcl_InitHashTable(&markers_.tagTable, TCL_STRING_KEYS); Tcl_InitHashTable(&penTable_, TCL_STRING_KEYS); - Tcl_InitHashTable(&setTable_, sizeof(BarSetKey) / sizeof(int)); + axes_.displayList = Blt_Chain_Create(); elements_.displayList = Blt_Chain_Create(); markers_.displayList = Blt_Chain_Create(); @@ -292,28 +133,6 @@ Graph::Graph(ClientData clientData, Tcl_Interp* interp, return; } - switch (classId) { - case CID_ELEM_LINE: - if (createPen("active", 0, NULL) != TCL_OK) { - valid_ =0; - return; - } - break; - case CID_ELEM_BAR: - if (createPen("active", 0, NULL) != TCL_OK) { - valid_ =0; - return; - } - break; - default: - break; - } - - if (Blt_CreatePageSetup(this) != TCL_OK) { - valid_ =0; - return; - } - // Keep a hold of the associated tkwin until we destroy the graph, // otherwise Tk might free it while we still need it. Tcl_Preserve(tkwin_); @@ -321,15 +140,6 @@ Graph::Graph(ClientData clientData, Tcl_Interp* interp, Tk_CreateEventHandler(tkwin_, ExposureMask|StructureNotifyMask|FocusChangeMask, GraphEventProc, this); - - if ((Tk_InitOptions(interp_, (char*)ops_, optionTable_, tkwin_) != TCL_OK) || (GraphObjConfigure(interp_, this, objc-2, objv+2) != TCL_OK)) { - valid_ =0; - return; - } - - adjustAxes(); - - Tcl_SetStringObj(Tcl_GetObjResult(interp_), Tk_PathName(tkwin_), -1); } Graph::~Graph() @@ -347,7 +157,6 @@ Graph::~Graph() destroyAxes(); destroyPens(); Blt_DestroyPageSetup(this); - Blt_DestroyBarSets(this); if (bindTable_) Blt_DestroyBindingTable(bindTable_); @@ -371,10 +180,6 @@ void Graph::configure() { GraphOptions* ops = (GraphOptions*)ops_; - // Don't allow negative bar widths. Reset to an arbitrary value (0.1) - if (ops->barWidth <= 0.0f) - ops->barWidth = 0.8f; - inset_ = ops->borderWidth + ops->highlightWidth; if ((ops->reqHeight != Tk_ReqHeight(tkwin_)) || (ops->reqWidth != Tk_ReqWidth(tkwin_))) @@ -573,7 +378,7 @@ void Graph::drawPlot(Drawable drawable) int Graph::print(const char *ident, Blt_Ps ps) { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; PageSetup *setupPtr = pageSetup_; // We need to know how big a graph to print. If the graph hasn't been drawn @@ -598,19 +403,19 @@ int Graph::print(const char *ident, Blt_Ps ps) reconfigure(); map(); - int x = left_ - gops->plotBW; - int y = top_ - gops->plotBW; + int x = left_ - ops->plotBW; + int y = top_ - ops->plotBW; - int w = (right_ - left_ + 1) + (2*gops->plotBW); - int h = (bottom_ - top_ + 1) + (2*gops->plotBW); + int w = (right_ - left_ + 1) + (2*ops->plotBW); + int h = (bottom_ - top_ + 1) + (2*ops->plotBW); int result = PostScriptPreamble(this, ident, ps); if (result != TCL_OK) goto error; - Blt_Ps_XSetFont(ps, gops->titleTextStyle.font); + Blt_Ps_XSetFont(ps, ops->titleTextStyle.font); if (pageSetup_->decorations) - Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(gops->plotBg)); + Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(ops->plotBg)); else Blt_Ps_SetClearBackground(ps); @@ -764,7 +569,7 @@ void Graph::drawMargins(Drawable drawable) void Graph::printMargins(Blt_Ps ps) { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; PageSetup *setupPtr = pageSetup_; XRectangle margin[4]; @@ -781,7 +586,7 @@ void Graph::printMargins(Blt_Ps ps) // Clear the surrounding margins and clip the plotting surface if (setupPtr->decorations) - Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(gops->normalBg)); + Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(ops->normalBg)); else Blt_Ps_SetClearBackground(ps); @@ -789,18 +594,18 @@ void Graph::printMargins(Blt_Ps ps) Blt_Ps_XFillRectangles(ps, margin, 4); Blt_Ps_Append(ps, "% Interior 3D border\n"); - if (gops->plotBW > 0) { - int x = left_ - gops->plotBW; - int y = top_ - gops->plotBW; - int w = (right_ - left_) + (2*gops->plotBW); - int h = (bottom_ - top_) + (2*gops->plotBW); - Blt_Ps_Draw3DRectangle(ps, gops->normalBg, (double)x, (double)y, w, h, - gops->plotBW, gops->plotRelief); + if (ops->plotBW > 0) { + int x = left_ - ops->plotBW; + int y = top_ - ops->plotBW; + int w = (right_ - left_) + (2*ops->plotBW); + int h = (bottom_ - top_) + (2*ops->plotBW); + Blt_Ps_Draw3DRectangle(ps, ops->normalBg, (double)x, (double)y, w, h, + ops->plotBW, ops->plotRelief); } - if (gops->title) { + if (ops->title) { Blt_Ps_Append(ps, "% Graph title\n"); - Blt_Ps_DrawText(ps, gops->title, &gops->titleTextStyle, + Blt_Ps_DrawText(ps, ops->title, &ops->titleTextStyle, (double)titleX_, (double)titleY_); } } @@ -840,44 +645,6 @@ void Graph::disableCrosshairs() // Pens -int Graph::createPen(const char* penName, int objc, Tcl_Obj* const objv[]) -{ - int isNew; - Tcl_HashEntry *hPtr = - Tcl_CreateHashEntry(&penTable_, penName, &isNew); - if (!isNew) { - Tcl_AppendResult(interp_, "pen \"", penName, "\" already exists in \"", - Tk_PathName(tkwin_), "\"", (char *)NULL); - return TCL_ERROR; - } - - Pen* penPtr; - switch (classId_) { - case CID_ELEM_BAR: - penPtr = new BarPen(this, penName, hPtr); - break; - case CID_ELEM_LINE: - penPtr = new LinePen(this, penName, hPtr); - break; - default: - return TCL_ERROR; - } - if (!penPtr) - return TCL_ERROR; - - Tcl_SetHashValue(hPtr, penPtr); - - if ((Tk_InitOptions(interp_, (char*)penPtr->ops(), penPtr->optionTable(), tkwin_) != TCL_OK) || (PenObjConfigure(interp_, this, penPtr, objc-4, objv+4) != TCL_OK)) { - delete penPtr; - return TCL_ERROR; - } - - flags |= CACHE_DIRTY; - eventuallyRedraw(); - - return TCL_OK; -} - void Graph::destroyPens() { Tcl_HashSearch iter; @@ -910,51 +677,6 @@ int Graph::getPen(Tcl_Obj* objPtr, Pen** penPtrPtr) // Elements -int Graph::createElement(int objc, Tcl_Obj* const objv[]) -{ - char *name = Tcl_GetString(objv[3]); - if (name[0] == '-') { - Tcl_AppendResult(interp_, "name of element \"", name, - "\" can't start with a '-'", NULL); - return TCL_ERROR; - } - - int isNew; - Tcl_HashEntry* hPtr = - Tcl_CreateHashEntry(&elements_.table, name, &isNew); - if (!isNew) { - Tcl_AppendResult(interp_, "element \"", name, - "\" already exists in \"", Tcl_GetString(objv[0]), - "\"", NULL); - return TCL_ERROR; - } - - Element* elemPtr; - switch (classId_) { - case CID_ELEM_BAR: - elemPtr = new BarElement(this, name, hPtr); - break; - case CID_ELEM_LINE: - elemPtr = new LineElement(this, name, hPtr); - break; - default: - return TCL_ERROR; - } - if (!elemPtr) - return TCL_ERROR; - - Tcl_SetHashValue(hPtr, elemPtr); - - if ((Tk_InitOptions(interp_, (char*)elemPtr->ops(), elemPtr->optionTable(), tkwin_) != TCL_OK) || (ElementObjConfigure(interp_, elemPtr, objc-4, objv+4) != TCL_OK)) { - delete elemPtr; - return TCL_ERROR; - } - - elemPtr->link = Blt_Chain_Append(elements_.displayList, elemPtr); - - return TCL_OK; -} - void Graph::destroyElement(Element* elemPtr) { Blt_DeleteBindings(bindTable_, elemPtr); @@ -991,10 +713,6 @@ void Graph::configureElements() void Graph::mapElements() { - GraphOptions* gops = (GraphOptions*)ops_; - if (gops->barMode != BARS_INFRONT) - Blt_ResetBarGroups(this); - for (Blt_ChainLink link =Blt_Chain_FirstLink(elements_.displayList); link; link = Blt_Chain_NextLink(link)) { Element* elemPtr = (Element*)Blt_Chain_GetValue(link); @@ -1292,28 +1010,28 @@ void Graph::configureAxes() void Graph::mapAxes() { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; for (int ii=0; ii<4; ii++) { int count =0; int offset =0; - Blt_Chain chain = gops->margins[ii].axes; + Blt_Chain chain = ops->margins[ii].axes; for (Blt_ChainLink link=Blt_Chain_FirstLink(chain); link; link = Blt_Chain_NextLink(link)) { Axis *axisPtr = (Axis*)Blt_Chain_GetValue(link); - AxisOptions* ops = (AxisOptions*)axisPtr->ops(); + AxisOptions* aops = (AxisOptions*)axisPtr->ops(); if (!axisPtr->use_) continue; - if (ops->reqNumMajorTicks <= 0) - ops->reqNumMajorTicks = 4; + if (aops->reqNumMajorTicks <= 0) + aops->reqNumMajorTicks = 4; - if (gops->stackAxes) + if (ops->stackAxes) axisPtr->mapStacked(count, ii); else axisPtr->map(offset, ii); - if (ops->showGrid) + if (aops->showGrid) axisPtr->mapGridlines(); offset += axisPtr->isHorizontal() ? axisPtr->height_ : axisPtr->width_; @@ -1324,10 +1042,10 @@ void Graph::mapAxes() void Graph::drawAxes(Drawable drawable) { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; for (int ii=0; ii<4; ii++) { - for (Blt_ChainLink link = Blt_Chain_LastLink(gops->margins[ii].axes); + for (Blt_ChainLink link = Blt_Chain_LastLink(ops->margins[ii].axes); link != NULL; link = Blt_Chain_PrevLink(link)) { Axis *axisPtr = (Axis*)Blt_Chain_GetValue(link); axisPtr->draw(drawable); @@ -1347,10 +1065,10 @@ void Graph::drawAxesLimits(Drawable drawable) void Graph::drawAxesGrids(Drawable drawable) { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; for (int ii=0; ii<4; ii++) { - for (Blt_ChainLink link = Blt_Chain_FirstLink(gops->margins[ii].axes); + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->margins[ii].axes); link; link = Blt_Chain_NextLink(link)) { Axis *axisPtr = (Axis*)Blt_Chain_GetValue(link); axisPtr->drawGrids(drawable); @@ -1360,10 +1078,10 @@ void Graph::drawAxesGrids(Drawable drawable) void Graph::printAxes(Blt_Ps ps) { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; Margin *mp, *mend; - for (mp = gops->margins, mend = mp + 4; mp < mend; mp++) { + for (mp = ops->margins, mend = mp + 4; mp < mend; mp++) { for (Blt_ChainLink link=Blt_Chain_FirstLink(mp->axes); link; link = Blt_Chain_NextLink(link)) { Axis *axisPtr = (Axis*)Blt_Chain_GetValue(link); @@ -1374,10 +1092,10 @@ void Graph::printAxes(Blt_Ps ps) void Graph::printAxesGrids(Blt_Ps ps) { - GraphOptions* gops = (GraphOptions*)ops_; + GraphOptions* ops = (GraphOptions*)ops_; for (int ii=0; ii<4; ii++) { - for (Blt_ChainLink link=Blt_Chain_FirstLink(gops->margins[ii].axes); + for (Blt_ChainLink link=Blt_Chain_FirstLink(ops->margins[ii].axes); link; link = Blt_Chain_NextLink(link)) { Axis *axisPtr = (Axis*)Blt_Chain_GetValue(link); axisPtr->printGrids(ps); @@ -1472,17 +1190,6 @@ Point2d Graph::invMap2D(double x, double y, Axis2d* axesPtr) void Graph::resetAxes() { - GraphOptions* gops = (GraphOptions*)ops_; - - /* FIXME: This should be called whenever the display list of - * elements change. Maybe yet another flag INIT_STACKS to - * indicate that the element display list has changed. - * Needs to be done before the axis limits are set. - */ - Blt_InitBarSetTable(this); - if ((gops->barMode == BARS_STACKED) && (nBarGroups_ > 0)) - Blt_ComputeBarStacks(this); - /* * Step 1: Reset all axes. Initialize the data limits of the axis to * impossible values. diff --git a/src/bltGraph.h b/src/bltGraph.h index f2de09b..326c5f0 100644 --- a/src/bltGraph.h +++ b/src/bltGraph.h @@ -67,24 +67,6 @@ typedef struct { } ClosestSearch; typedef struct { - int nSegments; - Axis2d axes; - float sum; - int count; - float lastY; - size_t index; -} BarGroup; - -typedef struct { - float value; - Axis2d axes; -} BarSetKey; - -typedef enum { - BARS_INFRONT, BARS_STACKED, BARS_ALIGNED, BARS_OVERLAP -} BarMode; - -typedef struct { short int width; short int height; short int axesOffset; @@ -136,11 +118,6 @@ typedef struct { int reqWidth; int reqPlotWidth; int reqPlotHeight; - - // bar graph - BarMode barMode; - double barWidth; - double baseline; } GraphOptions; class Graph { @@ -192,12 +169,6 @@ class Graph { short int cacheWidth_; short int cacheHeight_; - // barchart specific information - BarGroup *barGroups_; - int nBarGroups_; - Tcl_HashTable setTable_; - int maxBarSetSize_; - protected: void drawPlot(Drawable); void layoutGraph(); @@ -211,7 +182,7 @@ class Graph { void destroyElements(); void configureElements(); - void mapElements(); + virtual void mapElements(); void drawElements(Drawable); void drawActiveElements(Drawable); void printElements(Blt_Ps); @@ -234,11 +205,10 @@ class Graph { void adjustAxes(); public: - Graph(ClientData clientData, Tcl_Interp*interp, - int objc, Tcl_Obj* const objv[], ClassId classId); + Graph(ClientData, Tcl_Interp*, int, Tcl_Obj* const []); virtual ~Graph(); - void configure(); + virtual void configure(); void map(); void draw(); void eventuallyRedraw(); @@ -257,19 +227,19 @@ class Graph { ClientData axisTag(const char*); Point2d map2D(double, double, Axis2d*); Point2d invMap2D(double, double, Axis2d*); - void resetAxes(); + virtual void resetAxes(); Axis* nearestAxis(int, int); ClientData markerTag(const char*); Blt::Marker* nearestMarker(int, int, int); int isElementHidden(Blt::Marker*); - int createElement(int, Tcl_Obj* const []); + virtual int createElement(int, Tcl_Obj* const []) =0; void destroyElement(Element*); int getElement(Tcl_Obj*, Element**); ClientData elementTag(const char*); - int createPen(const char*, int, Tcl_Obj* const []); + virtual int createPen(const char*, int, Tcl_Obj* const []) =0; int getPen(Tcl_Obj*, Pen**); }; diff --git a/src/bltGraphBar.C b/src/bltGraphBar.C new file mode 100644 index 0000000..39ab46b --- /dev/null +++ b/src/bltGraphBar.C @@ -0,0 +1,334 @@ +/* + * Smithsonian Astrophysical Observatory, Cambridge, MA, USA + * This code has been modified under the terms listed below and is made + * available under the same terms. + */ + +/* + * Copyright 1991-2004 George A Howlett. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +extern "C" { +#include "bltGraphBar.h" +} + +#include "bltGraphOp.h" + +#include "bltGrAxis.h" +#include "bltGrAxisOp.h" +#include "bltGrXAxisOp.h" +#include "bltGrPen.h" +#include "bltGrPenBar.h" +#include "bltGrPenLine.h" +#include "bltGrPenOp.h" +#include "bltGrElem.h" +#include "bltGrElemBar.h" +#include "bltGrElemLine.h" +#include "bltGrElemOp.h" +#include "bltGrMarker.h" +#include "bltGrMarkerOp.h" +#include "bltGrLegd.h" +#include "bltGrLegdOp.h" +#include "bltGrHairs.h" +#include "bltGrHairsOp.h" +#include "bltGrDef.h" + +using namespace Blt; + +static const char* barmodeObjOption[] = + {"normal", "stacked", "aligned", "overlap", NULL}; +static const char* searchModeObjOption[] = {"points", "traces", "auto", NULL}; +static const char* searchAlongObjOption[] = {"x", "y", "both", NULL}; + +static Tk_OptionSpec optionSpecs[] = { + {TK_OPTION_DOUBLE, "-aspect", "aspect", "Aspect", + "0", -1, Tk_Offset(BarGraphOptions, aspect), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_BORDER, "-background", "background", "Background", + STD_NORMAL_BACKGROUND, -1, Tk_Offset(BarGraphOptions, normalBg), + 0, NULL, CACHE_DIRTY}, + {TK_OPTION_STRING_TABLE, "-barmode", "barMode", "BarMode", + "normal", -1, Tk_Offset(BarGraphOptions, barMode), + 0, &barmodeObjOption, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_DOUBLE, "-barwidth", "barWidth", "BarWidth", + ".9", -1, Tk_Offset(BarGraphOptions, barWidth), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_DOUBLE, "-baseline", "baseline", "Baseline", + "0", -1, Tk_Offset(BarGraphOptions, baseline), 0, NULL, 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, -1, 0, 0, "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, -1, 0, 0, "-background", 0}, + {TK_OPTION_SYNONYM, "-bm", NULL, NULL, NULL, -1, 0, 0, "-bottommargin", 0}, + {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", + STD_BORDERWIDTH, -1, Tk_Offset(BarGraphOptions, borderWidth), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-bottommargin", "bottomMargin", "BottomMargin", + "0", -1, Tk_Offset(BarGraphOptions, bottomMargin.reqSize), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-bottomvariable", "bottomVariable", "BottomVariable", + NULL, -1, Tk_Offset(BarGraphOptions, bottomMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_BOOLEAN, "-bufferelements", "bufferElements", "BufferElements", + "yes", -1, Tk_Offset(BarGraphOptions, backingStore), 0, NULL, 0}, + {TK_OPTION_BOOLEAN, "-buffergraph", "bufferGraph", "BufferGraph", + "yes", -1, Tk_Offset(BarGraphOptions, doubleBuffer), 0, NULL, 0}, + {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", + "crosshair", -1, Tk_Offset(BarGraphOptions, cursor), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, + {TK_OPTION_FONT, "-font", "font", "Font", + STD_FONT_MEDIUM, -1, Tk_Offset(BarGraphOptions, titleTextStyle.font), + 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", + STD_NORMAL_FOREGROUND, -1, Tk_Offset(BarGraphOptions, titleTextStyle.color), + 0, NULL, + CACHE_DIRTY}, + {TK_OPTION_SYNONYM, "-halo", NULL, NULL, NULL, -1, 0, 0, "-searchhalo", 0}, + {TK_OPTION_PIXELS, "-height", "height", "Height", + "4i", -1, Tk_Offset(BarGraphOptions, reqHeight), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", + "HighlightBackground", + STD_NORMAL_BACKGROUND, -1, Tk_Offset(BarGraphOptions, highlightBgColor), + 0, NULL, + CACHE_DIRTY}, + {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", + STD_NORMAL_FOREGROUND, -1, Tk_Offset(BarGraphOptions, highlightColor), + 0, NULL, 0}, + {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", + "HighlightThickness", + "2", -1, Tk_Offset(BarGraphOptions, highlightWidth), 0, NULL, 0}, + {TK_OPTION_BOOLEAN, "-invertxy", "invertXY", "InvertXY", + "no", -1, Tk_Offset(BarGraphOptions, inverted), 0, NULL, + RESET_WORLD | CACHE_DIRTY | RESET_AXES}, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "center", -1, Tk_Offset(BarGraphOptions, titleTextStyle.justify), + 0, NULL, 0}, + {TK_OPTION_PIXELS, "-leftmargin", "leftMargin", "Margin", + "0", -1, Tk_Offset(BarGraphOptions, leftMargin.reqSize), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-leftvariable", "leftVariable", "LeftVariable", + NULL, -1, Tk_Offset(BarGraphOptions, leftMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_SYNONYM, "-lm", NULL, NULL, NULL, -1, 0, 0, "-leftmargin", 0}, + {TK_OPTION_BORDER, "-plotbackground", "plotbackground", "PlotBackground", + STD_NORMAL_BACKGROUND, -1, Tk_Offset(BarGraphOptions, plotBg), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotborderwidth", "plotBorderWidth", "PlotBorderWidth", + STD_BORDERWIDTH, -1, Tk_Offset(BarGraphOptions, plotBW), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotpadx", "plotPadX", "PlotPad", + "0", -1, Tk_Offset(BarGraphOptions, xPad), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotpady", "plotPadY", "PlotPad", + "0", -1, Tk_Offset(BarGraphOptions, yPad), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_RELIEF, "-plotrelief", "plotRelief", "Relief", + "flat", -1, Tk_Offset(BarGraphOptions, plotRelief), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", + "flat", -1, Tk_Offset(BarGraphOptions, relief), 0, NULL, 0}, + {TK_OPTION_PIXELS, "-rightmargin", "rightMargin", "Margin", + "0", -1, Tk_Offset(BarGraphOptions, rightMargin.reqSize), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-rightvariable", "rightVariable", "RightVariable", + NULL, -1, Tk_Offset(BarGraphOptions, rightMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_SYNONYM, "-rm", NULL, NULL, NULL, -1, 0, 0, "-rightmargin", 0}, + {TK_OPTION_PIXELS, "-searchhalo", "searchhalo", "SearchHalo", + "2m", -1, Tk_Offset(BarGraphOptions, search.halo), 0, NULL, 0}, + {TK_OPTION_STRING_TABLE, "-searchmode", "searchMode", "SearchMode", + "points", -1, Tk_Offset(BarGraphOptions, search.mode), + 0, &searchModeObjOption, 0}, + {TK_OPTION_STRING_TABLE, "-searchalong", "searchAlong", "SearchAlong", + "both", -1, Tk_Offset(BarGraphOptions, search.along), + 0, &searchAlongObjOption, 0}, + {TK_OPTION_BOOLEAN, "-stackaxes", "stackAxes", "StackAxes", + "no", -1, Tk_Offset(BarGraphOptions, stackAxes), 0, NULL, 0}, + {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", + NULL, -1, Tk_Offset(BarGraphOptions, takeFocus), TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_STRING, "-title", "title", "Title", + NULL, -1, Tk_Offset(BarGraphOptions, title), + TK_OPTION_NULL_OK, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_SYNONYM, "-tm", NULL, NULL, NULL, -1, 0, 0, "-topmargin", 0}, + {TK_OPTION_PIXELS, "-topmargin", "topMargin", "TopMargin", + "0", -1, Tk_Offset(BarGraphOptions, topMargin.reqSize), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-topvariable", "topVariable", "TopVariable", + NULL, -1, Tk_Offset(BarGraphOptions, topMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_PIXELS, "-width", "width", "Width", + "5i", -1, Tk_Offset(BarGraphOptions, reqWidth), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotwidth", "plotWidth", "PlotWidth", + "0", -1, Tk_Offset(BarGraphOptions, reqPlotWidth), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotheight", "plotHeight", "PlotHeight", + "0", -1, Tk_Offset(BarGraphOptions, reqPlotHeight), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} +}; + +// Create + +BarGraph::BarGraph(ClientData clientData, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) + : Graph(clientData, interp, objc, objv) +{ + Tk_SetClass(tkwin_, "Barchart"); + classId_ = CID_ELEM_BAR; + + optionTable_ = Tk_CreateOptionTable(interp_, optionSpecs); + ops_ = (BarGraphOptions*)calloc(1, sizeof(BarGraphOptions)); + BarGraphOptions* ops = (BarGraphOptions*)ops_; + + barGroups_ =NULL; + nBarGroups_ =0; + maxBarSetSize_ =0; + + Tcl_InitHashTable(&setTable_, sizeof(BarSetKey) / sizeof(int)); + + ops->bottomMargin.site = MARGIN_BOTTOM; + ops->leftMargin.site = MARGIN_LEFT; + ops->topMargin.site = MARGIN_TOP; + ops->rightMargin.site = MARGIN_RIGHT; + + Blt_Ts_InitStyle(ops->titleTextStyle); + ops->titleTextStyle.anchor = TK_ANCHOR_N; + + if (createPen("active", 0, NULL) != TCL_OK) { + valid_ =0; + return; + } + + if ((Tk_InitOptions(interp_, (char*)ops_, optionTable_, tkwin_) != TCL_OK) || (GraphObjConfigure(interp_, this, objc-2, objv+2) != TCL_OK)) { + valid_ =0; + return; + } + + adjustAxes(); + + Tcl_SetStringObj(Tcl_GetObjResult(interp_), Tk_PathName(tkwin_), -1); +} + +BarGraph::~BarGraph() +{ + Blt_DestroyBarSets(this); +} + +void BarGraph::configure() +{ + BarGraphOptions* ops = (BarGraphOptions*)ops_; + // Don't allow negative bar widths. Reset to an arbitrary value (0.1) + if (ops->barWidth <= 0.0f) + ops->barWidth = 0.8f; + + Graph::configure(); +} + +int BarGraph::createPen(const char* penName, int objc, Tcl_Obj* const objv[]) +{ + int isNew; + Tcl_HashEntry *hPtr = + Tcl_CreateHashEntry(&penTable_, penName, &isNew); + if (!isNew) { + Tcl_AppendResult(interp_, "pen \"", penName, "\" already exists in \"", + Tk_PathName(tkwin_), "\"", (char *)NULL); + return TCL_ERROR; + } + + Pen* penPtr = new BarPen(this, penName, hPtr); + if (!penPtr) + return TCL_ERROR; + + Tcl_SetHashValue(hPtr, penPtr); + + if ((Tk_InitOptions(interp_, (char*)penPtr->ops(), penPtr->optionTable(), tkwin_) != TCL_OK) || (PenObjConfigure(interp_, this, penPtr, objc-4, objv+4) != TCL_OK)) { + delete penPtr; + return TCL_ERROR; + } + + flags |= CACHE_DIRTY; + eventuallyRedraw(); + + return TCL_OK; +} + +int BarGraph::createElement(int objc, Tcl_Obj* const objv[]) +{ + char *name = Tcl_GetString(objv[3]); + if (name[0] == '-') { + Tcl_AppendResult(interp_, "name of element \"", name, + "\" can't start with a '-'", NULL); + return TCL_ERROR; + } + + int isNew; + Tcl_HashEntry* hPtr = + Tcl_CreateHashEntry(&elements_.table, name, &isNew); + if (!isNew) { + Tcl_AppendResult(interp_, "element \"", name, + "\" already exists in \"", Tcl_GetString(objv[0]), + "\"", NULL); + return TCL_ERROR; + } + + Element* elemPtr = new BarElement(this, name, hPtr); + if (!elemPtr) + return TCL_ERROR; + + Tcl_SetHashValue(hPtr, elemPtr); + + if ((Tk_InitOptions(interp_, (char*)elemPtr->ops(), elemPtr->optionTable(), tkwin_) != TCL_OK) || (ElementObjConfigure(interp_, elemPtr, objc-4, objv+4) != TCL_OK)) { + delete elemPtr; + return TCL_ERROR; + } + + elemPtr->link = Blt_Chain_Append(elements_.displayList, elemPtr); + + return TCL_OK; +} + +void BarGraph::mapElements() +{ + BarGraphOptions* ops = (BarGraphOptions*)ops_; + if (ops->barMode != BARS_INFRONT) + Blt_ResetBarGroups(this); + + Graph::mapElements(); +} + +void BarGraph::resetAxes() +{ + BarGraphOptions* ops = (BarGraphOptions*)ops_; + + /* FIXME: This should be called whenever the display list of + * elements change. Maybe yet another flag INIT_STACKS to + * indicate that the element display list has changed. + * Needs to be done before the axis limits are set. + */ + Blt_InitBarSetTable(this); + if ((ops->barMode == BARS_STACKED) && (nBarGroups_ > 0)) + Blt_ComputeBarStacks(this); + + Graph::resetAxes(); +} diff --git a/src/bltGraphBar.h b/src/bltGraphBar.h new file mode 100644 index 0000000..4caae15 --- /dev/null +++ b/src/bltGraphBar.h @@ -0,0 +1,110 @@ +/* + * Smithsonian Astrophysical Observatory, Cambridge, MA, USA + * This code has been modified under the terms listed below and is made + * available under the same terms. + */ + +/* + * Copyright 1993-2004 George A Howlett. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BltGraphBar_h__ +#define __BltGraphBar_h__ + +extern "C" { +#include "bltGraph.h" +}; + +typedef struct { + int nSegments; + Axis2d axes; + float sum; + int count; + float lastY; + size_t index; +} BarGroup; + +typedef struct { + float value; + Axis2d axes; +} BarSetKey; + +typedef enum { + BARS_INFRONT, BARS_STACKED, BARS_ALIGNED, BARS_OVERLAP +} BarMode; + +typedef struct { + double aspect; + Tk_3DBorder normalBg; + int borderWidth; + Margin margins[4]; + int backingStore; + int doubleBuffer; + Tk_Cursor cursor; + TextStyle titleTextStyle; + int reqHeight; + XColor* highlightBgColor; + XColor* highlightColor; + int highlightWidth; + int inverted; + Tk_3DBorder plotBg; + int plotBW; + int xPad; + int yPad; + int plotRelief; + int relief; + ClosestSearch search; + int stackAxes; + const char *takeFocus; // nor used in C code + const char *title; + int reqWidth; + int reqPlotWidth; + int reqPlotHeight; + + // bar graph + BarMode barMode; + double barWidth; + double baseline; +} BarGraphOptions; + +class BarGraph : public Graph { + public: + BarGroup *barGroups_; + int nBarGroups_; + Tcl_HashTable setTable_; + int maxBarSetSize_; + + protected: + void resetAxes(); + void mapElements(); + + public: + BarGraph(ClientData, Tcl_Interp*, int, Tcl_Obj* const []); + virtual ~BarGraph(); + + void configure(); + int createPen(const char*, int, Tcl_Obj* const []); + int createElement(int, Tcl_Obj* const []); + +}; + +#endif diff --git a/src/bltGraphLine.C b/src/bltGraphLine.C new file mode 100644 index 0000000..0480c71 --- /dev/null +++ b/src/bltGraphLine.C @@ -0,0 +1,277 @@ +/* + * Smithsonian Astrophysical Observatory, Cambridge, MA, USA + * This code has been modified under the terms listed below and is made + * available under the same terms. + */ + +/* + * Copyright 1991-2004 George A Howlett. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +extern "C" { +#include "bltGraphLine.h" +} + +#include "bltGraphOp.h" + +#include "bltGrAxis.h" +#include "bltGrAxisOp.h" +#include "bltGrXAxisOp.h" +#include "bltGrPen.h" +#include "bltGrPenBar.h" +#include "bltGrPenLine.h" +#include "bltGrPenOp.h" +#include "bltGrElem.h" +#include "bltGrElemBar.h" +#include "bltGrElemLine.h" +#include "bltGrElemOp.h" +#include "bltGrMarker.h" +#include "bltGrMarkerOp.h" +#include "bltGrLegd.h" +#include "bltGrLegdOp.h" +#include "bltGrHairs.h" +#include "bltGrHairsOp.h" +#include "bltGrDef.h" + +using namespace Blt; + +static const char* searchModeObjOption[] = {"points", "traces", "auto", NULL}; +static const char* searchAlongObjOption[] = {"x", "y", "both", NULL}; + +static Tk_OptionSpec optionSpecs[] = { + {TK_OPTION_DOUBLE, "-aspect", "aspect", "Aspect", + "0", -1, Tk_Offset(GraphOptions, aspect), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_BORDER, "-background", "background", "Background", + STD_NORMAL_BACKGROUND, -1, Tk_Offset(GraphOptions, normalBg), + 0, NULL, CACHE_DIRTY}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, -1, 0, 0, "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, -1, 0, 0, "-background", 0}, + {TK_OPTION_SYNONYM, "-bm", NULL, NULL, NULL, -1, 0, 0, "-bottommargin", 0}, + {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", + STD_BORDERWIDTH, -1, Tk_Offset(GraphOptions, borderWidth), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-bottommargin", "bottomMargin", "BottomMargin", + "0", -1, Tk_Offset(GraphOptions, bottomMargin.reqSize), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-bottomvariable", "bottomVariable", "BottomVariable", + NULL, -1, Tk_Offset(GraphOptions, bottomMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_BOOLEAN, "-bufferelements", "bufferElements", "BufferElements", + "yes", -1, Tk_Offset(GraphOptions, backingStore), 0, NULL, 0}, + {TK_OPTION_BOOLEAN, "-buffergraph", "bufferGraph", "BufferGraph", + "yes", -1, Tk_Offset(GraphOptions, doubleBuffer), 0, NULL, 0}, + {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", + "crosshair", -1, Tk_Offset(GraphOptions, cursor), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, + {TK_OPTION_FONT, "-font", "font", "Font", + STD_FONT_MEDIUM, -1, Tk_Offset(GraphOptions, titleTextStyle.font), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", + STD_NORMAL_FOREGROUND, -1, Tk_Offset(GraphOptions, titleTextStyle.color), + 0, NULL, + CACHE_DIRTY}, + {TK_OPTION_SYNONYM, "-halo", NULL, NULL, NULL, -1, 0, 0, "-searchhalo", 0}, + {TK_OPTION_PIXELS, "-height", "height", "Height", + "4i", -1, Tk_Offset(GraphOptions, reqHeight), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", + "HighlightBackground", + STD_NORMAL_BACKGROUND, -1, Tk_Offset(GraphOptions, highlightBgColor), + 0, NULL, + CACHE_DIRTY}, + {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", + STD_NORMAL_FOREGROUND, -1, Tk_Offset(GraphOptions, highlightColor), + 0, NULL, 0}, + {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", + "HighlightThickness", + "2", -1, Tk_Offset(GraphOptions, highlightWidth), 0, NULL, 0}, + {TK_OPTION_BOOLEAN, "-invertxy", "invertXY", "InvertXY", + "no", -1, Tk_Offset(GraphOptions, inverted), 0, NULL, + RESET_WORLD | CACHE_DIRTY | RESET_AXES}, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "center", -1, Tk_Offset(GraphOptions, titleTextStyle.justify), 0, NULL, 0}, + {TK_OPTION_PIXELS, "-leftmargin", "leftMargin", "Margin", + "0", -1, Tk_Offset(GraphOptions, leftMargin.reqSize), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-leftvariable", "leftVariable", "LeftVariable", + NULL, -1, Tk_Offset(GraphOptions, leftMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_SYNONYM, "-lm", NULL, NULL, NULL, -1, 0, 0, "-leftmargin", 0}, + {TK_OPTION_BORDER, "-plotbackground", "plotbackground", "PlotBackground", + STD_NORMAL_BACKGROUND, -1, Tk_Offset(GraphOptions, plotBg), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotborderwidth", "plotBorderWidth", "PlotBorderWidth", + STD_BORDERWIDTH, -1, Tk_Offset(GraphOptions, plotBW), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotpadx", "plotPadX", "PlotPad", + "0", -1, Tk_Offset(GraphOptions, xPad), 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotpady", "plotPadY", "PlotPad", + "0", -1, Tk_Offset(GraphOptions, yPad), 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_RELIEF, "-plotrelief", "plotRelief", "Relief", + "flat", -1, Tk_Offset(GraphOptions, plotRelief), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", + "flat", -1, Tk_Offset(GraphOptions, relief), 0, NULL, 0}, + {TK_OPTION_PIXELS, "-rightmargin", "rightMargin", "Margin", + "0", -1, Tk_Offset(GraphOptions, rightMargin.reqSize), 0, NULL, + RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-rightvariable", "rightVariable", "RightVariable", + NULL, -1, Tk_Offset(GraphOptions, rightMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_SYNONYM, "-rm", NULL, NULL, NULL, -1, 0, 0, "-rightmargin", 0}, + {TK_OPTION_PIXELS, "-searchhalo", "searchhalo", "SearchHalo", + "2m", -1, Tk_Offset(GraphOptions, search.halo), 0, NULL, 0}, + {TK_OPTION_STRING_TABLE, "-searchmode", "searchMode", "SearchMode", + "points", -1, Tk_Offset(GraphOptions, search.mode), + 0, &searchModeObjOption, 0}, + {TK_OPTION_STRING_TABLE, "-searchalong", "searchAlong", "SearchAlong", + "both", -1, Tk_Offset(GraphOptions, search.along), + 0, &searchAlongObjOption, 0}, + {TK_OPTION_BOOLEAN, "-stackaxes", "stackAxes", "StackAxes", + "no", -1, Tk_Offset(GraphOptions, stackAxes), 0, NULL, 0}, + {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", + NULL, -1, Tk_Offset(GraphOptions, takeFocus), TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_STRING, "-title", "title", "Title", + NULL, -1, Tk_Offset(GraphOptions, title), + TK_OPTION_NULL_OK, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_SYNONYM, "-tm", NULL, NULL, NULL, -1, 0, 0, "-topmargin", 0}, + {TK_OPTION_PIXELS, "-topmargin", "topMargin", "TopMargin", + "0", -1, Tk_Offset(GraphOptions, topMargin.reqSize), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_STRING, "-topvariable", "topVariable", "TopVariable", + NULL, -1, Tk_Offset(GraphOptions, topMargin.varName), + TK_OPTION_NULL_OK, NULL, 0}, + {TK_OPTION_PIXELS, "-width", "width", "Width", + "5i", -1, Tk_Offset(GraphOptions, reqWidth), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotwidth", "plotWidth", "PlotWidth", + "0", -1, Tk_Offset(GraphOptions, reqPlotWidth), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_PIXELS, "-plotheight", "plotHeight", "PlotHeight", + "0", -1, Tk_Offset(GraphOptions, reqPlotHeight), + 0, NULL, RESET_WORLD | CACHE_DIRTY}, + {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} +}; + +// Create + +LineGraph::LineGraph(ClientData clientData, Tcl_Interp* interp, + int objc, Tcl_Obj* const objv[]) + : Graph(clientData, interp, objc, objv) +{ + optionTable_ = Tk_CreateOptionTable(interp_, optionSpecs); + ops_ = (LineGraphOptions*)calloc(1, sizeof(LineGraphOptions)); + LineGraphOptions* ops = (LineGraphOptions*)ops_; + + Tk_SetClass(tkwin_, "Graph"); + classId_ = CID_ELEM_LINE; + if (createPen("active", 0, NULL) != TCL_OK) { + valid_ =0; + return; + } + + ops->bottomMargin.site = MARGIN_BOTTOM; + ops->leftMargin.site = MARGIN_LEFT; + ops->topMargin.site = MARGIN_TOP; + ops->rightMargin.site = MARGIN_RIGHT; + + Blt_Ts_InitStyle(ops->titleTextStyle); + ops->titleTextStyle.anchor = TK_ANCHOR_N; + + if ((Tk_InitOptions(interp_, (char*)ops_, optionTable_, tkwin_) != TCL_OK) || (GraphObjConfigure(interp_, this, objc-2, objv+2) != TCL_OK)) { + valid_ =0; + return; + } + + adjustAxes(); + + Tcl_SetStringObj(Tcl_GetObjResult(interp_), Tk_PathName(tkwin_), -1); +} + +LineGraph::~LineGraph() +{ +} + +int LineGraph::createPen(const char* penName, int objc, Tcl_Obj* const objv[]) +{ + int isNew; + Tcl_HashEntry *hPtr = + Tcl_CreateHashEntry(&penTable_, penName, &isNew); + if (!isNew) { + Tcl_AppendResult(interp_, "pen \"", penName, "\" already exists in \"", + Tk_PathName(tkwin_), "\"", (char *)NULL); + return TCL_ERROR; + } + + Pen* penPtr = new LinePen(this, penName, hPtr); + if (!penPtr) + return TCL_ERROR; + + Tcl_SetHashValue(hPtr, penPtr); + + if ((Tk_InitOptions(interp_, (char*)penPtr->ops(), penPtr->optionTable(), tkwin_) != TCL_OK) || (PenObjConfigure(interp_, this, penPtr, objc-4, objv+4) != TCL_OK)) { + delete penPtr; + return TCL_ERROR; + } + + flags |= CACHE_DIRTY; + eventuallyRedraw(); + + return TCL_OK; +} + +int LineGraph::createElement(int objc, Tcl_Obj* const objv[]) +{ + char *name = Tcl_GetString(objv[3]); + if (name[0] == '-') { + Tcl_AppendResult(interp_, "name of element \"", name, + "\" can't start with a '-'", NULL); + return TCL_ERROR; + } + + int isNew; + Tcl_HashEntry* hPtr = + Tcl_CreateHashEntry(&elements_.table, name, &isNew); + if (!isNew) { + Tcl_AppendResult(interp_, "element \"", name, + "\" already exists in \"", Tcl_GetString(objv[0]), + "\"", NULL); + return TCL_ERROR; + } + + Element* elemPtr = new LineElement(this, name, hPtr); + if (!elemPtr) + return TCL_ERROR; + + Tcl_SetHashValue(hPtr, elemPtr); + + if ((Tk_InitOptions(interp_, (char*)elemPtr->ops(), elemPtr->optionTable(), tkwin_) != TCL_OK) || (ElementObjConfigure(interp_, elemPtr, objc-4, objv+4) != TCL_OK)) { + delete elemPtr; + return TCL_ERROR; + } + + elemPtr->link = Blt_Chain_Append(elements_.displayList, elemPtr); + + return TCL_OK; +} diff --git a/src/bltGraphLine.h b/src/bltGraphLine.h new file mode 100644 index 0000000..595a10e --- /dev/null +++ b/src/bltGraphLine.h @@ -0,0 +1,77 @@ +/* + * Smithsonian Astrophysical Observatory, Cambridge, MA, USA + * This code has been modified under the terms listed below and is made + * available under the same terms. + */ + +/* + * Copyright 1993-2004 George A Howlett. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BltGraphLine_h__ +#define __BltGraphLine_h__ + +extern "C" { +#include "bltGraph.h" +}; + +typedef struct { + double aspect; + Tk_3DBorder normalBg; + int borderWidth; + Margin margins[4]; + int backingStore; + int doubleBuffer; + Tk_Cursor cursor; + TextStyle titleTextStyle; + int reqHeight; + XColor* highlightBgColor; + XColor* highlightColor; + int highlightWidth; + int inverted; + Tk_3DBorder plotBg; + int plotBW; + int xPad; + int yPad; + int plotRelief; + int relief; + ClosestSearch search; + int stackAxes; + const char *takeFocus; // nor used in C code + const char *title; + int reqWidth; + int reqPlotWidth; + int reqPlotHeight; + + // line graph +} LineGraphOptions; + +class LineGraph : public Graph { + public: + LineGraph(ClientData, Tcl_Interp*, int objc, Tcl_Obj* const []); + virtual ~LineGraph(); + + int createElement(int, Tcl_Obj* const []); + int createPen(const char*, int, Tcl_Obj* const []); +}; + +#endif diff --git a/src/bltGraphOp.C b/src/bltGraphOp.C index 2798fed..3de03aa 100644 --- a/src/bltGraphOp.C +++ b/src/bltGraphOp.C @@ -32,7 +32,8 @@ extern "C" { #include "bltInt.h" #include "bltList.h" -#include "bltGraph.h" +#include "bltGraphLine.h" +#include "bltGraphBar.h" #include "bltOp.h" } @@ -83,7 +84,7 @@ static int GraphObjCmd(ClientData clientData, Tcl_Interp* interp, int objc, return TCL_ERROR; } - Graph* graphPtr = new Graph(clientData, interp, objc, objv, CID_ELEM_LINE); + Graph* graphPtr = new LineGraph(clientData, interp, objc, objv); return graphPtr->valid_ ? TCL_OK : TCL_ERROR; } @@ -95,7 +96,7 @@ static int BarchartObjCmd(ClientData clientData, Tcl_Interp* interp, int objc, return TCL_ERROR; } - Graph* graphPtr = new Graph(clientData, interp, objc, objv, CID_ELEM_BAR); + Graph* graphPtr = new BarGraph(clientData, interp, objc, objv); return graphPtr->valid_ ? TCL_OK : TCL_ERROR; } |