summaryrefslogtreecommitdiffstats
path: root/tkblt/generic/tkbltGraph.C
diff options
context:
space:
mode:
Diffstat (limited to 'tkblt/generic/tkbltGraph.C')
-rw-r--r--tkblt/generic/tkbltGraph.C1458
1 files changed, 0 insertions, 1458 deletions
diff --git a/tkblt/generic/tkbltGraph.C b/tkblt/generic/tkbltGraph.C
deleted file mode 100644
index f1453dc..0000000
--- a/tkblt/generic/tkbltGraph.C
+++ /dev/null
@@ -1,1458 +0,0 @@
-/*
- * 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.
- */
-
-#include <cfloat>
-#include <cmath>
-
-#include <tkInt.h>
-
-#include "tkbltGraph.h"
-#include "tkbltGraphOp.h"
-
-#include "tkbltGrBind.h"
-#include "tkbltGrAxis.h"
-#include "tkbltGrAxisOp.h"
-#include "tkbltGrXAxisOp.h"
-#include "tkbltGrPen.h"
-#include "tkbltGrPenBar.h"
-#include "tkbltGrPenLine.h"
-#include "tkbltGrElem.h"
-#include "tkbltGrElemBar.h"
-#include "tkbltGrElemLine.h"
-#include "tkbltGrMarker.h"
-#include "tkbltGrLegd.h"
-#include "tkbltGrHairs.h"
-#include "tkbltGrDef.h"
-#include "tkbltGrPostscript.h"
-#include "tkbltGrPSOutput.h"
-#include "tkbltInt.h"
-
-using namespace Blt;
-
-#define MARKER_ABOVE 0
-#define MARKER_UNDER 1
-
-// OptionSpecs
-
-Graph::Graph(ClientData clientData, Tcl_Interp* interp,
- int objc, Tcl_Obj* const objv[])
-{
- valid_ =1;
- interp_ = interp;
- tkwin_ = Tk_CreateWindowFromPath(interp_, Tk_MainWindow(interp_),
- Tcl_GetString(objv[1]), NULL);
- if (!tkwin_) {
- valid_ =0;
- return;
- }
- display_ = Tk_Display(tkwin_);
- ((TkWindow*)tkwin_)->instanceData = this;
-
- cmdToken_ = Tcl_CreateObjCommand(interp_, Tk_PathName(tkwin_),
- GraphInstCmdProc, this,
- GraphInstCmdDeleteProc);
-
- flags = RESET;
- nextMarkerId_ = 1;
-
- inset_ =0;
- titleX_ =0;
- titleY_ =0;
- titleWidth_ =0;
- titleHeight_ =0;
- width_ =0;
- height_ =0;
- left_ =0;
- right_ =0;
- top_ =0;
- bottom_ =0;
- focusPtr_ =NULL;
- halo_ =0;
- drawGC_ =NULL;
- vRange_ =0;
- hRange_ =0;
- vOffset_ =0;
- hOffset_ =0;
- vScale_ =0;
- hScale_ =0;
- cache_ =None;
- cacheWidth_ =0;
- cacheHeight_ =0;
-
- Tcl_InitHashTable(&axes_.table, TCL_STRING_KEYS);
- Tcl_InitHashTable(&axes_.tagTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&elements_.table, TCL_STRING_KEYS);
- Tcl_InitHashTable(&elements_.tagTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&markers_.table, TCL_STRING_KEYS);
- Tcl_InitHashTable(&markers_.tagTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&penTable_, TCL_STRING_KEYS);
-
- axes_.displayList = new Chain();
- elements_.displayList = new Chain();
- markers_.displayList = new Chain();
- bindTable_ = new BindTable(this, this);
-
- // 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_);
-
- Tk_CreateEventHandler(tkwin_,
- ExposureMask|StructureNotifyMask|FocusChangeMask,
- GraphEventProc, this);
-}
-
-Graph::~Graph()
-{
- // GraphOptions* ops = (GraphOptions*)ops_;
-
- destroyMarkers();
- destroyElements(); // must come before legend and others
-
- delete crosshairs_;
- delete legend_;
- delete postscript_;
-
- destroyAxes();
- destroyPens();
-
- delete bindTable_;
-
- if (drawGC_)
- Tk_FreeGC(display_, drawGC_);
-
- if (cache_ != None)
- Tk_FreePixmap(display_, cache_);
-
- Tk_FreeConfigOptions((char*)ops_, optionTable_, tkwin_);
- Tcl_Release(tkwin_);
- tkwin_ = NULL;
-
- free (ops_);
-}
-
-int Graph::configure()
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- inset_ = ops->borderWidth + ops->highlightWidth;
- if ((ops->reqHeight != Tk_ReqHeight(tkwin_)) ||
- (ops->reqWidth != Tk_ReqWidth(tkwin_)))
- Tk_GeometryRequest(tkwin_, ops->reqWidth, ops->reqHeight);
-
- Tk_SetInternalBorder(tkwin_, ops->borderWidth);
- XColor* colorPtr = Tk_3DBorderColor(ops->normalBg);
-
- titleWidth_ =0;
- titleHeight_ =0;
- if (ops->title != NULL) {
- int w, h;
- TextStyle ts(this, &ops->titleTextStyle);
- ts.getExtents(ops->title, &w, &h);
- titleHeight_ = h;
- }
-
- // Create GCs for interior and exterior regions, and a background GC for
- // clearing the margins with XFillRectangle
- // Margin
- XGCValues gcValues;
- gcValues.foreground = ops->titleTextStyle.color->pixel;
- gcValues.background = colorPtr->pixel;
- unsigned long gcMask = (GCForeground | GCBackground);
- GC newGC = Tk_GetGC(tkwin_, gcMask, &gcValues);
- if (drawGC_ != NULL)
- Tk_FreeGC(display_, drawGC_);
- drawGC_ = newGC;
-
- // If the -inverted option changed, we need to readjust the pointers
- // to the axes and recompute the their scales.
- adjustAxes();
-
- // Free the pixmap if we're not buffering the display of elements anymore.
- if (cache_ != None) {
- Tk_FreePixmap(display_, cache_);
- cache_ = None;
- }
-
- return TCL_OK;
-}
-
-void Graph::map()
-{
- if (flags & RESET) {
- resetAxes();
- flags &= ~RESET;
- flags |= LAYOUT;
- }
-
- if (flags & LAYOUT) {
- layoutGraph();
- crosshairs_->map();
- mapAxes();
- mapElements();
- flags &= ~LAYOUT;
- flags |= MAP_MARKERS | CACHE;
- }
-
- mapMarkers();
-}
-
-void Graph::draw()
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- flags &= ~REDRAW_PENDING;
- if ((flags & GRAPH_DELETED) || !Tk_IsMapped(tkwin_))
- return;
-
- // Don't bother computing the layout until the size of the window is
- // something reasonable.
- if ((Tk_Width(tkwin_) <= 1) || (Tk_Height(tkwin_) <= 1))
- return;
-
- width_ = Tk_Width(tkwin_);
- height_ = Tk_Height(tkwin_);
-
- map();
-
- // Create a pixmap the size of the window for double buffering
- Pixmap drawable = Tk_GetPixmap(display_, Tk_WindowId(tkwin_),
- width_, height_, Tk_Depth(tkwin_));
-
- if (cache_ == None || cacheWidth_ != width_ || cacheHeight_ != height_) {
- if (cache_ != None)
- Tk_FreePixmap(display_, cache_);
- cache_ = Tk_GetPixmap(display_, Tk_WindowId(tkwin_), width_, height_,
- Tk_Depth(tkwin_));
- cacheWidth_ = width_;
- cacheHeight_ = height_;
- flags |= CACHE;
- }
-
- // Update cache if needed
- if (flags & CACHE) {
- drawMargins(cache_);
-
- switch (legend_->position()) {
- case Legend::TOP:
- case Legend::BOTTOM:
- case Legend::RIGHT:
- case Legend::LEFT:
- legend_->draw(cache_);
- break;
- default:
- break;
- }
-
- // Draw the background of the plotting area with 3D border
- Tk_Fill3DRectangle(tkwin_, cache_, ops->plotBg,
- left_-ops->plotBW,
- top_-ops->plotBW,
- right_-left_+1+2*ops->plotBW,
- bottom_-top_+1+2*ops->plotBW,
- ops->plotBW, ops->plotRelief);
-
- drawAxesGrids(cache_);
- drawAxes(cache_);
- drawAxesLimits(cache_);
-
- if (!legend_->isRaised()) {
- switch (legend_->position()) {
- case Legend::PLOT:
- case Legend::XY:
- legend_->draw(cache_);
- break;
- default:
- break;
- }
- }
-
- drawMarkers(cache_, MARKER_UNDER);
- drawElements(cache_);
- drawActiveElements(cache_);
-
- if (legend_->isRaised()) {
- switch (legend_->position()) {
- case Legend::PLOT:
- case Legend::XY:
- legend_->draw(cache_);
- break;
- default:
- break;
- }
- }
-
- flags &= ~CACHE;
- }
-
- XCopyArea(display_, cache_, drawable, drawGC_, 0, 0, Tk_Width(tkwin_),
- Tk_Height(tkwin_), 0, 0);
-
- drawMarkers(drawable, MARKER_ABOVE);
-
- // Draw 3D border just inside of the focus highlight ring
- if ((ops->borderWidth > 0) && (ops->relief != TK_RELIEF_FLAT))
- Tk_Draw3DRectangle(tkwin_, drawable, ops->normalBg,
- ops->highlightWidth, ops->highlightWidth,
- width_ - 2*ops->highlightWidth,
- height_ - 2*ops->highlightWidth,
- ops->borderWidth, ops->relief);
-
- // Draw focus highlight ring
- if ((ops->highlightWidth > 0) && (flags & FOCUS)) {
- GC gc = Tk_GCForColor(ops->highlightColor, drawable);
- Tk_DrawFocusHighlight(tkwin_, gc, ops->highlightWidth, drawable);
- }
-
- // crosshairs
- crosshairs_->draw(drawable);
-
- XCopyArea(display_, drawable, Tk_WindowId(tkwin_), drawGC_,
- 0, 0, width_, height_, 0, 0);
-
- Tk_FreePixmap(display_, drawable);
-}
-
-int Graph::print(const char* ident, PSOutput* psPtr)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
- PostscriptOptions* pops = (PostscriptOptions*)postscript_->ops_;
-
- // be sure the window is realized so that relief colors are available
- if (flags & REDRAW_PENDING) {
- flags |= REDRAW_PENDING;
- DisplayGraph(this);
- }
-
- // 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 (pops->reqWidth > 0)
- width_ = pops->reqWidth;
- else if (width_ < 2)
- width_ = Tk_ReqWidth(tkwin_);
-
- if (pops->reqHeight > 0)
- height_ = pops->reqHeight;
- else if (height_ < 2)
- height_ = Tk_ReqHeight(tkwin_);
-
- psPtr->computeBBox(width_, height_);
- flags |= RESET;
-
- // Turn on PostScript measurements when computing the graph's layout.
- reconfigure();
-
- map();
-
- int x = left_ - ops->plotBW;
- int y = top_ - ops->plotBW;
-
- int w = (right_ - left_ + 1) + (2*ops->plotBW);
- int h = (bottom_ - top_ + 1) + (2*ops->plotBW);
-
- int result = psPtr->preamble(ident);
- if (result != TCL_OK)
- goto error;
-
- psPtr->setFont(ops->titleTextStyle.font);
- if (pops->decorations)
- psPtr->setBackground(Tk_3DBorderColor(ops->plotBg));
- else
- psPtr->setClearBackground();
-
- psPtr->fillRectangle(x, y, w, h);
- psPtr->append("gsave\n\n");
-
- // Start
- printMargins(psPtr);
-
- switch (legend_->position()) {
- case Legend::TOP:
- case Legend::BOTTOM:
- case Legend::RIGHT:
- case Legend::LEFT:
- legend_->print(psPtr);
- break;
- default:
- break;
- }
-
- printAxesGrids(psPtr);
- printAxes(psPtr);
- printAxesLimits(psPtr);
-
- if (!legend_->isRaised()) {
- switch (legend_->position()) {
- case Legend::PLOT:
- case Legend::XY:
- legend_->print(psPtr);
- break;
- default:
- break;
- }
- }
-
- printMarkers(psPtr, MARKER_UNDER);
- printElements(psPtr);
- printActiveElements(psPtr);
-
- if (legend_->isRaised()) {
- switch (legend_->position()) {
- case Legend::PLOT:
- case Legend::XY:
- legend_->print(psPtr);
- break;
- default:
- break;
- }
- }
- printMarkers(psPtr, MARKER_ABOVE);
-
- psPtr->append("\n");
- psPtr->append("% Unset clipping\n");
- psPtr->append("grestore\n\n");
- psPtr->append("showpage\n");
- psPtr->append("%Trailer\n");
- psPtr->append("grestore\n");
- psPtr->append("end\n");
- psPtr->append("%EOF\n");
-
- error:
- width_ = Tk_Width(tkwin_);
- height_ = Tk_Height(tkwin_);
- reconfigure();
-
- // Redraw the graph in order to re-calculate the layout as soon as
- // possible. This is in the case the crosshairs are active.
- flags |= LAYOUT;
- eventuallyRedraw();
-
- return result;
-}
-
-void Graph::eventuallyRedraw()
-{
- if (flags & GRAPH_DELETED)
- return;
-
- if (!(flags & REDRAW_PENDING)) {
- flags |= REDRAW_PENDING;
- Tcl_DoWhenIdle(DisplayGraph, this);
- }
-}
-
-void Graph::extents(Region2d* regionPtr)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- regionPtr->left = (double)(hOffset_ - ops->xPad);
- regionPtr->top = (double)(vOffset_ - ops->yPad);
- regionPtr->right = (double)(hOffset_ + hRange_ + ops->xPad);
- regionPtr->bottom = (double)(vOffset_ + vRange_ + ops->yPad);
-}
-
-int Graph::invoke(const Ensemble* ensemble, int cmdIndex,
- int objc, Tcl_Obj* const objv[])
-{
- while (cmdIndex < objc) {
- int index;
- if (Tcl_GetIndexFromObjStruct(interp_, objv[cmdIndex], ensemble, sizeof(ensemble[0]), "command", 0, &index) != TCL_OK)
- return TCL_ERROR;
-
- if (ensemble[index].proc)
- return ensemble[index].proc(this, interp_, objc, objv);
-
- ensemble = ensemble[index].subensemble;
- ++cmdIndex;
- }
-
- Tcl_WrongNumArgs(interp_, cmdIndex, objv, "option ?arg ...?");
- return TCL_ERROR;
-}
-
-void Graph::reconfigure()
-{
- configure();
- legend_->configure();
- configureElements();
- configureAxes();
- configureMarkers();
-}
-
-// Margins
-
-void Graph::drawMargins(Drawable drawable)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
- Rectangle rects[4];
-
- // 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 = width_;
- rects[0].height = top_;
- rects[3].y = bottom_;
- rects[3].height = height_ - bottom_;
- rects[2].y = rects[1].y = top_;
- rects[1].width = left_;
- rects[2].height = rects[1].height = bottom_ - top_;
- rects[2].x = right_;
- rects[2].width = width_ - right_;
-
- Tk_Fill3DRectangle(tkwin_, drawable, ops->normalBg,
- rects[0].x, rects[0].y, rects[0].width, rects[0].height,
- 0, TK_RELIEF_FLAT);
- Tk_Fill3DRectangle(tkwin_, drawable, ops->normalBg,
- rects[1].x, rects[1].y, rects[1].width, rects[1].height,
- 0, TK_RELIEF_FLAT);
- Tk_Fill3DRectangle(tkwin_, drawable, ops->normalBg,
- rects[2].x, rects[2].y, rects[2].width, rects[2].height,
- 0, TK_RELIEF_FLAT);
- Tk_Fill3DRectangle(tkwin_, drawable, ops->normalBg,
- rects[3].x, rects[3].y, rects[3].width, rects[3].height,
- 0, TK_RELIEF_FLAT);
-
- // Draw 3D border around the plotting area
- 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);
- Tk_Draw3DRectangle(tkwin_, drawable, ops->normalBg,
- x, y, w, h, ops->plotBW, ops->plotRelief);
- }
-
- if (ops->title) {
- TextStyle ts(this, &ops->titleTextStyle);
- ts.drawText(drawable, ops->title, titleX_, titleY_);
- }
-}
-
-void Graph::printMargins(PSOutput* psPtr)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
- PostscriptOptions* pops = (PostscriptOptions*)postscript_->ops_;
- Rectangle margin[4];
-
- margin[0].x = margin[0].y = margin[3].x = margin[1].x = 0;
- margin[0].width = margin[3].width = width_;
- margin[0].height = top_;
- margin[3].y = bottom_;
- margin[3].height = height_ - bottom_;
- margin[2].y = margin[1].y = top_;
- margin[1].width = left_;
- margin[2].height = margin[1].height = bottom_ - top_;
- margin[2].x = right_;
- margin[2].width = width_ - right_;
-
- // Clear the surrounding margins and clip the plotting surface
- if (pops->decorations)
- psPtr->setBackground(Tk_3DBorderColor(ops->normalBg));
- else
- psPtr->setClearBackground();
-
- psPtr->append("% Margins\n");
- psPtr->fillRectangles(margin, 4);
-
- if (pops->decorations) {
- psPtr->append("% Interior 3D border\n");
- 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);
- psPtr->print3DRectangle(ops->normalBg, (double)x, (double)y, w, h,
- ops->plotBW, ops->plotRelief);
- }
- }
-
- if (ops->title) {
- psPtr->append("% Graph title\n");
- TextStyle ts(this, &ops->titleTextStyle);
- ts.printText(psPtr, ops->title, titleX_, titleY_);
- }
-}
-
-// Pens
-
-void Graph::destroyPens()
-{
- Tcl_HashSearch iter;
- for (Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(&penTable_, &iter);
- hPtr; hPtr = Tcl_NextHashEntry(&iter)) {
- Pen* penPtr = (Pen*)Tcl_GetHashValue(hPtr);
- delete penPtr;
- }
- Tcl_DeleteHashTable(&penTable_);
-}
-
-int Graph::getPen(Tcl_Obj* objPtr, Pen** penPtrPtr)
-{
- *penPtrPtr = NULL;
- const char *name = Tcl_GetString(objPtr);
- if (!name || !name[0])
- return TCL_ERROR;
-
- Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&penTable_, name);
- if (!hPtr) {
- Tcl_AppendResult(interp_, "can't find pen \"", name, "\" in \"",
- Tk_PathName(tkwin_), "\"", NULL);
- return TCL_ERROR;
- }
-
- *penPtrPtr = (Pen*)Tcl_GetHashValue(hPtr);
-
- return TCL_OK;
-}
-
-// Elements
-
-void Graph::destroyElements()
-{
- Tcl_HashSearch iter;
- for (Tcl_HashEntry* hPtr=Tcl_FirstHashEntry(&elements_.table, &iter);
- hPtr; hPtr = Tcl_NextHashEntry(&iter)) {
- Element* elemPtr = (Element*)Tcl_GetHashValue(hPtr);
- legend_->removeElement(elemPtr);
- delete elemPtr;
- }
-
- Tcl_DeleteHashTable(&elements_.table);
- Tcl_DeleteHashTable(&elements_.tagTable);
- delete elements_.displayList;
-}
-
-void Graph::configureElements()
-{
- for (ChainLink* link = Chain_FirstLink(elements_.displayList); link;
- link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- elemPtr->configure();
- }
-}
-
-void Graph::mapElements()
-{
- for (ChainLink* link = Chain_FirstLink(elements_.displayList); link;
- link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- elemPtr->map();
- }
-}
-
-void Graph::drawElements(Drawable drawable)
-{
- // Draw with respect to the stacking order
- for (ChainLink* link=Chain_LastLink(elements_.displayList); link;
- link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- elemPtr->draw(drawable);
- }
-}
-
-void Graph::drawActiveElements(Drawable drawable)
-{
- for (ChainLink* link = Chain_LastLink(elements_.displayList); link;
- link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- elemPtr->drawActive(drawable);
- }
-}
-
-void Graph::printElements(PSOutput* psPtr)
-{
- for (ChainLink* link = Chain_LastLink(elements_.displayList); link;
- link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- elemPtr->print(psPtr);
- }
-}
-
-void Graph::printActiveElements(PSOutput* psPtr)
-{
- for (ChainLink* link = Chain_LastLink(elements_.displayList); link;
- link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- elemPtr->printActive(psPtr);
- }
-}
-
-int Graph::getElement(Tcl_Obj *objPtr, Element **elemPtrPtr)
-{
- *elemPtrPtr =NULL;
- const char* name = Tcl_GetString(objPtr);
- if (!name || !name[0])
- return TCL_ERROR;
-
- Tcl_HashEntry*hPtr = Tcl_FindHashEntry(&elements_.table, name);
- if (!hPtr) {
- Tcl_AppendResult(interp_, "can't find element \"", name, "\" in \"",
- Tk_PathName(tkwin_), "\"", NULL);
- return TCL_ERROR;
- }
-
- *elemPtrPtr = (Element*)Tcl_GetHashValue(hPtr);
- return TCL_OK;
-}
-
-ClientData Graph::elementTag(const char *tagName)
-{
- int isNew;
- Tcl_HashEntry* hPtr =
- Tcl_CreateHashEntry(&elements_.tagTable, tagName, &isNew);
- return Tcl_GetHashKey(&elements_.tagTable, hPtr);
-}
-
-// Markers
-
-void Graph::destroyMarkers()
-{
- Tcl_HashSearch iter;
- for (Tcl_HashEntry* hPtr=Tcl_FirstHashEntry(&markers_.table, &iter);
- hPtr; hPtr=Tcl_NextHashEntry(&iter)) {
- Marker* markerPtr = (Marker*)Tcl_GetHashValue(hPtr);
- delete markerPtr;
- }
- Tcl_DeleteHashTable(&markers_.table);
- Tcl_DeleteHashTable(&markers_.tagTable);
- delete markers_.displayList;
-}
-
-
-void Graph::configureMarkers()
-{
- for (ChainLink* link = Chain_FirstLink(markers_.displayList); link;
- link = Chain_NextLink(link)) {
- Marker* markerPtr = (Marker*)Chain_GetValue(link);
- markerPtr->configure();
- }
-}
-
-void Graph::mapMarkers()
-{
- for (ChainLink* link = Chain_FirstLink(markers_.displayList); link;
- link = Chain_NextLink(link)) {
- Marker* markerPtr = (Marker*)Chain_GetValue(link);
- MarkerOptions* mops = (MarkerOptions*)markerPtr->ops();
-
- if (mops->hide)
- continue;
-
- if ((flags & MAP_MARKERS) || (markerPtr->flags & MAP_ITEM)) {
- markerPtr->map();
- markerPtr->flags &= ~MAP_ITEM;
- }
- }
-
- flags &= ~MAP_MARKERS;
-}
-
-void Graph::drawMarkers(Drawable drawable, int under)
-{
- for (ChainLink* link = Chain_LastLink(markers_.displayList); link;
- link = Chain_PrevLink(link)) {
- Marker* markerPtr = (Marker*)Chain_GetValue(link);
- MarkerOptions* mops = (MarkerOptions*)markerPtr->ops();
-
- if ((mops->drawUnder != under) || markerPtr->clipped_ || mops->hide)
- continue;
-
- if (isElementHidden(markerPtr))
- continue;
-
- markerPtr->draw(drawable);
- }
-}
-
-void Graph::printMarkers(PSOutput* psPtr, int under)
-{
- for (ChainLink* link = Chain_LastLink(markers_.displayList); link;
- link = Chain_PrevLink(link)) {
- Marker* markerPtr = (Marker*)Chain_GetValue(link);
- MarkerOptions* mops = (MarkerOptions*)markerPtr->ops();
- if (mops->drawUnder != under)
- continue;
-
- if (mops->hide)
- continue;
-
- if (isElementHidden(markerPtr))
- continue;
-
- psPtr->format("%% Marker \"%s\" is a %s.\n",
- markerPtr->name_, markerPtr->className());
- markerPtr->print(psPtr);
- }
-}
-
-ClientData Graph::markerTag(const char* tagName)
-{
- int isNew;
- Tcl_HashEntry* hPtr = Tcl_CreateHashEntry(&markers_.tagTable, tagName,&isNew);
- return Tcl_GetHashKey(&markers_.tagTable, hPtr);
-}
-
-Marker* Graph::nearestMarker(int x, int y, int under)
-{
- Point2d point;
- point.x = (double)x;
- point.y = (double)y;
- for (ChainLink* link = Chain_FirstLink(markers_.displayList); link;
- link = Chain_NextLink(link)) {
- Marker* markerPtr = (Marker*)Chain_GetValue(link);
- MarkerOptions* mops = (MarkerOptions*)markerPtr->ops();
-
- if ((markerPtr->flags & MAP_ITEM) || mops->hide)
- continue;
-
- if (isElementHidden(markerPtr))
- continue;
-
- if (mops->drawUnder == under)
- if (markerPtr->pointIn(&point))
- return markerPtr;
- }
- return NULL;
-}
-
-int Graph::isElementHidden(Marker* markerPtr)
-{
- MarkerOptions* mops = (MarkerOptions*)markerPtr->ops();
-
- if (mops->elemName) {
- Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&elements_.table, mops->elemName);
- if (hPtr) {
- Element* elemPtr = (Element*)Tcl_GetHashValue(hPtr);
- ElementOptions* eops = (ElementOptions*)elemPtr->ops();
- if (!elemPtr->link || eops->hide)
- return 1;
- }
- }
- return 0;
-}
-
-// Axis
-
-int Graph::createAxes()
-{
- for (int ii=0; ii<4; ii++) {
- int isNew;
- Tcl_HashEntry* hPtr =
- Tcl_CreateHashEntry(&axes_.table, axisNames[ii].name, &isNew);
- Chain* chain = new Chain();
-
- Axis* axisPtr = new Axis(this, axisNames[ii].name, ii, hPtr);
- if (!axisPtr)
- return TCL_ERROR;
- AxisOptions* ops = (AxisOptions*)axisPtr->ops();
-
- Tcl_SetHashValue(hPtr, axisPtr);
-
- axisPtr->refCount_ = 1;
- axisPtr->use_ =1;
-
- axisPtr->setClass(!(ii&1) ? CID_AXIS_X : CID_AXIS_Y);
-
- if (Tk_InitOptions(interp_, (char*)axisPtr->ops(),
- axisPtr->optionTable(), tkwin_) != TCL_OK)
- return TCL_ERROR;
-
- if (axisPtr->configure() != TCL_OK)
- return TCL_ERROR;
-
- if ((axisPtr->margin_ == MARGIN_RIGHT) || (axisPtr->margin_ == MARGIN_TOP))
- ops->hide = 1;
-
- axisChain_[ii] = chain;
- axisPtr->link = chain->append(axisPtr);
- axisPtr->chain = chain;
- }
- return TCL_OK;
-}
-
-int Graph::createAxis(int objc, Tcl_Obj* const objv[])
-{
- char *string = Tcl_GetString(objv[3]);
- if (string[0] == '-') {
- Tcl_AppendResult(interp_, "name of axis \"", string,
- "\" can't start with a '-'", NULL);
- return TCL_ERROR;
- }
-
- int isNew;
- Tcl_HashEntry* hPtr = Tcl_CreateHashEntry(&axes_.table, string, &isNew);
- if (!isNew) {
- Tcl_AppendResult(interp_, "axis \"", string, "\" already exists in \"",
- Tcl_GetString(objv[0]), "\"", NULL);
- return TCL_ERROR;
- }
-
- Axis* axisPtr = new Axis(this, Tcl_GetString(objv[3]), MARGIN_NONE, hPtr);
- if (!axisPtr)
- return TCL_ERROR;
-
- Tcl_SetHashValue(hPtr, axisPtr);
-
- if ((Tk_InitOptions(interp_, (char*)axisPtr->ops(), axisPtr->optionTable(), tkwin_) != TCL_OK) || (AxisObjConfigure(axisPtr, interp_, objc-4, objv+4) != TCL_OK)) {
- delete axisPtr;
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-void Graph::destroyAxes()
-{
- Tcl_HashSearch cursor;
- for (Tcl_HashEntry *hPtr=Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr=Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- delete axisPtr;
- }
- Tcl_DeleteHashTable(&axes_.table);
-
- for (int ii=0; ii<4; ii++)
- delete axisChain_[ii];
-
- Tcl_DeleteHashTable(&axes_.tagTable);
- delete axes_.displayList;
-}
-
-void Graph::configureAxes()
-{
- Tcl_HashSearch cursor;
- for (Tcl_HashEntry *hPtr=Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr = Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- axisPtr->configure();
- }
-}
-
-void Graph::mapAxes()
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- for (int ii=0; ii<4; ii++) {
- int count =0;
- int offset =0;
-
- Chain* chain = ops->margins[ii].axes;
- for (ChainLink* link=Chain_FirstLink(chain); link;
- link = Chain_NextLink(link)) {
- Axis *axisPtr = (Axis*)Chain_GetValue(link);
- AxisOptions* aops = (AxisOptions*)axisPtr->ops();
- if (!axisPtr->use_)
- continue;
-
- if (aops->reqNumMajorTicks <= 0)
- aops->reqNumMajorTicks = 4;
-
- if (ops->stackAxes)
- axisPtr->mapStacked(count, ii);
- else
- axisPtr->map(offset, ii);
-
- if (aops->showGrid)
- axisPtr->mapGridlines();
-
- offset += axisPtr->isHorizontal() ? axisPtr->height_ : axisPtr->width_;
- count++;
- }
- }
-}
-
-void Graph::drawAxes(Drawable drawable)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- for (int ii=0; ii<4; ii++) {
- for (ChainLink* link = Chain_LastLink(ops->margins[ii].axes); link;
- link = Chain_PrevLink(link)) {
- Axis *axisPtr = (Axis*)Chain_GetValue(link);
- axisPtr->draw(drawable);
- }
- }
-}
-
-void Graph::drawAxesLimits(Drawable drawable)
-{
- Tcl_HashSearch cursor;
- for (Tcl_HashEntry* hPtr=Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr = Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- axisPtr->drawLimits(drawable);
- }
-}
-
-void Graph::drawAxesGrids(Drawable drawable)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- for (int ii=0; ii<4; ii++) {
- for (ChainLink* link = Chain_FirstLink(ops->margins[ii].axes); link;
- link = Chain_NextLink(link)) {
- Axis *axisPtr = (Axis*)Chain_GetValue(link);
- axisPtr->drawGrids(drawable);
- }
- }
-}
-
-void Graph::printAxes(PSOutput* psPtr)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- for (Margin *mp = ops->margins, *mend = mp + 4; mp < mend; mp++) {
- for (ChainLink* link = Chain_FirstLink(mp->axes); link;
- link = Chain_NextLink(link)) {
- Axis *axisPtr = (Axis*)Chain_GetValue(link);
- axisPtr->print(psPtr);
- }
- }
-}
-
-void Graph::printAxesGrids(PSOutput* psPtr)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- for (int ii=0; ii<4; ii++) {
- for (ChainLink* link = Chain_FirstLink(ops->margins[ii].axes); link;
- link = Chain_NextLink(link)) {
- Axis *axisPtr = (Axis*)Chain_GetValue(link);
- axisPtr->printGrids(psPtr);
- }
- }
-}
-
-void Graph::printAxesLimits(PSOutput* psPtr)
-{
- Tcl_HashSearch cursor;
- for (Tcl_HashEntry* hPtr=Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr = Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- axisPtr->printLimits(psPtr);
- }
-}
-
-int Graph::getAxis(Tcl_Obj *objPtr, Axis **axisPtrPtr)
-{
- *axisPtrPtr = NULL;
- const char* name = Tcl_GetString(objPtr);
- if (!name || !name[0])
- return TCL_ERROR;
-
- Tcl_HashEntry* hPtr = Tcl_FindHashEntry(&axes_.table, name);
- if (!hPtr) {
- Tcl_AppendResult(interp_, "can't find axis \"", name, "\" in \"",
- Tk_PathName(tkwin_), "\"", NULL);
- return TCL_ERROR;
- }
-
- *axisPtrPtr = (Axis*)Tcl_GetHashValue(hPtr);
- return TCL_OK;
-}
-
-ClientData Graph::axisTag(const char *tagName)
-{
- int isNew;
- Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&axes_.tagTable, tagName, &isNew);
- return Tcl_GetHashKey(&axes_.tagTable, hPtr);
-}
-
-void Graph::adjustAxes()
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- if (ops->inverted) {
- ops->leftMargin.axes = axisChain_[0];
- ops->bottomMargin.axes = axisChain_[1];
- ops->rightMargin.axes = axisChain_[2];
- ops->topMargin.axes = axisChain_[3];
- }
- else {
- ops->leftMargin.axes = axisChain_[1];
- ops->bottomMargin.axes = axisChain_[0];
- ops->rightMargin.axes = axisChain_[3];
- ops->topMargin.axes = axisChain_[2];
- }
-}
-
-Point2d Graph::map2D(double x, double y, Axis* xAxis, Axis* yAxis)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- Point2d point;
- if (ops->inverted) {
- point.x = yAxis->hMap(y);
- point.y = xAxis->vMap(x);
- }
- else {
- point.x = xAxis->hMap(x);
- point.y = yAxis->vMap(y);
- }
- return point;
-}
-
-Point2d Graph::invMap2D(double x, double y, Axis* xAxis, Axis* yAxis)
-{
- GraphOptions* ops = (GraphOptions*)ops_;
-
- Point2d point;
- if (ops->inverted) {
- point.x = xAxis->invVMap(y);
- point.y = yAxis->invHMap(x);
- }
- else {
- point.x = xAxis->invHMap(x);
- point.y = yAxis->invVMap(y);
- }
- return point;
-}
-
-void Graph::resetAxes()
-{
- // Step 1: Reset all axes. Initialize the data limits of the axis to
- // impossible values.
- Tcl_HashSearch cursor;
- for (Tcl_HashEntry* hPtr = Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr = Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- axisPtr->min_ = axisPtr->valueRange_.min = DBL_MAX;
- axisPtr->max_ = axisPtr->valueRange_.max = -DBL_MAX;
- }
-
- // Step 2: For each element that's to be displayed, get the smallest
- // and largest data values mapped to each X and Y-axis. This
- // will be the axis limits if the user doesn't override them
- // with -min and -max options.
- for (ChainLink* link = Chain_FirstLink(elements_.displayList); link;
- link = Chain_NextLink(link)) {
- Region2d exts;
-
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemops = (ElementOptions*)elemPtr->ops();
- elemPtr->extents(&exts);
- elemops->xAxis->getDataLimits(exts.left, exts.right);
- elemops->yAxis->getDataLimits(exts.top, exts.bottom);
- }
-
- // Step 3: Now that we know the range of data values for each axis,
- // set axis limits and compute a sweep to generate tick values.
- for (Tcl_HashEntry* hPtr = Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr = Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- AxisOptions* ops = (AxisOptions*)axisPtr->ops();
- axisPtr->fixRange();
-
- double min = axisPtr->min_;
- double max = axisPtr->max_;
- if ((!isnan(axisPtr->scrollMin_)) && (min < axisPtr->scrollMin_))
- min = axisPtr->scrollMin_;
-
- if ((!isnan(axisPtr->scrollMax_)) && (max > axisPtr->scrollMax_))
- max = axisPtr->scrollMax_;
-
- if (ops->logScale)
- axisPtr->logScale(min, max);
- else
- axisPtr->linearScale(min, max);
- }
-}
-
-Axis* Graph::nearestAxis(int x, int y)
-{
- Tcl_HashSearch cursor;
- for (Tcl_HashEntry* hPtr=Tcl_FirstHashEntry(&axes_.table, &cursor);
- hPtr; hPtr = Tcl_NextHashEntry(&cursor)) {
- Axis *axisPtr = (Axis*)Tcl_GetHashValue(hPtr);
- AxisOptions* ops = (AxisOptions*)axisPtr->ops();
- if (ops->hide || !axisPtr->use_)
- continue;
-
- if (ops->showTicks) {
- for (ChainLink* link = Chain_FirstLink(axisPtr->tickLabels_); link;
- link = Chain_NextLink(link)) {
- TickLabel *labelPtr = (TickLabel*)Chain_GetValue(link);
- double rw, rh;
- Point2d bbox[5];
- getBoundingBox(labelPtr->width, labelPtr->height, ops->tickAngle,
- &rw, &rh, bbox);
- Point2d t;
- t = anchorPoint(labelPtr->anchorPos.x, labelPtr->anchorPos.y,
- rw, rh, axisPtr->tickAnchor_);
- t.x = x - t.x - (rw * 0.5);
- t.y = y - t.y - (rh * 0.5);
-
- bbox[4] = bbox[0];
- if (pointInPolygon(&t, bbox, 5)) {
- return axisPtr;
- }
- }
- }
-
- if (ops->title) {
- int w, h;
- double rw, rh;
- Point2d bbox[5];
- getTextExtents(ops->titleFont, ops->title, -1, &w, &h);
- getBoundingBox(w, h, axisPtr->titleAngle_, &rw, &rh, bbox);
- Point2d t = anchorPoint(axisPtr->titlePos_.x, axisPtr->titlePos_.y,
- rw, rh, axisPtr->titleAnchor_);
- // Translate the point so that the 0,0 is the upper left
- // corner of the bounding box
- t.x = x - t.x - (rw * 0.5);
- t.y = y - t.y - (rh * 0.5);
-
- bbox[4] = bbox[0];
- if (pointInPolygon(&t, bbox, 5)) {
- return axisPtr;
- }
- }
- if (ops->lineWidth > 0) {
- if ((x <= axisPtr->right_) && (x >= axisPtr->left_) &&
- (y <= axisPtr->bottom_) && (y >= axisPtr->top_)) {
- return axisPtr;
- }
- }
- }
-
- return NULL;
-}
-
-// Bind
-
-const char** Graph::getTags(ClientData object, ClassId classId, int* num)
-{
- const char** tags =NULL;
-
- switch (classId) {
- case CID_ELEM_BAR:
- case CID_ELEM_LINE:
- {
- Element* ptr = (Element*)object;
- ElementOptions* ops = (ElementOptions*)ptr->ops();
- int cnt =0;
- for (const char** pp=ops->tags; *pp; pp++)
- cnt++;
- cnt +=2;
-
- tags = new const char*[cnt];
- tags[0] = (const char*)elementTag(ptr->name_);
- tags[1] = (const char*)elementTag(ptr->className());
- int ii=2;
- for (const char** pp = ops->tags; *pp; pp++, ii++)
- tags[ii] = (const char*)elementTag(*pp);
-
- *num = cnt;
- return tags;
- }
- break;
- case CID_AXIS_X:
- case CID_AXIS_Y:
- {
- Axis* ptr = (Axis*)object;
- AxisOptions* ops = (AxisOptions*)ptr->ops();
- int cnt =0;
- for (const char** pp=ops->tags; *pp; pp++)
- cnt++;
- cnt +=2;
-
- tags = new const char*[cnt];
- tags[0] = (const char*)axisTag(ptr->name_);
- tags[1] = (const char*)axisTag(ptr->className());
- int ii=2;
- for (const char** pp = ops->tags; *pp; pp++, ii++)
- tags[ii] = (const char*)axisTag(*pp);
-
- *num = cnt;
- return tags;
- }
- break;
- case CID_MARKER_BITMAP:
- case CID_MARKER_LINE:
- case CID_MARKER_POLYGON:
- case CID_MARKER_TEXT:
- {
- Marker* ptr = (Marker*)object;
- MarkerOptions* ops = (MarkerOptions*)ptr->ops();
- int cnt =0;
- for (const char** pp=ops->tags; *pp; pp++)
- cnt++;
- cnt +=2;
-
- tags = new const char*[cnt];
- tags[0] = (const char*)markerTag(ptr->name_);
- tags[1] = (const char*)markerTag(ptr->className());
- int ii=2;
- for (const char** pp = ops->tags; *pp; pp++, ii++)
- tags[ii] = (const char*)markerTag(*pp);
-
- *num = cnt;
- return tags;
- }
- break;
- default:
- break;
- }
-
- return NULL;
-}
-
-ClientData Graph::pickEntry(int xx, int yy, ClassId* classIdPtr)
-{
- if (flags & (LAYOUT | MAP_MARKERS)) {
- *classIdPtr = CID_NONE;
- return NULL;
- }
-
- // Sample coordinate is in one of the graph margins. Can only pick an axis.
- Region2d exts;
- extents(&exts);
- if (xx>=exts.right || xx<exts.left || yy>=exts.bottom || yy<exts.top) {
- Axis* axisPtr = nearestAxis(xx, yy);
- if (axisPtr) {
- *classIdPtr = 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 = nearestMarker(xx, yy, 0);
- if (markerPtr) {
- *classIdPtr = markerPtr->classId();
- return markerPtr;
- }
-
- GraphOptions* ops = (GraphOptions*)ops_;
- ClosestSearch* searchPtr = &ops->search;
- searchPtr->index = -1;
- searchPtr->x = xx;
- searchPtr->y = yy;
- searchPtr->dist = (double)(searchPtr->halo + 1);
-
- for (ChainLink* link = Chain_LastLink(elements_.displayList); link;
- link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* eops = (ElementOptions*)elemPtr->ops();
- if (eops->hide)
- continue;
- elemPtr->closest();
- }
-
- // Found an element within the minimum halo distance.
- if (searchPtr->dist <= (double)searchPtr->halo) {
- *classIdPtr = searchPtr->elemPtr->classId();
- return searchPtr->elemPtr;
- }
-
- markerPtr = nearestMarker(xx, yy, 1);
- if (markerPtr) {
- *classIdPtr = markerPtr->classId();
- return markerPtr;
- }
-
- *classIdPtr = CID_NONE;
- return NULL;
-}
-
-int Graph::getXY(const char* string, int* xPtr, int* yPtr)
-{
- if (!string || !*string) {
- *xPtr = -SHRT_MAX;
- *yPtr = -SHRT_MAX;
- return TCL_OK;
- }
-
- if (*string != '@') {
- Tcl_AppendResult(interp_, "bad position \"", string,
- "\": should be \"@x,y\"", (char *)NULL);
- return TCL_ERROR;
- }
-
- char* comma = (char*)strchr(string + 1, ',');
- if (!comma) {
- Tcl_AppendResult(interp_, "bad position \"", string,
- "\": should be \"@x,y\"", (char *)NULL);
- return TCL_ERROR;
- }
-
- *comma = '\0';
- int x, y;
- int result = ((Tk_GetPixels(interp_, tkwin_, string + 1, &x) == TCL_OK) &&
- (Tk_GetPixels(interp_, tkwin_, comma + 1, &y) == TCL_OK));
- *comma = ',';
- if (!result) {
- Tcl_AppendResult(interp_, ": can't parse position \"", string, "\"",
- (char *)NULL);
- return TCL_ERROR;
- }
-
- *xPtr = x;
- *yPtr = y;
- return TCL_OK;
-}
-
-// Graphics
-
-void Graph::drawSegments(Drawable drawable, GC gc,
- Segment2d* segments, int nSegments)
-{
- for (Segment2d *sp = segments, *send = sp + nSegments; sp < send; sp++)
- XDrawLine(display_, drawable, gc, (int)sp->p.x, (int)sp->p.y, (int)sp->q.x, (int)sp->q.y);
-}
-
-GC Graph::getPrivateGC(unsigned long gcMask, XGCValues *valuePtr)
-{
- Pixmap pixmap = None;
- Drawable drawable = Tk_WindowId(tkwin_);
- Display* display = Tk_Display(tkwin_);
- if (drawable == None)
- drawable = RootWindow(Tk_Display(tkwin_),Tk_ScreenNumber(tkwin_));
-
- GC gc = XCreateGC(display, drawable, gcMask, valuePtr);
- if (pixmap != None)
- Tk_FreePixmap(display, pixmap);
-
- return gc;
-}
-
-void Graph::freePrivateGC(GC gc)
-{
- Tk_FreeXId(display_, (XID)XGContextFromGC(gc));
- XFreeGC(display_, gc);
-}
-
-void Graph::setDashes(GC gc, Dashes* dashesPtr)
-{
- XSetDashes(display_, gc, dashesPtr->offset, (const char*)dashesPtr->values,
- (int)strlen((char*)dashesPtr->values));
-}