summaryrefslogtreecommitdiffstats
path: root/tkblt/generic/tkbltGrLegd.C
diff options
context:
space:
mode:
Diffstat (limited to 'tkblt/generic/tkbltGrLegd.C')
-rw-r--r--tkblt/generic/tkbltGrLegd.C1070
1 files changed, 0 insertions, 1070 deletions
diff --git a/tkblt/generic/tkbltGrLegd.C b/tkblt/generic/tkbltGrLegd.C
deleted file mode 100644
index b8822f1..0000000
--- a/tkblt/generic/tkbltGrLegd.C
+++ /dev/null
@@ -1,1070 +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 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.
- */
-
-#include <tk.h>
-#include <tkInt.h>
-
-#include "tkbltGrBind.h"
-#include "tkbltGraph.h"
-#include "tkbltGrLegd.h"
-#include "tkbltGrElem.h"
-#include "tkbltGrPostscript.h"
-#include "tkbltGrMisc.h"
-#include "tkbltGrDef.h"
-#include "tkbltConfig.h"
-#include "tkbltGrPSOutput.h"
-
-using namespace Blt;
-
-static void SelectCmdProc(ClientData);
-static Tk_SelectionProc SelectionProc;
-
-// OptionSpecs
-
-static const char* selectmodeObjOption[] = {
- "single", "multiple", NULL
-};
-static const char* positionObjOption[] = {
- "rightmargin", "leftmargin", "topmargin", "bottommargin",
- "plotarea", "xy", NULL
-};
-
-static Tk_OptionSpec optionSpecs[] = {
- {TK_OPTION_BORDER, "-activebackground", "activeBackground",
- "ActiveBackground",
- STD_ACTIVE_BACKGROUND, -1, Tk_Offset(LegendOptions, activeBg),
- 0, NULL, CACHE},
- {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
- "ActiveBorderWidth",
- STD_BORDERWIDTH, -1, Tk_Offset(LegendOptions, entryBW), 0, NULL, LAYOUT},
- {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "ActiveForeground",
- STD_ACTIVE_FOREGROUND, -1, Tk_Offset(LegendOptions, activeFgColor),
- 0, NULL, CACHE},
- {TK_OPTION_RELIEF, "-activerelief", "activeRelief", "ActiveRelief",
- "flat", -1, Tk_Offset(LegendOptions, activeRelief), 0, NULL, LAYOUT},
- {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
- "n", -1, Tk_Offset(LegendOptions, anchor), 0, NULL, LAYOUT},
- {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
- NULL, 0, -1, 0, (ClientData)"-background", 0},
- {TK_OPTION_BORDER, "-background", "background", "Background",
- NULL, -1, Tk_Offset(LegendOptions, normalBg),
- TK_OPTION_NULL_OK, NULL, CACHE},
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- STD_BORDERWIDTH, -1, Tk_Offset(LegendOptions, borderWidth),
- 0, NULL, LAYOUT},
- {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
- NULL, 0, -1, 0, (ClientData)"-borderwidth", 0},
- {TK_OPTION_INT, "-columns", "columns", "columns",
- "0", -1, Tk_Offset(LegendOptions, reqColumns), 0, NULL, LAYOUT},
- {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection",
- "no", -1, Tk_Offset(LegendOptions, exportSelection), 0, NULL, LAYOUT},
- {TK_OPTION_CUSTOM, "-focusdashes", "focusDashes", "FocusDashes",
- "dot", -1, Tk_Offset(LegendOptions, focusDashes),
- TK_OPTION_NULL_OK, &dashesObjOption, CACHE},
- {TK_OPTION_COLOR, "-focusforeground", "focusForeground", "FocusForeground",
- STD_ACTIVE_FOREGROUND, -1, Tk_Offset(LegendOptions, focusColor),
- 0, NULL, CACHE},
- {TK_OPTION_FONT, "-font", "font", "Font",
- STD_FONT_SMALL, -1, Tk_Offset(LegendOptions, style.font), 0, NULL, LAYOUT},
- {TK_OPTION_SYNONYM, "-fg", NULL, NULL,
- NULL, 0, -1, 0, (ClientData)"-foreground", 0},
- {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
- STD_NORMAL_FOREGROUND, -1, Tk_Offset(LegendOptions, fgColor),
- 0, NULL, CACHE},
- {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide",
- "no", -1, Tk_Offset(LegendOptions, hide), 0, NULL, LAYOUT},
- {TK_OPTION_PIXELS, "-ipadx", "iPadX", "Pad",
- "1", -1, Tk_Offset(LegendOptions, ixPad), 0, NULL, LAYOUT},
- {TK_OPTION_PIXELS, "-ipady", "iPadY", "Pad",
- "1", -1, Tk_Offset(LegendOptions, iyPad), 0, NULL, LAYOUT},
- {TK_OPTION_BORDER, "-nofocusselectbackground", "noFocusSelectBackground",
- "NoFocusSelectBackground",
- STD_ACTIVE_BACKGROUND, -1, Tk_Offset(LegendOptions, selOutFocusBg),
- 0, NULL, CACHE},
- {TK_OPTION_COLOR, "-nofocusselectforeground", "noFocusSelectForeground",
- "NoFocusSelectForeground",
- STD_ACTIVE_FOREGROUND, -1, Tk_Offset(LegendOptions, selOutFocusFgColor),
- 0, NULL, CACHE},
- {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
- "1", -1, Tk_Offset(LegendOptions, xPad), 0, NULL, LAYOUT},
- {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
- "1", -1, Tk_Offset(LegendOptions, yPad), 0, NULL, LAYOUT},
- {TK_OPTION_STRING_TABLE, "-position", "position", "Position",
- "rightmargin", -1, Tk_Offset(LegendOptions, position),
- 0, &positionObjOption, LAYOUT},
- {TK_OPTION_BOOLEAN, "-raised", "raised", "Raised",
- "no", -1, Tk_Offset(LegendOptions, raised), 0, NULL, LAYOUT},
- {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- "flat", -1, Tk_Offset(LegendOptions, relief), 0, NULL, LAYOUT},
- {TK_OPTION_INT, "-rows", "rows", "rows",
- "0", -1, Tk_Offset(LegendOptions, reqRows), 0, NULL, LAYOUT},
- {TK_OPTION_BORDER, "-selectbackground", "selectBackground",
- "SelectBackground",
- STD_ACTIVE_BACKGROUND, -1, Tk_Offset(LegendOptions, selInFocusBg),
- 0, NULL, LAYOUT},
- {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
- "SelectBorderWidth",
- "1", -1, Tk_Offset(LegendOptions, selBW), 0, NULL, LAYOUT},
- {TK_OPTION_STRING, "-selectcommand", "selectCommand", "SelectCommand",
- NULL, -1, Tk_Offset(LegendOptions, selectCmd), TK_OPTION_NULL_OK, NULL, 0},
- {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "SelectForeground",
- STD_ACTIVE_FOREGROUND, -1, Tk_Offset(LegendOptions, selInFocusFgColor),
- 0, NULL, CACHE},
- {TK_OPTION_STRING_TABLE, "-selectmode", "selectMode", "SelectMode",
- "multiple", -1, Tk_Offset(LegendOptions, selectMode),
- 0, &selectmodeObjOption, 0},
- {TK_OPTION_RELIEF, "-selectrelief", "selectRelief", "SelectRelief",
- "flat", -1, Tk_Offset(LegendOptions, selRelief), 0, NULL, LAYOUT},
- {TK_OPTION_STRING, "-title", "title", "Title",
- NULL, -1, Tk_Offset(LegendOptions, title), TK_OPTION_NULL_OK, NULL, LAYOUT},
- {TK_OPTION_COLOR, "-titlecolor", "titleColor", "TitleColor",
- STD_NORMAL_FOREGROUND, -1, Tk_Offset(LegendOptions, titleStyle.color),
- 0, NULL, CACHE},
- {TK_OPTION_FONT, "-titlefont", "titleFont", "TitleFont",
- STD_FONT_SMALL, -1, Tk_Offset(LegendOptions, titleStyle.font),
- 0, NULL, LAYOUT},
- {TK_OPTION_PIXELS, "-x", "x", "X",
- "0", -1, Tk_Offset(LegendOptions, xReq), 0, NULL, LAYOUT},
- {TK_OPTION_PIXELS, "-y", "y", "Y",
- "0", -1, Tk_Offset(LegendOptions, yReq), 0, NULL, LAYOUT},
- {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
-};
-
-Legend::Legend(Graph* graphPtr)
-{
- ops_ = (void*)calloc(1, sizeof(LegendOptions));
- LegendOptions* ops = (LegendOptions*)ops_;
-
- graphPtr_ = graphPtr;
- flags =0;
- nEntries_ =0;
- nColumns_ =0;
- nRows_ =0;
- width_ =0;
- height_ =0;
- entryWidth_ =0;
- entryHeight_ =0;
- x_ =0;
- y_ =0;
- bindTable_ =NULL;
- focusGC_ =NULL;
- focusPtr_ =NULL;
- selAnchorPtr_ =NULL;
- selMarkPtr_ =NULL;
- selected_ = new Chain();
- titleWidth_ =0;
- titleHeight_ =0;
-
- ops->style.anchor =TK_ANCHOR_NW;
- ops->style.color =NULL;
- ops->style.font =NULL;
- ops->style.angle =0;
- ops->style.justify =TK_JUSTIFY_LEFT;
-
- ops->titleStyle.anchor =TK_ANCHOR_NW;
- ops->titleStyle.color =NULL;
- ops->titleStyle.font =NULL;
- ops->titleStyle.angle =0;
- ops->titleStyle.justify =TK_JUSTIFY_LEFT;
-
- bindTable_ = new BindTable(graphPtr, this);
-
- Tcl_InitHashTable(&selectTable_, TCL_ONE_WORD_KEYS);
-
- Tk_CreateSelHandler(graphPtr_->tkwin_, XA_PRIMARY, XA_STRING,
- SelectionProc, this, XA_STRING);
-
- optionTable_ =Tk_CreateOptionTable(graphPtr->interp_, optionSpecs);
- Tk_InitOptions(graphPtr->interp_, (char*)ops_, optionTable_, graphPtr->tkwin_);
-}
-
-Legend::~Legend()
-{
- // LegendOptions* ops = (LegendOptions*)ops_;
-
- delete bindTable_;
-
- if (focusGC_)
- graphPtr_->freePrivateGC(focusGC_);
-
- if (graphPtr_->tkwin_)
- Tk_DeleteSelHandler(graphPtr_->tkwin_, XA_PRIMARY, XA_STRING);
-
- delete selected_;
-
- Tk_FreeConfigOptions((char*)ops_, optionTable_, graphPtr_->tkwin_);
- free(ops_);
-}
-
-int Legend::configure()
-{
- LegendOptions* ops = (LegendOptions*)ops_;
-
- // GC for active label, Dashed outline
- unsigned long gcMask = GCForeground | GCLineStyle;
- XGCValues gcValues;
- gcValues.foreground = ops->focusColor->pixel;
- gcValues.line_style = (LineIsDashed(ops->focusDashes))
- ? LineOnOffDash : LineSolid;
- GC newGC = graphPtr_->getPrivateGC(gcMask, &gcValues);
- if (LineIsDashed(ops->focusDashes)) {
- ops->focusDashes.offset = 2;
- graphPtr_->setDashes(newGC, &ops->focusDashes);
- }
- if (focusGC_)
- graphPtr_->freePrivateGC(focusGC_);
-
- focusGC_ = newGC;
-
- return TCL_OK;
-}
-
-void Legend::map(int plotWidth, int plotHeight)
-{
- LegendOptions* ops = (LegendOptions*)ops_;
-
- entryWidth_ =0;
- entryHeight_ = 0;
- nRows_ =0;
- nColumns_ =0;
- nEntries_ =0;
- height_ =0;
- width_ = 0;
-
- TextStyle tts(graphPtr_, &ops->titleStyle);
- tts.getExtents(ops->title, &titleWidth_, &titleHeight_);
-
- // Count the number of legend entries and determine the widest and tallest
- // label. The number of entries would normally be the number of elements,
- // but elements can have no legend entry (-label "").
- int nEntries =0;
- int maxWidth =0;
- int maxHeight =0;
- TextStyle ts(graphPtr_, &ops->style);
- for (ChainLink* link = Chain_FirstLink(graphPtr_->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
-
- if (!elemOps->label)
- continue;
-
- int w, h;
- ts.getExtents(elemOps->label, &w, &h);
- if (maxWidth < (int)w)
- maxWidth = w;
-
- if (maxHeight < (int)h)
- maxHeight = h;
-
- nEntries++;
- }
- if (nEntries == 0)
- return;
-
- Tk_FontMetrics fontMetrics;
- Tk_GetFontMetrics(ops->style.font, &fontMetrics);
- int symbolWidth = 2 * fontMetrics.ascent;
-
- maxWidth += 2 * ops->entryBW + 2*ops->ixPad +
- + symbolWidth + 3 * 2;
-
- maxHeight += 2 * ops->entryBW + 2*ops->iyPad;
-
- maxWidth |= 0x01;
- maxHeight |= 0x01;
-
- int lw = plotWidth - 2 * ops->borderWidth - 2*ops->xPad;
- int lh = plotHeight - 2 * ops->borderWidth - 2*ops->yPad;
-
- /*
- * The number of rows and columns is computed as one of the following:
- *
- * both options set User defined.
- * -rows Compute columns from rows.
- * -columns Compute rows from columns.
- * neither set Compute rows and columns from
- * size of plot.
- */
- int nRows =0;
- int nColumns =0;
- if (ops->reqRows > 0) {
- nRows = MIN(ops->reqRows, nEntries);
- if (ops->reqColumns > 0)
- nColumns = MIN(ops->reqColumns, nEntries);
- else
- nColumns = ((nEntries - 1) / nRows) + 1; /* Only -rows. */
- }
- else if (ops->reqColumns > 0) { /* Only -columns. */
- nColumns = MIN(ops->reqColumns, nEntries);
- nRows = ((nEntries - 1) / nColumns) + 1;
- }
- else {
- // Compute # of rows and columns from the legend size
- nRows = lh / maxHeight;
- nColumns = lw / maxWidth;
- if (nRows < 1) {
- nRows = nEntries;
- }
- if (nColumns < 1) {
- nColumns = nEntries;
- }
- if (nRows > nEntries) {
- nRows = nEntries;
- }
- switch ((Position)ops->position) {
- case TOP:
- case BOTTOM:
- nRows = ((nEntries - 1) / nColumns) + 1;
- break;
- case LEFT:
- case RIGHT:
- default:
- nColumns = ((nEntries - 1) / nRows) + 1;
- break;
- }
- }
- if (nColumns < 1)
- nColumns = 1;
-
- if (nRows < 1)
- nRows = 1;
-
- lh = (nRows * maxHeight);
- if (titleHeight_ > 0)
- lh += titleHeight_ + ops->yPad;
-
- lw = nColumns * maxWidth;
- if (lw < (int)(titleWidth_))
- lw = titleWidth_;
-
- width_ = lw + 2 * ops->borderWidth + 2*ops->xPad;
- height_ = lh + 2 * ops->borderWidth + 2*ops->yPad;
- nRows_ = nRows;
- nColumns_ = nColumns;
- nEntries_ = nEntries;
- entryHeight_ = maxHeight;
- entryWidth_ = maxWidth;
-
- int row =0;
- int col =0;
- int count =0;
- for (ChainLink* link = Chain_FirstLink(graphPtr_->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- count++;
- elemPtr->row_ = row;
- elemPtr->col_ = col;
- row++;
- if ((count % nRows) == 0) {
- col++;
- row = 0;
- }
- }
-}
-
-void Legend::draw(Drawable drawable)
-{
- LegendOptions* ops = (LegendOptions*)ops_;
- GraphOptions* gops = (GraphOptions*)graphPtr_->ops_;
-
- if ((ops->hide) || (nEntries_ == 0))
- return;
-
- setOrigin();
- Tk_Window tkwin = graphPtr_->tkwin_;
- int w = width_;
- int h = height_;
-
- Pixmap pixmap = Tk_GetPixmap(graphPtr_->display_, Tk_WindowId(tkwin), w, h,
- Tk_Depth(tkwin));
-
- if (ops->normalBg)
- Tk_Fill3DRectangle(tkwin, pixmap, ops->normalBg, 0, 0,
- w, h, 0, TK_RELIEF_FLAT);
- else {
- switch ((Position)ops->position) {
- case TOP:
- case BOTTOM:
- case RIGHT:
- case LEFT:
- Tk_Fill3DRectangle(tkwin, pixmap, gops->normalBg, 0, 0,
- w, h, 0, TK_RELIEF_FLAT);
- break;
- case PLOT:
- case XY:
- // Legend background is transparent and is positioned over the the
- // plot area. Either copy the part of the background from the backing
- // store pixmap or (if no backing store exists) just fill it with the
- // background color of the plot.
- if (graphPtr_->cache_ != None)
- XCopyArea(graphPtr_->display_, graphPtr_->cache_, pixmap,
- graphPtr_->drawGC_, x_, y_, w, h, 0, 0);
- else
- Tk_Fill3DRectangle(tkwin, pixmap, gops->plotBg, 0, 0,
- w, h, TK_RELIEF_FLAT, 0);
- break;
- };
- }
-
- Tk_FontMetrics fontMetrics;
- Tk_GetFontMetrics(ops->style.font, &fontMetrics);
-
- int symbolSize = fontMetrics.ascent;
- int xMid = symbolSize + 1 + ops->entryBW;
- int yMid = (symbolSize / 2) + 1 + ops->entryBW;
- int xLabel = 2 * symbolSize + ops->entryBW + ops->ixPad + 2 * 2;
- int ySymbol = yMid + ops->iyPad;
- int xSymbol = xMid + 2;
-
- int x = ops->xPad + ops->borderWidth;
- int y = ops->yPad + ops->borderWidth;
-
- TextStyle tts(graphPtr_, &ops->titleStyle);
- tts.drawText(pixmap, ops->title, x, y);
- if (titleHeight_ > 0)
- y += titleHeight_ + ops->yPad;
-
- int count = 0;
- int yStart = y;
- TextStyle ts(graphPtr_, &ops->style);
-
- for (ChainLink* link = Chain_FirstLink(graphPtr_->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
- if (!elemOps->label)
- continue;
-
- int isSelected = entryIsSelected(elemPtr);
- if (elemPtr->labelActive_)
- Tk_Fill3DRectangle(tkwin, pixmap, ops->activeBg,
- x, y, entryWidth_, entryHeight_,
- ops->entryBW, ops->activeRelief);
- else if (isSelected) {
- XColor* fg = (flags & FOCUS) ?
- ops->selInFocusFgColor : ops->selOutFocusFgColor;
- Tk_3DBorder bg = (flags & FOCUS) ?
- ops->selInFocusBg : ops->selOutFocusBg;
- ops->style.color = fg;
- Tk_Fill3DRectangle(tkwin, pixmap, bg, x, y,
- entryWidth_, entryHeight_,
- ops->selBW, ops->selRelief);
- }
- else {
- ops->style.color = ops->fgColor;
- if (elemOps->legendRelief != TK_RELIEF_FLAT)
- Tk_Fill3DRectangle(tkwin, pixmap, gops->normalBg,
- x, y, entryWidth_,
- entryHeight_, ops->entryBW,
- elemOps->legendRelief);
- }
- elemPtr->drawSymbol(pixmap, x + xSymbol, y + ySymbol, symbolSize);
-
- ts.drawText(pixmap, elemOps->label, x+xLabel, y+ops->entryBW+ops->iyPad);
- count++;
-
- if (focusPtr_ == elemPtr) {
- if (isSelected) {
- XColor* color = (flags & FOCUS) ?
- ops->selInFocusFgColor : ops->selOutFocusFgColor;
- XSetForeground(graphPtr_->display_, focusGC_, color->pixel);
- }
- XDrawRectangle(graphPtr_->display_, pixmap, focusGC_,
- x + 1, y + 1, entryWidth_ - 3,
- entryHeight_ - 3);
- if (isSelected)
- XSetForeground(graphPtr_->display_, focusGC_, ops->focusColor->pixel);
- }
-
- // Check when to move to the next column
- if ((count % nRows_) > 0)
- y += entryHeight_;
- else {
- x += entryWidth_;
- y = yStart;
- }
- }
-
- Tk_3DBorder bg = ops->normalBg;
- if (!bg)
- bg = gops->normalBg;
-
- Tk_Draw3DRectangle(tkwin, pixmap, bg, 0, 0, w, h,
- ops->borderWidth, ops->relief);
- XCopyArea(graphPtr_->display_, pixmap, drawable, graphPtr_->drawGC_,
- 0, 0, w, h, x_, y_);
-
- Tk_FreePixmap(graphPtr_->display_, pixmap);
-}
-
-void Legend::print(PSOutput* psPtr)
-{
- LegendOptions* ops = (LegendOptions*)ops_;
- GraphOptions* gops = (GraphOptions*)graphPtr_->ops_;
- PostscriptOptions* pops = (PostscriptOptions*)graphPtr_->postscript_->ops_;
-
- if ((ops->hide) || (nEntries_ == 0))
- return;
-
- setOrigin();
-
- double x = x_;
- double y = y_;
- int width = width_ - 2*ops->xPad;
- int height = height_ - 2*ops->yPad;
-
- psPtr->append("% Legend\n");
- if (pops->decorations) {
- if (ops->normalBg)
- psPtr->fill3DRectangle(ops->normalBg, x, y, width, height,
- ops->borderWidth, ops->relief);
- else
- psPtr->print3DRectangle(gops->normalBg, x, y, width, height,
- ops->borderWidth, ops->relief);
-
- }
- else {
- psPtr->setClearBackground();
- psPtr->fillRectangle(x, y, width, height);
- }
-
- Tk_FontMetrics fontMetrics;
- Tk_GetFontMetrics(ops->style.font, &fontMetrics);
- int symbolSize = fontMetrics.ascent;
- int xMid = symbolSize + 1 + ops->entryBW;
- int yMid = (symbolSize / 2) + 1 + ops->entryBW;
- int xLabel = 2 * symbolSize + ops->entryBW + ops->ixPad + 5;
- int xSymbol = xMid + ops->ixPad;
- int ySymbol = yMid + ops->iyPad;
-
- x += ops->borderWidth;
- y += ops->borderWidth;
- TextStyle tts(graphPtr_, &ops->titleStyle);
- tts.printText(psPtr, ops->title, x, y);
- if (titleHeight_ > 0)
- y += titleHeight_ + ops->yPad;
-
- int count = 0;
- double yStart = y;
- TextStyle ts(graphPtr_, &ops->style);
-
- for (ChainLink* link = Chain_FirstLink(graphPtr_->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
-
- if (!elemOps->label)
- continue;
-
- if (elemPtr->labelActive_) {
- ops->style.color = ops->activeFgColor;
- psPtr->fill3DRectangle(ops->activeBg, x, y, entryWidth_,
- entryHeight_, ops->entryBW,
- ops->activeRelief);
- }
- else {
- ops->style.color = ops->fgColor;
- if (elemOps->legendRelief != TK_RELIEF_FLAT)
- psPtr->print3DRectangle(gops->normalBg, x, y, entryWidth_, entryHeight_,
- ops->entryBW, elemOps->legendRelief);
- }
- elemPtr->printSymbol(psPtr, x + xSymbol, y + ySymbol, symbolSize);
- ts.printText(psPtr, elemOps->label, x + xLabel,
- y + ops->entryBW + ops->iyPad);
- count++;
-
- if ((count % nRows_) > 0)
- y += entryHeight_;
- else {
- x += entryWidth_;
- y = yStart;
- }
- }
-}
-
-void Legend::removeElement(Element* elemPtr)
-{
- bindTable_->deleteBindings(elemPtr);
-}
-
-void Legend::eventuallyInvokeSelectCmd()
-{
- if ((flags & SELECT_PENDING) == 0) {
- flags |= SELECT_PENDING;
- Tcl_DoWhenIdle(SelectCmdProc, this);
- }
-}
-
-void Legend::setOrigin()
-{
- LegendOptions* ops = (LegendOptions*)ops_;
- GraphOptions* gops = (GraphOptions*)graphPtr_->ops_;
-
- int x =0;
- int y =0;
- int w =0;
- int h =0;
- switch ((Position)ops->position) {
- case RIGHT:
- w = gops->rightMargin.width - gops->rightMargin.axesOffset;
- h = graphPtr_->bottom_ - graphPtr_->top_;
- x = graphPtr_->right_ + gops->rightMargin.axesOffset;
- y = graphPtr_->top_;
- break;
-
- case LEFT:
- w = gops->leftMargin.width - gops->leftMargin.axesOffset;
- h = graphPtr_->bottom_ - graphPtr_->top_;
- x = graphPtr_->inset_;
- y = graphPtr_->top_;
- break;
-
- case TOP:
- w = graphPtr_->right_ - graphPtr_->left_;
- h = gops->topMargin.height - gops->topMargin.axesOffset;
- if (gops->title)
- h -= graphPtr_->titleHeight_;
-
- x = graphPtr_->left_;
- y = graphPtr_->inset_;
- if (gops->title)
- y += graphPtr_->titleHeight_;
- break;
-
- case BOTTOM:
- w = graphPtr_->right_ - graphPtr_->left_;
- h = gops->bottomMargin.height - gops->bottomMargin.axesOffset;
- x = graphPtr_->left_;
- y = graphPtr_->bottom_ + gops->bottomMargin.axesOffset;
- break;
-
- case PLOT:
- w = graphPtr_->right_ - graphPtr_->left_;
- h = graphPtr_->bottom_ - graphPtr_->top_;
- x = graphPtr_->left_;
- y = graphPtr_->top_;
- break;
-
- case XY:
- w = width_;
- h = height_;
- x = ops->xReq;
- y = ops->yReq;
- if (x < 0)
- x += graphPtr_->width_;
-
- if (y < 0)
- y += graphPtr_->height_;
- break;
- }
-
- switch (ops->anchor) {
- case TK_ANCHOR_NW:
- break;
- case TK_ANCHOR_W:
- if (h > height_)
- y += (h - height_) / 2;
- break;
- case TK_ANCHOR_SW:
- if (h > height_)
- y += (h - height_);
- break;
- case TK_ANCHOR_N:
- if (w > width_)
- x += (w - width_) / 2;
- break;
- case TK_ANCHOR_CENTER:
- if (h > height_)
- y += (h - height_) / 2;
-
- if (w > width_)
- x += (w - width_) / 2;
- break;
- case TK_ANCHOR_S:
- if (w > width_)
- x += (w - width_) / 2;
-
- if (h > height_)
- y += (h - height_);
- break;
- case TK_ANCHOR_NE:
- if (w > width_)
- x += w - width_;
- break;
- case TK_ANCHOR_E:
- if (w > width_)
- x += w - width_;
-
- if (h > height_)
- y += (h - height_) / 2;
- break;
- case TK_ANCHOR_SE:
- if (w > width_) {
- x += w - width_;
- }
- if (h > height_) {
- y += (h - height_);
- }
- break;
- }
-
- x_ = x + ops->xPad;
- y_ = y + ops->yPad;
-}
-
-void Legend::selectEntry(Element* elemPtr)
-{
- switch (flags & SELECT_TOGGLE) {
- case SELECT_CLEAR:
- deselectElement(elemPtr);
- break;
- case SELECT_SET:
- selectElement(elemPtr);
- break;
- case SELECT_TOGGLE:
- Tcl_HashEntry* hPtr = Tcl_FindHashEntry(&selectTable_, (char*)elemPtr);
- if (hPtr)
- deselectElement(elemPtr);
- else
- selectElement(elemPtr);
- break;
- }
-}
-
-void Legend::selectElement(Element* elemPtr)
-{
- int isNew;
- Tcl_HashEntry* hPtr =
- Tcl_CreateHashEntry(&selectTable_, (char*)elemPtr, &isNew);
- if (isNew) {
- ChainLink* link = selected_->append(elemPtr);
- Tcl_SetHashValue(hPtr, link);
- }
-}
-
-void Legend::deselectElement(Element* elemPtr)
-{
- Tcl_HashEntry* hPtr = Tcl_FindHashEntry(&selectTable_, (char*)elemPtr);
- if (hPtr) {
- ChainLink* link = (ChainLink*)Tcl_GetHashValue(hPtr);
- selected_->deleteLink(link);
- Tcl_DeleteHashEntry(hPtr);
- }
-}
-
-
-int Legend::selectRange(Element *fromPtr, Element *toPtr)
-{
- int isBefore=0;
- for (ChainLink* linkPtr = fromPtr->link; linkPtr; linkPtr = linkPtr->next())
- if (linkPtr == toPtr->link)
- isBefore =1;
-
- if (isBefore) {
- for (ChainLink* link = fromPtr->link; link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- selectEntry(elemPtr);
- if (link == toPtr->link)
- break;
- }
- }
- else {
- for (ChainLink* link = fromPtr->link; link; link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- selectEntry(elemPtr);
- if (link == toPtr->link)
- break;
- }
- }
-
- return TCL_OK;
-}
-
-void Legend::clearSelection()
-{
- LegendOptions* ops = (LegendOptions*)ops_;
-
- Tcl_DeleteHashTable(&selectTable_);
- Tcl_InitHashTable(&selectTable_, TCL_ONE_WORD_KEYS);
- selected_->reset();
-
- if (ops->selectCmd)
- eventuallyInvokeSelectCmd();
-}
-
-int Legend::entryIsSelected(Element* elemPtr)
-{
- Tcl_HashEntry* hPtr = Tcl_FindHashEntry(&selectTable_, (char*)elemPtr);
- return (hPtr != NULL);
-}
-
-int Legend::getElementFromObj(Tcl_Obj* objPtr, Element** elemPtrPtr)
-{
- const char *string = Tcl_GetString(objPtr);
- Element* elemPtr = NULL;
-
- if (!strcmp(string, "anchor"))
- elemPtr = selAnchorPtr_;
- else if (!strcmp(string, "current"))
- elemPtr = (Element*)bindTable_->currentItem();
- else if (!strcmp(string, "first"))
- elemPtr = getFirstElement();
- else if (!strcmp(string, "focus"))
- elemPtr = focusPtr_;
- else if (!strcmp(string, "last"))
- elemPtr = getLastElement();
- else if (!strcmp(string, "end"))
- elemPtr = getLastElement();
- else if (!strcmp(string, "next.row"))
- elemPtr = getNextRow(focusPtr_);
- else if (!strcmp(string, "next.column"))
- elemPtr = getNextColumn(focusPtr_);
- else if (!strcmp(string, "previous.row"))
- elemPtr = getPreviousRow(focusPtr_);
- else if (!strcmp(string, "previous.column"))
- elemPtr = getPreviousColumn(focusPtr_);
- else if (string[0] == '@') {
- int x, y;
- if (graphPtr_->getXY(string, &x, &y) != TCL_OK)
- return TCL_ERROR;
-
- ClassId classId;
- elemPtr = (Element*)pickEntry(x, y, &classId);
- }
- else {
- if (graphPtr_->getElement(objPtr, &elemPtr) != TCL_OK)
- return TCL_ERROR;
-
- if (!elemPtr->link) {
- Tcl_AppendResult(graphPtr_->interp_, "bad legend index \"", string, "\"",
- (char *)NULL);
- return TCL_ERROR;
- }
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
- if (!elemOps->label)
- elemPtr = NULL;
- }
-
- *elemPtrPtr = elemPtr;
- return TCL_OK;
-}
-
-Element* Legend::getNextRow(Element* focusPtr)
-{
- unsigned col = focusPtr->col_;
- unsigned row = focusPtr->row_ + 1;
- for (ChainLink* link = focusPtr->link; link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
-
- if (!elemOps->label)
- continue;
-
- if ((elemPtr->col_ == col) && (elemPtr->row_ == row))
- return elemPtr;
- }
- return NULL;
-}
-
-Element* Legend::getNextColumn(Element* focusPtr)
-{
- unsigned col = focusPtr->col_ + 1;
- unsigned row = focusPtr->row_;
- for (ChainLink* link = focusPtr->link; link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
-
- if (!elemOps->label)
- continue;
-
- if ((elemPtr->col_ == col) && (elemPtr->row_ == row))
- return elemPtr;
- }
- return NULL;
-}
-
-Element* Legend::getPreviousRow(Element* focusPtr)
-{
- unsigned col = focusPtr->col_;
- unsigned row = focusPtr->row_ - 1;
- for (ChainLink* link = focusPtr->link; link; link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
-
- if (!elemOps->label)
- continue;
-
- if ((elemPtr->col_ == col) && (elemPtr->row_ == row))
- return elemPtr;
- }
- return NULL;
-}
-
-Element* Legend::getPreviousColumn(Element* focusPtr)
-{
- unsigned col = focusPtr->col_ - 1;
- unsigned row = focusPtr->row_;
- for (ChainLink* link = focusPtr->link; link; link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
-
- if (!elemOps->label)
- continue;
-
- if ((elemPtr->col_ == col) && (elemPtr->row_ == row))
- return elemPtr;
- }
- return NULL;
-}
-
-Element* Legend::getFirstElement()
-{
- for (ChainLink* link = Chain_FirstLink(graphPtr_->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
- if (elemOps->label)
- return elemPtr;
- }
- return NULL;
-}
-
-Element* Legend::getLastElement()
-{
- for (ChainLink* link = Chain_LastLink(graphPtr_->elements_.displayList);
- link; link = Chain_PrevLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
- if (elemOps->label)
- return elemPtr;
- }
- return NULL;
-}
-
-ClientData Legend::pickEntry(int xx, int yy, ClassId* classIdPtr)
-{
- LegendOptions* ops = (LegendOptions*)ops_;
-
- int ww = width_;
- int hh = height_;
-
- if (titleHeight_ > 0)
- yy -= titleHeight_ + ops->yPad;
-
- xx -= x_ + ops->borderWidth;
- yy -= y_ + ops->borderWidth;
- ww -= 2 * ops->borderWidth + 2*ops->xPad;
- hh -= 2 * ops->borderWidth + 2*ops->yPad;
-
- // In the bounding box? if so, compute the index
- if (xx >= 0 && xx < ww && yy >= 0 && yy < hh) {
- int row = yy / entryHeight_;
- int column = xx / entryWidth_;
- int nn = (column * nRows_) + row;
-
- // Legend entries are stored in bottom-to-top
- if (nn < nEntries_) {
- int count = 0;
- for (ChainLink* link = Chain_FirstLink(graphPtr_->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- ElementOptions* elemOps = (ElementOptions*)elemPtr->ops();
- if (elemOps->label) {
- if (count == nn) {
- *classIdPtr = elemPtr->classId();
- return elemPtr;
- }
- count++;
- }
- }
- }
- }
-
- return NULL;
-}
-
-// Support
-
-static int SelectionProc(ClientData clientData, int offset, char *buffer,
- int maxBytes)
-{
- Legend* legendPtr = (Legend*)clientData;
- Graph* graphPtr = legendPtr->graphPtr_;
- LegendOptions* ops = (LegendOptions*)legendPtr->ops();
-
- if ((ops->exportSelection) == 0)
- return -1;
-
- // Retrieve the names of the selected entries
- Tcl_DString dString;
- Tcl_DStringInit(&dString);
- if (legendPtr->flags & SELECT_SORTED) {
- for (ChainLink* link=Chain_FirstLink(legendPtr->selected_);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- Tcl_DStringAppend(&dString, elemPtr->name_, -1);
- Tcl_DStringAppend(&dString, "\n", -1);
- }
- }
- else {
- for (ChainLink* link=Chain_FirstLink(graphPtr->elements_.displayList);
- link; link = Chain_NextLink(link)) {
- Element* elemPtr = (Element*)Chain_GetValue(link);
- if (legendPtr->entryIsSelected(elemPtr)) {
- Tcl_DStringAppend(&dString, elemPtr->name_, -1);
- Tcl_DStringAppend(&dString, "\n", -1);
- }
- }
- }
-
- int nBytes = Tcl_DStringLength(&dString) - offset;
- strncpy(buffer, Tcl_DStringValue(&dString) + offset, maxBytes);
- Tcl_DStringFree(&dString);
- buffer[maxBytes] = '\0';
- return MIN(nBytes, maxBytes);
-}
-
-static void SelectCmdProc(ClientData clientData)
-{
- Legend* legendPtr = (Legend*)clientData;
- LegendOptions* ops = (LegendOptions*)legendPtr->ops();
-
- Tcl_Preserve(legendPtr);
- legendPtr->flags &= ~SELECT_PENDING;
- if (ops->selectCmd) {
- Tcl_Interp* interp = legendPtr->graphPtr_->interp_;
- if (Tcl_GlobalEval(interp, ops->selectCmd) != TCL_OK)
- Tcl_BackgroundError(interp);
- }
- Tcl_Release(legendPtr);
-}
-
-
-