diff options
author | joye <joye> | 2014-04-17 17:29:14 (GMT) |
---|---|---|
committer | joye <joye> | 2014-04-17 17:29:14 (GMT) |
commit | 9caebde9f70de2451a69021472ab824182e88fa1 (patch) | |
tree | b345e006f0eef3fb5d6a815ebb572cdc319a32bf /src | |
parent | 5203b01c7d32185f31ad84a0cf1040b90adb1d42 (diff) | |
download | blt-9caebde9f70de2451a69021472ab824182e88fa1.zip blt-9caebde9f70de2451a69021472ab824182e88fa1.tar.gz blt-9caebde9f70de2451a69021472ab824182e88fa1.tar.bz2 |
*** empty log message ***
Diffstat (limited to 'src')
-rw-r--r-- | src/bltGrAxis.C | 2 | ||||
-rw-r--r-- | src/bltGraph.C | 441 | ||||
-rw-r--r-- | src/bltGraph.h | 1 |
3 files changed, 250 insertions, 194 deletions
diff --git a/src/bltGrAxis.C b/src/bltGrAxis.C index 49552f8..5ea79a3 100644 --- a/src/bltGrAxis.C +++ b/src/bltGrAxis.C @@ -1747,7 +1747,7 @@ void Axis::printGrids(Blt_Ps ps) AxisOptions* ops = (AxisOptions*)ops_; if (ops->hide || !ops->showGrid || !use_ || (flags & DELETE_PENDING)) - continue; + return; Blt_Ps_Format(ps, "%% Axis %s: grid line attributes\n", name()); Blt_Ps_XSetLineAttributes(ps, ops->major.color, ops->major.lineWidth, diff --git a/src/bltGraph.C b/src/bltGraph.C index c30f7f5..c768dbc 100644 --- a/src/bltGraph.C +++ b/src/bltGraph.C @@ -57,6 +57,8 @@ using namespace Blt; extern int Blt_CreatePageSetup(Graph* graphPtr); extern void Blt_DestroyPageSetup(Graph* graphPtr); extern void Blt_LayoutGraph(Graph* graphPtr); +extern int PostScriptPreamble(Graph* graphPtr, const char *fileName, Blt_Ps ps); +extern void MarginsToPostScript(Graph* graphPtr, Blt_Ps ps); static Blt_BindPickProc PickEntry; @@ -527,6 +529,7 @@ void Graph::map() void Graph::drawPlot(Drawable drawable) { GraphOptions* ops = (GraphOptions*)ops_; + drawMargins(drawable); // Draw the background of the plotting area with 3D border @@ -537,9 +540,9 @@ void Graph::drawPlot(Drawable drawable) bottom_ - top_ + 1 + 2*ops->plotBW, ops->plotBW, ops->plotRelief); - // Draw the elements, markers, legend, and axis limits drawAxes(drawable); drawAxesGrids(drawable); + drawAxesLimits(drawable); drawMarkers(drawable, MARKER_UNDER); if (!legend_->isRaised()) { @@ -553,64 +556,16 @@ void Graph::drawPlot(Drawable drawable) } } - drawAxesLimits(drawable); drawElements(drawable); } -/* - *--------------------------------------------------------------------------- - * - * DrawMargins -- - * - * Draws the exterior region of the graph (axes, ticks, titles, etc) - * onto a pixmap. The interior region is defined by the given rectangle - * structure. - * - * --------------------------------- - * | | - * | rectArr[0] | - * | | - * --------------------------------- - * | |top right| | - * | | | | - * | | | | - * | [1] | | [2] | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | |left bottom| | - * --------------------------------- - * | | - * | rectArr[3] | - * | | - * --------------------------------- - * - * X coordinate axis - * Y coordinate axis - * legend - * interior border - * exterior border - * titles (X and Y axis, graph) - * - * Returns: - * None. - * - * Side Effects: - * Exterior of graph is displayed in its window. - * - *--------------------------------------------------------------------------- - */ void Graph::drawMargins(Drawable drawable) { GraphOptions* ops = (GraphOptions*)ops_; XRectangle rects[4]; - /* - * Draw the four outer rectangles which encompass the plotting - * surface. This clears the surrounding area and clips the plot. - */ + // Draw the four outer rectangles which encompass the plotting + // surface. This clears the surrounding area and clips the plot. rects[0].x = rects[0].y = rects[3].x = rects[1].x = 0; rects[0].width = rects[3].width = (short int)width_; rects[0].height = (short int)top_; @@ -635,8 +590,7 @@ void Graph::drawMargins(Drawable drawable) rects[3].x, rects[3].y, rects[3].width, rects[3].height, 0, TK_RELIEF_FLAT); - /* Draw 3D border around the plotting area */ - + // Draw 3D border around the plotting area if (ops->plotBW > 0) { int x, y, w, h; @@ -659,7 +613,7 @@ void Graph::drawMargins(Drawable drawable) break; } - if (ops->title != NULL) + if (ops->title) Blt_DrawText(tkwin_, drawable, ops->title, &ops->titleTextStyle, titleX_, titleY_); @@ -667,6 +621,111 @@ void Graph::drawMargins(Drawable drawable) flags &= ~DRAW_MARGINS; } +int Graph::print(const char *ident, Blt_Ps ps) +{ + GraphOptions* gops = (GraphOptions*)ops_; + PageSetup *setupPtr = pageSetup_; + + // We need to know how big a graph to print. If the graph hasn't been drawn + // yet, the width and height will be 1. Instead use the requested size of + // the widget. The user can still override this with the -width and -height + // postscript options. + if (setupPtr->reqWidth > 0) + width_ = setupPtr->reqWidth; + else if (width_ < 2) + width_ = Tk_ReqWidth(tkwin_); + + if (setupPtr->reqHeight > 0) + height_ = setupPtr->reqHeight; + else if (height_ < 2) + height_ = Tk_ReqHeight(tkwin_); + + Blt_Ps_ComputeBoundingBox(setupPtr, width_, height_); + flags |= LAYOUT_NEEDED | RESET_WORLD; + + /* Turn on PostScript measurements when computing the graph's layout. */ + Blt_Ps_SetPrinting(ps, 1); + reconfigure(); + map(); + + int x = left_ - gops->plotBW; + int y = top_ - gops->plotBW; + + int w = (right_ - left_ + 1) + (2*gops->plotBW); + int h = (bottom_ - top_ + 1) + (2*gops->plotBW); + + int result = PostScriptPreamble(this, ident, ps); + if (result != TCL_OK) + goto error; + + Blt_Ps_XSetFont(ps, gops->titleTextStyle.font); + if (pageSetup_->decorations) + Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(gops->plotBg)); + else + Blt_Ps_SetClearBackground(ps); + + Blt_Ps_XFillRectangle(ps, x, y, w, h); + Blt_Ps_Rectangle(ps, x, y, w, h); + Blt_Ps_Append(ps, "gsave clip\n\n"); + + // Draw the grid, elements, and markers in the plotting area + printAxesGrids(ps); + printAxesLimits(ps); + printMarkers(ps, 1); + + // Print legend underneath elements and markers + if (!legend_->isRaised()) { + switch (legend_->position()) { + case Legend::PLOT: + case Legend::XY: + legend_->print(ps); + break; + default: + break; + } + } + + printElements(ps); + + // Print legend above elements (but not markers) + if (legend_->isRaised()) { + switch (legend_->position()) { + case Legend::PLOT: + case Legend::XY: + legend_->print(ps); + break; + default: + break; + } + } + + printMarkers(ps, 0); + printActiveElements(ps); + Blt_Ps_VarAppend(ps, "\n", + "% Unset clipping\n", + "grestore\n\n", (char *)NULL); + MarginsToPostScript(this, ps); + Blt_Ps_VarAppend(ps, + "showpage\n", + "%Trailer\n", + "grestore\n", + "end\n", + "%EOF\n", (char *)NULL); + error: + width_ = Tk_Width(tkwin_); + height_ = Tk_Height(tkwin_); + flags |= MAP_WORLD; + Blt_Ps_SetPrinting(ps, 0); + reconfigure(); + map(); + + // Redraw the graph in order to re-calculate the layout as soon as + // possible. This is in the case the crosshairs are active. + eventuallyRedraw(); + + return result; +} + void Graph::eventuallyRedraw() { if ((flags & GRAPH_DELETED) || !Tk_IsMapped(tkwin_)) @@ -737,131 +796,6 @@ void Graph::reconfigure() // Support -void Blt_GraphTags(Blt_BindTable table, ClientData object, ClientData context, - Blt_List list) -{ - Graph* graphPtr = (Graph*)Blt_GetBindingData(table); - ClassId classId = (ClassId)(long(context)); - - switch (classId) { - case CID_ELEM_BAR: - case CID_ELEM_LINE: - { - Element* elemPtr = (Element*)object; - ElementOptions* ops = (ElementOptions*)elemPtr->ops(); - MakeTagProc* tagProc = Blt_MakeElementTag; - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, elemPtr->name()), 0); - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, elemPtr->className()), 0); - if (ops->tags) - for (const char** p = ops->tags; *p != NULL; p++) - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, *p), 0); - } - break; - case CID_AXIS_X: - case CID_AXIS_Y: - { - Axis* axisPtr = (Axis*)object; - AxisOptions* ops = (AxisOptions*)axisPtr->ops(); - MakeTagProc* tagProc = Blt_MakeAxisTag; - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, axisPtr->name()), 0); - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, axisPtr->className()), 0); - if (ops->tags) - for (const char** p = ops->tags; *p != NULL; p++) - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, *p), 0); - } - break; - case CID_MARKER_BITMAP: - case CID_MARKER_LINE: - case CID_MARKER_POLYGON: - case CID_MARKER_TEXT: - case CID_MARKER_WINDOW: - { - Marker* markerPtr = (Marker*)object; - MarkerOptions* ops = (MarkerOptions*)markerPtr->ops(); - MakeTagProc* tagProc = Blt::MakeMarkerTag; - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, markerPtr->name()), 0); - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, markerPtr->className()), 0); - if (ops->tags) - for (const char** p = ops->tags; *p != NULL; p++) - Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, *p), 0); - - } - break; - default: - break; - } -} - -// Find the closest point from the set of displayed elements, searching -// the display list from back to front. That way, if the points from -// two different elements overlay each other exactly, the one that's on -// top (visible) is picked. -static ClientData PickEntry(ClientData clientData, int x, int y, - ClientData* contextPtr) -{ - Graph* graphPtr = (Graph*)clientData; - GraphOptions* ops = (GraphOptions*)graphPtr->ops_; - - if (graphPtr->flags & MAP_ALL) { - *contextPtr = (ClientData)NULL; - return NULL; - } - - Region2d exts; - graphPtr->extents(&exts); - - // Sample coordinate is in one of the graph margins. Can only pick an axis. - if ((x >= exts.right) || (x < exts.left) || - (y >= exts.bottom) || (y < exts.top)) { - Axis* axisPtr = Blt_NearestAxis(graphPtr, x, y); - if (axisPtr) { - *contextPtr = (ClientData)axisPtr->classId(); - return axisPtr; - } - } - - // From top-to-bottom check: - // 1. markers drawn on top (-under false). - // 2. elements using its display list back to front. - // 3. markers drawn under element (-under true). - Marker* markerPtr = graphPtr->nearestMarker(x, y, 0); - if (markerPtr) { - *contextPtr = (ClientData)markerPtr->classId(); - return markerPtr; - } - - ClosestSearch* searchPtr = &ops->search; - searchPtr->index = -1; - searchPtr->x = x; - searchPtr->y = y; - searchPtr->dist = (double)(searchPtr->halo + 1); - - Blt_ChainLink link; - Element* elemPtr; - for (link = Blt_Chain_LastLink(graphPtr->elements_.displayList); - link != NULL; link = Blt_Chain_PrevLink(link)) { - elemPtr = (Element*)Blt_Chain_GetValue(link); - if (elemPtr->hide() || (elemPtr->flags & MAP_ITEM)) - continue; - - elemPtr->closest(); - } - // Found an element within the minimum halo distance. - if (searchPtr->dist <= (double)searchPtr->halo) { - *contextPtr = (ClientData)elemPtr->classId(); - return searchPtr->elemPtr; - } - - markerPtr = graphPtr->nearestMarker(x, y, 1); - if (markerPtr) { - *contextPtr = (ClientData)markerPtr->classId(); - return markerPtr; - } - - *contextPtr = (ClientData)NULL; - return NULL; -} - // Crosshairs void Graph::enableCrosshairs() @@ -1140,10 +1074,11 @@ void Graph::configureAxes() void Graph::mapAxes() { GraphOptions* gops = (GraphOptions*)ops_; - for (int margin = 0; margin < 4; margin++) { + + for (int ii=0; ii<4; ii++) { int count =0; int offset =0; - Blt_Chain chain = gops->margins[margin].axes; + Blt_Chain chain = gops->margins[ii].axes; for (Blt_ChainLink link=Blt_Chain_FirstLink(chain); link; link = Blt_Chain_NextLink(link)) { Axis *axisPtr = (Axis*)Blt_Chain_GetValue(link); @@ -1151,18 +1086,13 @@ void Graph::mapAxes() if (!axisPtr->use_ || (axisPtr->flags & DELETE_PENDING)) continue; - if (gops->stackAxes) { - if (ops->reqNumMajorTicks <= 0) - ops->reqNumMajorTicks = 4; - - axisPtr->mapStacked(count, margin); - } - else { - if (ops->reqNumMajorTicks <= 0) - ops->reqNumMajorTicks = 4; + if (ops->reqNumMajorTicks <= 0) + ops->reqNumMajorTicks = 4; - axisPtr->map(offset, margin); - } + if (gops->stackAxes) + axisPtr->mapStacked(count, ii); + else + axisPtr->map(offset, ii); if (ops->showGrid) axisPtr->mapGridlines(); @@ -1225,7 +1155,7 @@ void Graph::printAxes(Blt_Ps ps) void Graph::printAxesGrids(Blt_Ps ps) { - GraphOptions* gops = (GraphOptions*)graphPtr->ops_; + GraphOptions* gops = (GraphOptions*)ops_; for (int ii=0; ii<4; ii++) { for (Blt_ChainLink link=Blt_Chain_FirstLink(gops->margins[ii].axes); @@ -1322,3 +1252,128 @@ void Graph::resetAxes() } +void Blt_GraphTags(Blt_BindTable table, ClientData object, ClientData context, + Blt_List list) +{ + Graph* graphPtr = (Graph*)Blt_GetBindingData(table); + ClassId classId = (ClassId)(long(context)); + + switch (classId) { + case CID_ELEM_BAR: + case CID_ELEM_LINE: + { + Element* elemPtr = (Element*)object; + ElementOptions* ops = (ElementOptions*)elemPtr->ops(); + MakeTagProc* tagProc = Blt_MakeElementTag; + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, elemPtr->name()), 0); + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, elemPtr->className()), 0); + if (ops->tags) + for (const char** p = ops->tags; *p != NULL; p++) + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, *p), 0); + } + break; + case CID_AXIS_X: + case CID_AXIS_Y: + { + Axis* axisPtr = (Axis*)object; + AxisOptions* ops = (AxisOptions*)axisPtr->ops(); + MakeTagProc* tagProc = Blt_MakeAxisTag; + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, axisPtr->name()), 0); + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, axisPtr->className()), 0); + if (ops->tags) + for (const char** p = ops->tags; *p != NULL; p++) + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, *p), 0); + } + break; + case CID_MARKER_BITMAP: + case CID_MARKER_LINE: + case CID_MARKER_POLYGON: + case CID_MARKER_TEXT: + case CID_MARKER_WINDOW: + { + Marker* markerPtr = (Marker*)object; + MarkerOptions* ops = (MarkerOptions*)markerPtr->ops(); + MakeTagProc* tagProc = Blt::MakeMarkerTag; + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, markerPtr->name()), 0); + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, markerPtr->className()), 0); + if (ops->tags) + for (const char** p = ops->tags; *p != NULL; p++) + Blt_List_Append(list, (const char*)(*tagProc)(graphPtr, *p), 0); + + } + break; + default: + break; + } +} + +// Find the closest point from the set of displayed elements, searching +// the display list from back to front. That way, if the points from +// two different elements overlay each other exactly, the one that's on +// top (visible) is picked. +static ClientData PickEntry(ClientData clientData, int x, int y, + ClientData* contextPtr) +{ + Graph* graphPtr = (Graph*)clientData; + GraphOptions* ops = (GraphOptions*)graphPtr->ops_; + + if (graphPtr->flags & MAP_ALL) { + *contextPtr = (ClientData)NULL; + return NULL; + } + + Region2d exts; + graphPtr->extents(&exts); + + // Sample coordinate is in one of the graph margins. Can only pick an axis. + if ((x >= exts.right) || (x < exts.left) || + (y >= exts.bottom) || (y < exts.top)) { + Axis* axisPtr = Blt_NearestAxis(graphPtr, x, y); + if (axisPtr) { + *contextPtr = (ClientData)axisPtr->classId(); + return axisPtr; + } + } + + // From top-to-bottom check: + // 1. markers drawn on top (-under false). + // 2. elements using its display list back to front. + // 3. markers drawn under element (-under true). + Marker* markerPtr = graphPtr->nearestMarker(x, y, 0); + if (markerPtr) { + *contextPtr = (ClientData)markerPtr->classId(); + return markerPtr; + } + + ClosestSearch* searchPtr = &ops->search; + searchPtr->index = -1; + searchPtr->x = x; + searchPtr->y = y; + searchPtr->dist = (double)(searchPtr->halo + 1); + + Blt_ChainLink link; + Element* elemPtr; + for (link = Blt_Chain_LastLink(graphPtr->elements_.displayList); + link != NULL; link = Blt_Chain_PrevLink(link)) { + elemPtr = (Element*)Blt_Chain_GetValue(link); + if (elemPtr->hide() || (elemPtr->flags & MAP_ITEM)) + continue; + + elemPtr->closest(); + } + // Found an element within the minimum halo distance. + if (searchPtr->dist <= (double)searchPtr->halo) { + *contextPtr = (ClientData)elemPtr->classId(); + return searchPtr->elemPtr; + } + + markerPtr = graphPtr->nearestMarker(x, y, 1); + if (markerPtr) { + *contextPtr = (ClientData)markerPtr->classId(); + return markerPtr; + } + + *contextPtr = (ClientData)NULL; + return NULL; +} + diff --git a/src/bltGraph.h b/src/bltGraph.h index 6c3795d..6ab071c 100644 --- a/src/bltGraph.h +++ b/src/bltGraph.h @@ -243,6 +243,7 @@ class Graph { void resetAxes(); void printAxes(Blt_Ps); + void printAxesGrids(Blt_Ps); void printAxesLimits(Blt_Ps); int isElementHidden(Blt::Marker*); |