1 |
|
---|
2 | /*
|
---|
3 | * bltGrBar.c --
|
---|
4 | *
|
---|
5 | * This module implements barchart elements for the BLT graph widget.
|
---|
6 | *
|
---|
7 | * Copyright 1993-1998 Lucent Technologies, Inc.
|
---|
8 | *
|
---|
9 | * Permission to use, copy, modify, and distribute this software and
|
---|
10 | * its documentation for any purpose and without fee is hereby
|
---|
11 | * granted, provided that the above copyright notice appear in all
|
---|
12 | * copies and that both that the copyright notice and warranty
|
---|
13 | * disclaimer appear in supporting documentation, and that the names
|
---|
14 | * of Lucent Technologies any of their entities not be used in
|
---|
15 | * advertising or publicity pertaining to distribution of the software
|
---|
16 | * without specific, written prior permission.
|
---|
17 | *
|
---|
18 | * Lucent Technologies disclaims all warranties with regard to this
|
---|
19 | * software, including all implied warranties of merchantability and
|
---|
20 | * fitness. In no event shall Lucent Technologies be liable for any
|
---|
21 | * special, indirect or consequential damages or any damages
|
---|
22 | * whatsoever resulting from loss of use, data or profits, whether in
|
---|
23 | * an action of contract, negligence or other tortuous action, arising
|
---|
24 | * out of or in connection with the use or performance of this
|
---|
25 | * software.
|
---|
26 | */
|
---|
27 |
|
---|
28 | #include "bltGraph.h"
|
---|
29 | #include <X11/Xutil.h>
|
---|
30 |
|
---|
31 | #include "bltGrElem.h"
|
---|
32 |
|
---|
33 | typedef struct {
|
---|
34 | char *name; /* Pen style identifier. If NULL pen
|
---|
35 | * was statically allocated. */
|
---|
36 | Blt_Uid classUid; /* Type of pen */
|
---|
37 | char *typeId; /* String token identifying the type of pen */
|
---|
38 | unsigned int flags; /* Indicates if the pen element is active or
|
---|
39 | * normal */
|
---|
40 | int refCount; /* Reference count for elements using
|
---|
41 | * this pen. */
|
---|
42 | Blt_HashEntry *hashPtr;
|
---|
43 | Tk_ConfigSpec *specsPtr; /* Configuration specifications */
|
---|
44 |
|
---|
45 | PenConfigureProc *configProc;
|
---|
46 | PenDestroyProc *destroyProc;
|
---|
47 |
|
---|
48 | XColor *fgColor; /* Foreground color of bar */
|
---|
49 | Tk_3DBorder border; /* 3D border and background color */
|
---|
50 | int borderWidth; /* 3D border width of bar */
|
---|
51 | int relief; /* Relief of the bar */
|
---|
52 | Pixmap stipple; /* Stipple */
|
---|
53 | GC gc; /* Graphics context */
|
---|
54 |
|
---|
55 | /* Error bar attributes. */
|
---|
56 | int errorBarShow; /* Describes which error bars to
|
---|
57 | * display: none, x, y, or * both. */
|
---|
58 |
|
---|
59 | int errorBarLineWidth; /* Width of the error bar segments. */
|
---|
60 |
|
---|
61 | int errorBarCapWidth;
|
---|
62 | XColor *errorBarColor; /* Color of the error bar. */
|
---|
63 |
|
---|
64 | GC errorBarGC; /* Error bar graphics context. */
|
---|
65 |
|
---|
66 | /* Show value attributes. */
|
---|
67 | int valueShow; /* Indicates whether to display data value.
|
---|
68 | * Values are x, y, or none. */
|
---|
69 |
|
---|
70 | char *valueFormat; /* A printf format string. */
|
---|
71 | TextStyle valueStyle; /* Text attributes (color, font,
|
---|
72 | * rotation, etc.) of the value. */
|
---|
73 |
|
---|
74 | } BarPen;
|
---|
75 |
|
---|
76 | typedef struct {
|
---|
77 | Weight weight; /* Weight range where this pen is valid. */
|
---|
78 |
|
---|
79 | BarPen *penPtr; /* Pen to draw */
|
---|
80 |
|
---|
81 | Segment2D *xErrorBars; /* Point to start of this pen's X-error bar
|
---|
82 | * segments in the element's array. */
|
---|
83 |
|
---|
84 | Segment2D *yErrorBars; /* Point to start of this pen's Y-error bar
|
---|
85 | * segments in the element's array. */
|
---|
86 | int xErrorBarCnt; /* # of error bars for this pen. */
|
---|
87 |
|
---|
88 | int yErrorBarCnt; /* # of error bars for this pen. */
|
---|
89 |
|
---|
90 | int errorBarCapWidth; /* Length of the cap ends on each
|
---|
91 | * error bar. */
|
---|
92 |
|
---|
93 | int symbolSize; /* Size of the pen's symbol scaled to the
|
---|
94 | * current graph size. */
|
---|
95 |
|
---|
96 | /* Bar chart specific data. */
|
---|
97 | XRectangle *rectangles; /* Indicates starting location in bar
|
---|
98 | * array for this pen. */
|
---|
99 | int nRects; /* Number of bar segments for this pen. */
|
---|
100 |
|
---|
101 | } BarPenStyle;
|
---|
102 |
|
---|
103 | typedef struct {
|
---|
104 | char *name; /* Identifier to refer the
|
---|
105 | * element. Used in the "insert",
|
---|
106 | * "delete", or "show", commands. */
|
---|
107 |
|
---|
108 | Blt_Uid classUid; /* Type of element; either
|
---|
109 | * bltBarElementUid, bltLineElementUid, or
|
---|
110 | * bltStripElementUid. */
|
---|
111 |
|
---|
112 | Graph *graphPtr; /* Graph widget of element*/
|
---|
113 | unsigned int flags; /* Indicates if the entire element is
|
---|
114 | * active, or if coordinates need to
|
---|
115 | * be calculated */
|
---|
116 | char **tags;
|
---|
117 | int hidden; /* If non-zero, don't display the element. */
|
---|
118 |
|
---|
119 | Blt_HashEntry *hashPtr;
|
---|
120 | char *label; /* Label displayed in legend */
|
---|
121 | int labelRelief; /* Relief of label in legend. */
|
---|
122 |
|
---|
123 | Axis2D axes;
|
---|
124 | ElemVector x, y, w; /* Contains array of numeric values */
|
---|
125 |
|
---|
126 | ElemVector xError; /* Relative/symmetric X error values. */
|
---|
127 | ElemVector yError; /* Relative/symmetric Y error values. */
|
---|
128 | ElemVector xHigh, xLow; /* Absolute/asymmetric X-coordinate high/low
|
---|
129 | error values. */
|
---|
130 | ElemVector yHigh, yLow; /* Absolute/asymmetric Y-coordinate high/low
|
---|
131 | error values. */
|
---|
132 |
|
---|
133 | int *activeIndices; /* Array of indices (malloc-ed) that
|
---|
134 | * indicate the data points have been
|
---|
135 | * selected as active (drawn with
|
---|
136 | * "active" colors). */
|
---|
137 |
|
---|
138 | int nActiveIndices; /* Number of active data points. Special
|
---|
139 | * case: if nActiveIndices < 0 and the
|
---|
140 | * active bit is set in "flags", then all
|
---|
141 | * data points are drawn active. */
|
---|
142 |
|
---|
143 | ElementProcs *procsPtr; /* Class information for bar elements */
|
---|
144 | Tk_ConfigSpec *specsPtr; /* Configuration specifications */
|
---|
145 |
|
---|
146 | Segment2D *xErrorBars; /* Point to start of this pen's X-error bar
|
---|
147 | * segments in the element's array. */
|
---|
148 | Segment2D *yErrorBars; /* Point to start of this pen's Y-error bar
|
---|
149 | * segments in the element's array. */
|
---|
150 | int xErrorBarCnt; /* # of error bars for this pen. */
|
---|
151 | int yErrorBarCnt; /* # of error bars for this pen. */
|
---|
152 |
|
---|
153 | int *xErrorToData; /* Maps individual error bar segments back
|
---|
154 | * to the data point associated with it. */
|
---|
155 | int *yErrorToData; /* Maps individual error bar segments back
|
---|
156 | * to the data point associated with it. */
|
---|
157 |
|
---|
158 | int errorBarCapWidth; /* Length of cap on error bars */
|
---|
159 |
|
---|
160 | BarPen *activePenPtr; /* Standard Pens */
|
---|
161 | BarPen *normalPenPtr;
|
---|
162 |
|
---|
163 | Blt_Chain *palette; /* Chain of pen style information. */
|
---|
164 |
|
---|
165 | /* Symbol scaling */
|
---|
166 | int scaleSymbols; /* If non-zero, the symbols will scale
|
---|
167 | * in size as the graph is zoomed
|
---|
168 | * in/out. */
|
---|
169 |
|
---|
170 | double xRange, yRange; /* Initial X-axis and Y-axis ranges:
|
---|
171 | * used to scale the size of element's
|
---|
172 | * symbol. */
|
---|
173 | int state;
|
---|
174 | /*
|
---|
175 | * Bar specific attributes
|
---|
176 | */
|
---|
177 | BarPen builtinPen;
|
---|
178 |
|
---|
179 | int *rectToData;
|
---|
180 | XRectangle *rectangles; /* Array of rectangles comprising the bar
|
---|
181 | * segments of the element. */
|
---|
182 | int nRects; /* # of visible bar segments for element */
|
---|
183 |
|
---|
184 | int padX; /* Spacing on either side of bar */
|
---|
185 | double barWidth;
|
---|
186 | int nActive;
|
---|
187 |
|
---|
188 | XRectangle *activeRects;
|
---|
189 | int *activeToData;
|
---|
190 | } Bar;
|
---|
191 |
|
---|
192 | extern Tk_CustomOption bltBarPenOption;
|
---|
193 | extern Tk_CustomOption bltDataOption;
|
---|
194 | extern Tk_CustomOption bltDataPairsOption;
|
---|
195 | extern Tk_CustomOption bltDistanceOption;
|
---|
196 | extern Tk_CustomOption bltListOption;
|
---|
197 | extern Tk_CustomOption bltXAxisOption;
|
---|
198 | extern Tk_CustomOption bltYAxisOption;
|
---|
199 | extern Tk_CustomOption bltShadowOption;
|
---|
200 | extern Tk_CustomOption bltFillOption;
|
---|
201 | extern Tk_CustomOption bltColorOption;
|
---|
202 | extern Tk_CustomOption bltStateOption;
|
---|
203 |
|
---|
204 | extern Tk_OptionParseProc Blt_StringToStyles;
|
---|
205 | extern Tk_OptionPrintProc Blt_StylesToString;
|
---|
206 | static Tk_OptionParseProc StringToBarMode;
|
---|
207 | static Tk_OptionPrintProc BarModeToString;
|
---|
208 |
|
---|
209 | static Tk_CustomOption stylesOption =
|
---|
210 | {
|
---|
211 | Blt_StringToStyles, Blt_StylesToString, (ClientData)sizeof(BarPenStyle)
|
---|
212 | };
|
---|
213 |
|
---|
214 | Tk_CustomOption bltBarModeOption =
|
---|
215 | {
|
---|
216 | StringToBarMode, BarModeToString, (ClientData)0
|
---|
217 | };
|
---|
218 |
|
---|
219 | #define DEF_BAR_ACTIVE_PEN "activeBar"
|
---|
220 | #define DEF_BAR_AXIS_X "x"
|
---|
221 | #define DEF_BAR_AXIS_Y "y"
|
---|
222 | #define DEF_BAR_BACKGROUND "navyblue"
|
---|
223 | #define DEF_BAR_BG_MONO BLACK
|
---|
224 | #define DEF_BAR_BORDERWIDTH "2"
|
---|
225 | #define DEF_BAR_DATA (char *)NULL
|
---|
226 | #define DEF_BAR_ERRORBAR_COLOR "defcolor"
|
---|
227 | #define DEF_BAR_ERRORBAR_LINE_WIDTH "1"
|
---|
228 | #define DEF_BAR_ERRORBAR_CAP_WIDTH "1"
|
---|
229 | #define DEF_BAR_FOREGROUND "blue"
|
---|
230 | #define DEF_BAR_FG_MONO WHITE
|
---|
231 | #define DEF_BAR_HIDE "no"
|
---|
232 | #define DEF_BAR_LABEL (char *)NULL
|
---|
233 | #define DEF_BAR_LABEL_RELIEF "flat"
|
---|
234 | #define DEF_BAR_NORMAL_STIPPLE ""
|
---|
235 | #define DEF_BAR_RELIEF "raised"
|
---|
236 | #define DEF_BAR_SHOW_ERRORBARS "both"
|
---|
237 | #define DEF_BAR_STATE "normal"
|
---|
238 | #define DEF_BAR_STYLES ""
|
---|
239 | #define DEF_BAR_TAGS "all"
|
---|
240 | #define DEF_BAR_WIDTH "0.0"
|
---|
241 | #define DEF_BAR_DATA (char *)NULL
|
---|
242 |
|
---|
243 | #define DEF_PEN_ACTIVE_BACKGROUND "red"
|
---|
244 | #define DEF_PEN_ACTIVE_BG_MONO WHITE
|
---|
245 | #define DEF_PEN_ACTIVE_FOREGROUND "pink"
|
---|
246 | #define DEF_PEN_ACTIVE_FG_MONO BLACK
|
---|
247 | #define DEF_PEN_BORDERWIDTH "2"
|
---|
248 | #define DEF_PEN_NORMAL_BACKGROUND "navyblue"
|
---|
249 | #define DEF_PEN_NORMAL_BG_MONO BLACK
|
---|
250 | #define DEF_PEN_NORMAL_FOREGROUND "blue"
|
---|
251 | #define DEF_PEN_NORMAL_FG_MONO WHITE
|
---|
252 | #define DEF_PEN_RELIEF "raised"
|
---|
253 | #define DEF_PEN_STIPPLE ""
|
---|
254 | #define DEF_PEN_TYPE "bar"
|
---|
255 | #define DEF_PEN_VALUE_ANCHOR "s"
|
---|
256 | #define DEF_PEN_VALUE_COLOR RGB_BLACK
|
---|
257 | #define DEF_PEN_VALUE_FONT STD_FONT_SMALL
|
---|
258 | #define DEF_PEN_VALUE_FORMAT "%g"
|
---|
259 | #define DEF_PEN_VALUE_ROTATE (char *)NULL
|
---|
260 | #define DEF_PEN_VALUE_SHADOW (char *)NULL
|
---|
261 | #define DEF_PEN_SHOW_VALUES "no"
|
---|
262 |
|
---|
263 | static Tk_ConfigSpec barPenConfigSpecs[] =
|
---|
264 | {
|
---|
265 | {TK_CONFIG_BORDER, "-background", "background", "Background",
|
---|
266 | DEF_PEN_ACTIVE_BACKGROUND, Tk_Offset(BarPen, border),
|
---|
267 | TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY | ACTIVE_PEN},
|
---|
268 | {TK_CONFIG_BORDER, "-background", "background", "Background",
|
---|
269 | DEF_PEN_ACTIVE_BACKGROUND, Tk_Offset(BarPen, border),
|
---|
270 | TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY | ACTIVE_PEN},
|
---|
271 | {TK_CONFIG_BORDER, "-background", "background", "Background",
|
---|
272 | DEF_PEN_NORMAL_BACKGROUND, Tk_Offset(BarPen, border),
|
---|
273 | TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY | NORMAL_PEN},
|
---|
274 | {TK_CONFIG_BORDER, "-background", "background", "Background",
|
---|
275 | DEF_PEN_NORMAL_BACKGROUND, Tk_Offset(BarPen, border),
|
---|
276 | TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY | NORMAL_PEN},
|
---|
277 | {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL,
|
---|
278 | (char *)NULL, 0, ALL_PENS},
|
---|
279 | {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL,
|
---|
280 | (char *)NULL, 0, ALL_PENS},
|
---|
281 | {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth",
|
---|
282 | DEF_PEN_BORDERWIDTH, Tk_Offset(BarPen, borderWidth), ALL_PENS,
|
---|
283 | &bltDistanceOption},
|
---|
284 | {TK_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
|
---|
285 | DEF_BAR_ERRORBAR_COLOR, Tk_Offset(BarPen, errorBarColor),
|
---|
286 | ALL_PENS, &bltColorOption},
|
---|
287 | {TK_CONFIG_CUSTOM, "-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
|
---|
288 | DEF_BAR_ERRORBAR_LINE_WIDTH, Tk_Offset(BarPen, errorBarLineWidth),
|
---|
289 | ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
|
---|
290 | {TK_CONFIG_CUSTOM, "-errorbarcap", "errorBarCap", "ErrorBarCap",
|
---|
291 | DEF_BAR_ERRORBAR_CAP_WIDTH, Tk_Offset(BarPen, errorBarCapWidth),
|
---|
292 | ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
|
---|
293 | {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL,
|
---|
294 | (char *)NULL, 0, ALL_PENS},
|
---|
295 | {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
---|
296 | DEF_PEN_ACTIVE_FOREGROUND, Tk_Offset(BarPen, fgColor),
|
---|
297 | ACTIVE_PEN | TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY},
|
---|
298 | {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
---|
299 | DEF_PEN_ACTIVE_FOREGROUND, Tk_Offset(BarPen, fgColor),
|
---|
300 | ACTIVE_PEN | TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY},
|
---|
301 | {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
---|
302 | DEF_PEN_NORMAL_FOREGROUND, Tk_Offset(BarPen, fgColor),
|
---|
303 | NORMAL_PEN | TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY},
|
---|
304 | {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
---|
305 | DEF_PEN_NORMAL_FOREGROUND, Tk_Offset(BarPen, fgColor),
|
---|
306 | NORMAL_PEN | TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY},
|
---|
307 | {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
|
---|
308 | DEF_PEN_RELIEF, Tk_Offset(BarPen, relief), ALL_PENS},
|
---|
309 | {TK_CONFIG_CUSTOM, "-showerrorbars", "showErrorBars", "ShowErrorBars",
|
---|
310 | DEF_BAR_SHOW_ERRORBARS, Tk_Offset(BarPen, errorBarShow),
|
---|
311 | TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
|
---|
312 | {TK_CONFIG_CUSTOM, "-showvalues", "showValues", "ShowValues",
|
---|
313 | DEF_PEN_SHOW_VALUES, Tk_Offset(BarPen, valueShow),
|
---|
314 | ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
|
---|
315 | {TK_CONFIG_BITMAP, "-stipple", "stipple", "Stipple",
|
---|
316 | DEF_PEN_STIPPLE, Tk_Offset(BarPen, stipple),
|
---|
317 | ALL_PENS | TK_CONFIG_NULL_OK},
|
---|
318 | {TK_CONFIG_STRING, "-type", (char *)NULL, (char *)NULL,
|
---|
319 | DEF_PEN_TYPE, Tk_Offset(BarPen, typeId), ALL_PENS | TK_CONFIG_NULL_OK},
|
---|
320 | {TK_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
|
---|
321 | DEF_PEN_VALUE_ANCHOR, Tk_Offset(BarPen, valueStyle.anchor), ALL_PENS},
|
---|
322 | {TK_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
|
---|
323 | DEF_PEN_VALUE_COLOR, Tk_Offset(BarPen, valueStyle.color), ALL_PENS},
|
---|
324 | {TK_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
|
---|
325 | DEF_PEN_VALUE_FONT, Tk_Offset(BarPen, valueStyle.font), ALL_PENS},
|
---|
326 | {TK_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
|
---|
327 | DEF_PEN_VALUE_FORMAT, Tk_Offset(BarPen, valueFormat),
|
---|
328 | ALL_PENS | TK_CONFIG_NULL_OK},
|
---|
329 | {TK_CONFIG_DOUBLE, "-valuerotate", "valueRotate", "ValueRotate",
|
---|
330 | DEF_PEN_VALUE_ROTATE, Tk_Offset(BarPen, valueStyle.theta), ALL_PENS},
|
---|
331 | {TK_CONFIG_CUSTOM, "-valueshadow", "valueShadow", "ValueShadow",
|
---|
332 | DEF_PEN_VALUE_SHADOW, Tk_Offset(BarPen, valueStyle.shadow),
|
---|
333 | ALL_PENS, &bltShadowOption},
|
---|
334 | {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
|
---|
335 | };
|
---|
336 |
|
---|
337 |
|
---|
338 | static Tk_ConfigSpec barElemConfigSpecs[] =
|
---|
339 | {
|
---|
340 | {TK_CONFIG_CUSTOM, "-activepen", "activePen", "ActivePen",
|
---|
341 | DEF_BAR_ACTIVE_PEN, Tk_Offset(Bar, activePenPtr),
|
---|
342 | TK_CONFIG_NULL_OK, &bltBarPenOption},
|
---|
343 | {TK_CONFIG_BORDER, "-background", "background", "Background",
|
---|
344 | DEF_BAR_BACKGROUND, Tk_Offset(Bar, builtinPen.border),
|
---|
345 | TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY},
|
---|
346 | {TK_CONFIG_BORDER, "-background", "background", "Background",
|
---|
347 | DEF_BAR_BACKGROUND, Tk_Offset(Bar, builtinPen.border),
|
---|
348 | TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY},
|
---|
349 | {TK_CONFIG_DOUBLE, "-barwidth", "barWidth", "BarWidth",
|
---|
350 | DEF_BAR_WIDTH, Tk_Offset(Bar, barWidth),
|
---|
351 | TK_CONFIG_DONT_SET_DEFAULT},
|
---|
352 | {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL,
|
---|
353 | (char *)NULL, 0, 0},
|
---|
354 | {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL,
|
---|
355 | (char *)NULL, 0, 0},
|
---|
356 | {TK_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags",
|
---|
357 | DEF_BAR_TAGS, Tk_Offset(Bar, tags),
|
---|
358 | TK_CONFIG_NULL_OK, &bltListOption},
|
---|
359 | {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth",
|
---|
360 | DEF_BAR_BORDERWIDTH, Tk_Offset(Bar, builtinPen.borderWidth),
|
---|
361 | 0, &bltDistanceOption},
|
---|
362 | {TK_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
|
---|
363 | DEF_BAR_ERRORBAR_COLOR, Tk_Offset(Bar, builtinPen.errorBarColor),
|
---|
364 | 0, &bltColorOption},
|
---|
365 | {TK_CONFIG_CUSTOM, "-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
|
---|
366 | DEF_BAR_ERRORBAR_LINE_WIDTH,
|
---|
367 | Tk_Offset(Bar, builtinPen.errorBarLineWidth),
|
---|
368 | TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
|
---|
369 | {TK_CONFIG_CUSTOM, "-errorbarcap", "errorBarCap", "ErrorBarCap",
|
---|
370 | DEF_BAR_ERRORBAR_CAP_WIDTH, Tk_Offset(Bar, builtinPen.errorBarCapWidth),
|
---|
371 | ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
|
---|
372 | {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
|
---|
373 | {TK_CONFIG_CUSTOM, "-data", "data", "Data",
|
---|
374 | (char *)NULL, 0, 0, &bltDataPairsOption},
|
---|
375 | {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
---|
376 | DEF_BAR_FOREGROUND, Tk_Offset(Bar, builtinPen.fgColor),
|
---|
377 | TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY},
|
---|
378 | {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
---|
379 | DEF_BAR_FOREGROUND, Tk_Offset(Bar, builtinPen.fgColor),
|
---|
380 | TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY},
|
---|
381 | {TK_CONFIG_STRING, "-label", "label", "Label",
|
---|
382 | DEF_BAR_LABEL, Tk_Offset(Bar, label), TK_CONFIG_NULL_OK},
|
---|
383 | {TK_CONFIG_RELIEF, "-labelrelief", "labelRelief", "LabelRelief",
|
---|
384 | DEF_BAR_LABEL_RELIEF, Tk_Offset(Bar, labelRelief),
|
---|
385 | TK_CONFIG_DONT_SET_DEFAULT},
|
---|
386 | {TK_CONFIG_BOOLEAN, "-hide", "hide", "Hide",
|
---|
387 | DEF_BAR_HIDE, Tk_Offset(Bar, hidden),
|
---|
388 | TK_CONFIG_DONT_SET_DEFAULT},
|
---|
389 | {TK_CONFIG_CUSTOM, "-mapx", "mapX", "MapX",
|
---|
390 | DEF_BAR_AXIS_X, Tk_Offset(Bar, axes.x), 0, &bltXAxisOption},
|
---|
391 | {TK_CONFIG_CUSTOM, "-mapy", "mapY", "MapY",
|
---|
392 | DEF_BAR_AXIS_Y, Tk_Offset(Bar, axes.y), 0, &bltYAxisOption},
|
---|
393 | {TK_CONFIG_CUSTOM, "-pen", "pen", "Pen",
|
---|
394 | (char *)NULL, Tk_Offset(Bar, normalPenPtr),
|
---|
395 | TK_CONFIG_NULL_OK, &bltBarPenOption},
|
---|
396 | {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
|
---|
397 | DEF_BAR_RELIEF, Tk_Offset(Bar, builtinPen.relief), 0},
|
---|
398 | {TK_CONFIG_CUSTOM, "-showerrorbars", "showErrorBars", "ShowErrorBars",
|
---|
399 | DEF_BAR_SHOW_ERRORBARS, Tk_Offset(Bar, builtinPen.errorBarShow),
|
---|
400 | TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
|
---|
401 | {TK_CONFIG_CUSTOM, "-showvalues", "showValues", "ShowValues",
|
---|
402 | DEF_PEN_SHOW_VALUES, Tk_Offset(Bar, builtinPen.valueShow),
|
---|
403 | TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
|
---|
404 | {TK_CONFIG_CUSTOM, "-state", "state", "State",
|
---|
405 | DEF_BAR_STATE, Tk_Offset(Bar, state),
|
---|
406 | TK_CONFIG_DONT_SET_DEFAULT, &bltStateOption},
|
---|
407 | {TK_CONFIG_BITMAP, "-stipple", "stipple", "Stipple",
|
---|
408 | DEF_BAR_NORMAL_STIPPLE, Tk_Offset(Bar, builtinPen.stipple),
|
---|
409 | TK_CONFIG_NULL_OK},
|
---|
410 | {TK_CONFIG_CUSTOM, "-styles", "styles", "Styles",
|
---|
411 | DEF_BAR_STYLES, Tk_Offset(Bar, palette),
|
---|
412 | TK_CONFIG_NULL_OK, &stylesOption},
|
---|
413 | {TK_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
|
---|
414 | DEF_PEN_VALUE_ANCHOR, Tk_Offset(Bar, builtinPen.valueStyle.anchor), 0},
|
---|
415 | {TK_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
|
---|
416 | DEF_PEN_VALUE_COLOR, Tk_Offset(Bar, builtinPen.valueStyle.color), 0},
|
---|
417 | {TK_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
|
---|
418 | DEF_PEN_VALUE_FONT, Tk_Offset(Bar, builtinPen.valueStyle.font), 0},
|
---|
419 | {TK_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
|
---|
420 | DEF_PEN_VALUE_FORMAT, Tk_Offset(Bar, builtinPen.valueFormat),
|
---|
421 | TK_CONFIG_NULL_OK},
|
---|
422 | {TK_CONFIG_DOUBLE, "-valuerotate", "valueRotate", "ValueRotate",
|
---|
423 | DEF_PEN_VALUE_ROTATE, Tk_Offset(Bar, builtinPen.valueStyle.theta), 0},
|
---|
424 | {TK_CONFIG_CUSTOM, "-valueshadow", "valueShadow", "ValueShadow",
|
---|
425 | DEF_PEN_VALUE_SHADOW, Tk_Offset(Bar, builtinPen.valueStyle.shadow),
|
---|
426 | 0, &bltShadowOption},
|
---|
427 |
|
---|
428 | {TK_CONFIG_CUSTOM, "-weights", "weights", "Weights",
|
---|
429 | (char *)NULL, Tk_Offset(Bar, w), 0, &bltDataOption},
|
---|
430 | {TK_CONFIG_CUSTOM, "-x", "xdata", "Xdata",
|
---|
431 | DEF_BAR_DATA, Tk_Offset(Bar, x), 0, &bltDataOption},
|
---|
432 | {TK_CONFIG_CUSTOM, "-y", "ydata", "Ydata",
|
---|
433 | DEF_BAR_DATA, Tk_Offset(Bar, y), 0, &bltDataOption},
|
---|
434 | {TK_CONFIG_CUSTOM, "-xdata", "xdata", "Xdata",
|
---|
435 | DEF_BAR_DATA, Tk_Offset(Bar, x), 0, &bltDataOption},
|
---|
436 | {TK_CONFIG_CUSTOM, "-ydata", "ydata", "Ydata",
|
---|
437 | DEF_BAR_DATA, Tk_Offset(Bar, y), 0, &bltDataOption},
|
---|
438 | {TK_CONFIG_CUSTOM, "-xerror", "xError", "XError",
|
---|
439 | DEF_BAR_DATA, Tk_Offset(Bar, xError), 0, &bltDataOption},
|
---|
440 | {TK_CONFIG_CUSTOM, "-xhigh", "xHigh", "XHigh",
|
---|
441 | DEF_BAR_DATA, Tk_Offset(Bar, xHigh), 0, &bltDataOption},
|
---|
442 | {TK_CONFIG_CUSTOM, "-xlow", "xLow", "XLow",
|
---|
443 | DEF_BAR_DATA, Tk_Offset(Bar, xLow), 0, &bltDataOption},
|
---|
444 | {TK_CONFIG_CUSTOM, "-yerror", "yError", "YError",
|
---|
445 | DEF_BAR_DATA, Tk_Offset(Bar, yError), 0, &bltDataOption},
|
---|
446 | {TK_CONFIG_CUSTOM, "-yhigh", "yHigh", "YHigh",
|
---|
447 | DEF_BAR_DATA, Tk_Offset(Bar, yHigh), 0, &bltDataOption},
|
---|
448 | {TK_CONFIG_CUSTOM, "-ylow", "yLow", "YLow",
|
---|
449 | DEF_BAR_DATA, Tk_Offset(Bar, yLow), 0, &bltDataOption},
|
---|
450 | {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
|
---|
451 | };
|
---|
452 |
|
---|
453 | /* Forward declarations */
|
---|
454 | static PenConfigureProc ConfigurePen;
|
---|
455 | static PenDestroyProc DestroyPen;
|
---|
456 | static ElementClosestProc ClosestBar;
|
---|
457 | static ElementConfigProc ConfigureBar;
|
---|
458 | static ElementDestroyProc DestroyBar;
|
---|
459 | static ElementDrawProc DrawActiveBar;
|
---|
460 | static ElementDrawProc DrawNormalBar;
|
---|
461 | static ElementDrawSymbolProc DrawSymbol;
|
---|
462 | static ElementExtentsProc GetBarExtents;
|
---|
463 | static ElementToPostScriptProc ActiveBarToPostScript;
|
---|
464 | static ElementToPostScriptProc NormalBarToPostScript;
|
---|
465 | static ElementSymbolToPostScriptProc SymbolToPostScript;
|
---|
466 | static ElementMapProc MapBar;
|
---|
467 |
|
---|
468 | INLINE static int
|
---|
469 | Round(x)
|
---|
470 | register double x;
|
---|
471 | {
|
---|
472 | return (int) (x + ((x < 0.0) ? -0.5 : 0.5));
|
---|
473 | }
|
---|
474 |
|
---|
475 | /*
|
---|
476 | * ----------------------------------------------------------------------
|
---|
477 | * Custom option parse and print procedures
|
---|
478 | * ----------------------------------------------------------------------
|
---|
479 | */
|
---|
480 |
|
---|
481 | /*
|
---|
482 | * ----------------------------------------------------------------------
|
---|
483 | *
|
---|
484 | * NameOfBarMode --
|
---|
485 | *
|
---|
486 | * Converts the integer representing the mode style into a string.
|
---|
487 | *
|
---|
488 | * ----------------------------------------------------------------------
|
---|
489 | */
|
---|
490 | static char *
|
---|
491 | NameOfBarMode(mode)
|
---|
492 | BarMode mode;
|
---|
493 | {
|
---|
494 | switch (mode) {
|
---|
495 | case MODE_INFRONT:
|
---|
496 | return "infront";
|
---|
497 | case MODE_OVERLAP:
|
---|
498 | return "overlap";
|
---|
499 | case MODE_STACKED:
|
---|
500 | return "stacked";
|
---|
501 | case MODE_ALIGNED:
|
---|
502 | return "aligned";
|
---|
503 | default:
|
---|
504 | return "unknown mode value";
|
---|
505 | }
|
---|
506 | }
|
---|
507 |
|
---|
508 | /*
|
---|
509 | * ----------------------------------------------------------------------
|
---|
510 | *
|
---|
511 | * StringToMode --
|
---|
512 | *
|
---|
513 | * Converts the mode string into its numeric representation.
|
---|
514 | *
|
---|
515 | * Valid mode strings are:
|
---|
516 | *
|
---|
517 | * "infront" Draw a full bar at each point in the element.
|
---|
518 | *
|
---|
519 | * "stacked" Stack bar segments vertically. Each stack is defined
|
---|
520 | * by each ordinate at a particular abscissa. The height
|
---|
521 | * of each segment is represented by the sum the previous
|
---|
522 | * ordinates.
|
---|
523 | *
|
---|
524 | * "aligned" Align bar segments as smaller slices one next to
|
---|
525 | * the other. Like "stacks", aligned segments are
|
---|
526 | * defined by each ordinate at a particular abscissa.
|
---|
527 | *
|
---|
528 | * Results:
|
---|
529 | * A standard Tcl result.
|
---|
530 | *
|
---|
531 | * ----------------------------------------------------------------------
|
---|
532 | */
|
---|
533 | /*ARGSUSED*/
|
---|
534 | static int
|
---|
535 | StringToBarMode(clientData, interp, tkwin, string, widgRec, offset)
|
---|
536 | ClientData clientData; /* Not used. */
|
---|
537 | Tcl_Interp *interp; /* Interpreter to send results back to */
|
---|
538 | Tk_Window tkwin; /* Not used. */
|
---|
539 | char *string; /* Mode style string */
|
---|
540 | char *widgRec; /* Cubicle structure record */
|
---|
541 | int offset; /* Offset of style in record */
|
---|
542 | {
|
---|
543 | BarMode *modePtr = (BarMode *)(widgRec + offset);
|
---|
544 | unsigned int length;
|
---|
545 | char c;
|
---|
546 |
|
---|
547 | c = string[0];
|
---|
548 | length = strlen(string);
|
---|
549 | if ((c == 'n') && (strncmp(string, "normal", length) == 0)) {
|
---|
550 | *modePtr = MODE_INFRONT;
|
---|
551 | } else if ((c == 'i') && (strncmp(string, "infront", length) == 0)) {
|
---|
552 | *modePtr = MODE_INFRONT;
|
---|
553 | } else if ((c == 's') && (strncmp(string, "stacked", length) == 0)) {
|
---|
554 | *modePtr = MODE_STACKED;
|
---|
555 | } else if ((c == 'a') && (strncmp(string, "aligned", length) == 0)) {
|
---|
556 | *modePtr = MODE_ALIGNED;
|
---|
557 | } else if ((c == 'o') && (strncmp(string, "overlap", length) == 0)) {
|
---|
558 | *modePtr = MODE_OVERLAP;
|
---|
559 | } else {
|
---|
560 | Tcl_AppendResult(interp, "bad mode argument \"", string,
|
---|
561 | "\": should be \"infront\", \"stacked\", \"overlap\", or \"aligned\"",
|
---|
562 | (char *)NULL);
|
---|
563 | return TCL_ERROR;
|
---|
564 | }
|
---|
565 | return TCL_OK;
|
---|
566 | }
|
---|
567 |
|
---|
568 | /*
|
---|
569 | * ----------------------------------------------------------------------
|
---|
570 | *
|
---|
571 | * BarModeToString --
|
---|
572 | *
|
---|
573 | * Returns the mode style string based upon the mode flags.
|
---|
574 | *
|
---|
575 | * Results:
|
---|
576 | * The mode style string is returned.
|
---|
577 | *
|
---|
578 | * ----------------------------------------------------------------------
|
---|
579 | */
|
---|
580 | /*ARGSUSED*/
|
---|
581 | static char *
|
---|
582 | BarModeToString(clientData, tkwin, widgRec, offset, freeProcPtr)
|
---|
583 | ClientData clientData; /* Not used. */
|
---|
584 | Tk_Window tkwin; /* Not used. */
|
---|
585 | char *widgRec; /* Row/column structure record */
|
---|
586 | int offset; /* Offset of mode in Partition record */
|
---|
587 | Tcl_FreeProc **freeProcPtr; /* Not used. */
|
---|
588 | {
|
---|
589 | BarMode mode = *(BarMode *)(widgRec + offset);
|
---|
590 |
|
---|
591 | return NameOfBarMode(mode);
|
---|
592 | }
|
---|
593 |
|
---|
594 |
|
---|
595 | /*
|
---|
596 | * Zero out the style's number of rectangles and errorbars.
|
---|
597 | */
|
---|
598 | static void
|
---|
599 | ClearPalette(palette)
|
---|
600 | Blt_Chain *palette;
|
---|
601 | {
|
---|
602 | register BarPenStyle *stylePtr;
|
---|
603 | Blt_ChainLink *linkPtr;
|
---|
604 |
|
---|
605 | for (linkPtr = Blt_ChainFirstLink(palette); linkPtr != NULL;
|
---|
606 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
607 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
608 | stylePtr->xErrorBarCnt = stylePtr->yErrorBarCnt = stylePtr->nRects = 0;
|
---|
609 | }
|
---|
610 | }
|
---|
611 |
|
---|
612 | static int
|
---|
613 | ConfigurePen(graphPtr, penPtr)
|
---|
614 | Graph *graphPtr;
|
---|
615 | Pen *penPtr;
|
---|
616 | {
|
---|
617 | BarPen *bpPtr = (BarPen *)penPtr;
|
---|
618 | XGCValues gcValues;
|
---|
619 | unsigned long gcMask;
|
---|
620 | int fillStyle;
|
---|
621 | GC newGC;
|
---|
622 | long defColor;
|
---|
623 |
|
---|
624 | Blt_ResetTextStyle(graphPtr->tkwin, &(bpPtr->valueStyle));
|
---|
625 | gcMask = GCForeground;
|
---|
626 | if (bpPtr->fgColor != NULL) {
|
---|
627 | defColor = bpPtr->fgColor->pixel;
|
---|
628 | gcValues.foreground = bpPtr->fgColor->pixel;
|
---|
629 | } else if (bpPtr->border != NULL) {
|
---|
630 | defColor = Tk_3DBorderColor(bpPtr->border)->pixel;
|
---|
631 | gcValues.foreground = Tk_3DBorderColor(bpPtr->border)->pixel;
|
---|
632 | } else {
|
---|
633 | defColor = BlackPixel(graphPtr->display,
|
---|
634 | Tk_ScreenNumber(graphPtr->tkwin));
|
---|
635 | }
|
---|
636 | if ((bpPtr->fgColor != NULL) && (bpPtr->border != NULL)) {
|
---|
637 | gcMask |= GCBackground;
|
---|
638 | gcValues.background = Tk_3DBorderColor(bpPtr->border)->pixel;
|
---|
639 | fillStyle = FillOpaqueStippled;
|
---|
640 | } else {
|
---|
641 | fillStyle = FillStippled;
|
---|
642 | }
|
---|
643 | if (bpPtr->stipple != None) {
|
---|
644 | gcValues.stipple = bpPtr->stipple;
|
---|
645 | gcValues.fill_style = fillStyle;
|
---|
646 | gcMask |= (GCStipple | GCFillStyle);
|
---|
647 | }
|
---|
648 | newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
|
---|
649 | if (bpPtr->gc != NULL) {
|
---|
650 | Tk_FreeGC(graphPtr->display, bpPtr->gc);
|
---|
651 | }
|
---|
652 | bpPtr->gc = newGC;
|
---|
653 |
|
---|
654 | gcMask = GCForeground | GCLineWidth;
|
---|
655 | if (bpPtr->errorBarColor == COLOR_DEFAULT) {
|
---|
656 | gcValues.foreground = defColor;
|
---|
657 | } else {
|
---|
658 | gcValues.foreground = bpPtr->errorBarColor->pixel;
|
---|
659 | }
|
---|
660 | gcValues.line_width = LineWidth(bpPtr->errorBarLineWidth);
|
---|
661 | newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
|
---|
662 | if (bpPtr->errorBarGC != NULL) {
|
---|
663 | Tk_FreeGC(graphPtr->display, bpPtr->errorBarGC);
|
---|
664 | }
|
---|
665 | bpPtr->errorBarGC = newGC;
|
---|
666 |
|
---|
667 | return TCL_OK;
|
---|
668 | }
|
---|
669 |
|
---|
670 | static void
|
---|
671 | DestroyPen(graphPtr, penPtr)
|
---|
672 | Graph *graphPtr;
|
---|
673 | Pen *penPtr;
|
---|
674 | {
|
---|
675 | BarPen *bpPtr = (BarPen *)penPtr;
|
---|
676 |
|
---|
677 | Blt_FreeTextStyle(graphPtr->display, &(bpPtr->valueStyle));
|
---|
678 | if (bpPtr->gc != NULL) {
|
---|
679 | Tk_FreeGC(graphPtr->display, bpPtr->gc);
|
---|
680 | }
|
---|
681 | if (bpPtr->errorBarGC != NULL) {
|
---|
682 | Tk_FreeGC(graphPtr->display, bpPtr->errorBarGC);
|
---|
683 | }
|
---|
684 | }
|
---|
685 |
|
---|
686 | static void
|
---|
687 | InitPen(penPtr)
|
---|
688 | BarPen *penPtr;
|
---|
689 | {
|
---|
690 | Blt_InitTextStyle(&(penPtr->valueStyle));
|
---|
691 | penPtr->specsPtr = barPenConfigSpecs;
|
---|
692 | penPtr->configProc = ConfigurePen;
|
---|
693 | penPtr->destroyProc = DestroyPen;
|
---|
694 | penPtr->relief = TK_RELIEF_RAISED;
|
---|
695 | penPtr->flags = NORMAL_PEN;
|
---|
696 | penPtr->errorBarShow = SHOW_BOTH;
|
---|
697 | penPtr->valueShow = SHOW_NONE;
|
---|
698 | penPtr->borderWidth = 2;
|
---|
699 | }
|
---|
700 |
|
---|
701 | Pen *
|
---|
702 | Blt_BarPen(penName)
|
---|
703 | char *penName;
|
---|
704 | {
|
---|
705 | BarPen *penPtr;
|
---|
706 |
|
---|
707 | penPtr = Blt_Calloc(1, sizeof(BarPen));
|
---|
708 | assert(penPtr);
|
---|
709 | InitPen(penPtr);
|
---|
710 | penPtr->name = Blt_Strdup(penName);
|
---|
711 | if (strcmp(penName, "activeBar") == 0) {
|
---|
712 | penPtr->flags = ACTIVE_PEN;
|
---|
713 | }
|
---|
714 | return (Pen *) penPtr;
|
---|
715 | }
|
---|
716 |
|
---|
717 | /*
|
---|
718 | * ----------------------------------------------------------------------
|
---|
719 | *
|
---|
720 | * CheckStacks --
|
---|
721 | *
|
---|
722 | * Check that the data limits are not superseded by the heights
|
---|
723 | * of stacked bar segments. The heights are calculated by
|
---|
724 | * Blt_ComputeStacks.
|
---|
725 | *
|
---|
726 | * Results:
|
---|
727 | * If the y-axis limits need to be adjusted for stacked segments,
|
---|
728 | * *minPtr* or *maxPtr* are updated.
|
---|
729 | *
|
---|
730 | * Side effects:
|
---|
731 | * Autoscaling of the y-axis is affected.
|
---|
732 | *
|
---|
733 | * ----------------------------------------------------------------------
|
---|
734 | */
|
---|
735 | static void
|
---|
736 | CheckStacks(graphPtr, pairPtr, minPtr, maxPtr)
|
---|
737 | Graph *graphPtr;
|
---|
738 | Axis2D *pairPtr;
|
---|
739 | double *minPtr, *maxPtr; /* Current minimum maximum for y-axis */
|
---|
740 | {
|
---|
741 | FreqInfo *infoPtr;
|
---|
742 | register int i;
|
---|
743 |
|
---|
744 | if ((graphPtr->mode != MODE_STACKED) || (graphPtr->nStacks == 0)) {
|
---|
745 | return;
|
---|
746 | }
|
---|
747 | infoPtr = graphPtr->freqArr;
|
---|
748 | for (i = 0; i < graphPtr->nStacks; i++) {
|
---|
749 | if ((infoPtr->axes.x == pairPtr->x) &&
|
---|
750 | (infoPtr->axes.y == pairPtr->y)) {
|
---|
751 | /*
|
---|
752 |
|
---|
753 | * Check if any of the y-values (because of stacking) are
|
---|
754 | * greater than the current limits of the graph.
|
---|
755 | */
|
---|
756 | if (infoPtr->sum < 0.0) {
|
---|
757 | if (*minPtr > infoPtr->sum) {
|
---|
758 | *minPtr = infoPtr->sum;
|
---|
759 | }
|
---|
760 | } else {
|
---|
761 | if (*maxPtr < infoPtr->sum) {
|
---|
762 | *maxPtr = infoPtr->sum;
|
---|
763 | }
|
---|
764 | }
|
---|
765 | }
|
---|
766 | infoPtr++;
|
---|
767 | }
|
---|
768 | }
|
---|
769 |
|
---|
770 | /*
|
---|
771 | * ----------------------------------------------------------------------
|
---|
772 | *
|
---|
773 | * ConfigureBar --
|
---|
774 | *
|
---|
775 | * Sets up the appropriate configuration parameters in the GC.
|
---|
776 | * It is assumed the parameters have been previously set by
|
---|
777 | * a call to Tk_ConfigureWidget.
|
---|
778 | *
|
---|
779 | * Results:
|
---|
780 | * The return value is a standard Tcl result. If TCL_ERROR is
|
---|
781 | * returned, then interp->result contains an error message.
|
---|
782 | *
|
---|
783 | * Side effects:
|
---|
784 | * Configuration information such as bar foreground/background
|
---|
785 | * color and stipple etc. get set in a new GC.
|
---|
786 | *
|
---|
787 | * ----------------------------------------------------------------------
|
---|
788 | */
|
---|
789 | /*ARGSUSED*/
|
---|
790 | static int
|
---|
791 | ConfigureBar(graphPtr, elemPtr)
|
---|
792 | Graph *graphPtr;
|
---|
793 | register Element *elemPtr;
|
---|
794 | {
|
---|
795 | Bar *barPtr = (Bar *)elemPtr;
|
---|
796 | Blt_ChainLink *linkPtr;
|
---|
797 |
|
---|
798 | if (ConfigurePen(graphPtr, (Pen *)&(barPtr->builtinPen)) != TCL_OK) {
|
---|
799 | return TCL_ERROR;
|
---|
800 | }
|
---|
801 | /*
|
---|
802 | * Point to the static normal pen if no external pens have
|
---|
803 | * been selected.
|
---|
804 | */
|
---|
805 | if (barPtr->normalPenPtr == NULL) {
|
---|
806 | barPtr->normalPenPtr = &(barPtr->builtinPen);
|
---|
807 | }
|
---|
808 | linkPtr = Blt_ChainFirstLink(barPtr->palette);
|
---|
809 | if (linkPtr != NULL) {
|
---|
810 | BarPenStyle *stylePtr;
|
---|
811 |
|
---|
812 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
813 | stylePtr->penPtr = barPtr->normalPenPtr;
|
---|
814 | }
|
---|
815 | if (Blt_ConfigModified(barPtr->specsPtr, "-barwidth", "-*data",
|
---|
816 | "-map*", "-label", "-hide", "-x", "-y", (char *)NULL)) {
|
---|
817 | barPtr->flags |= MAP_ITEM;
|
---|
818 | }
|
---|
819 | return TCL_OK;
|
---|
820 | }
|
---|
821 |
|
---|
822 | static void
|
---|
823 | GetBarExtents(elemPtr, extsPtr)
|
---|
824 | Element *elemPtr;
|
---|
825 | Extents2D *extsPtr;
|
---|
826 | {
|
---|
827 | Graph *graphPtr = elemPtr->graphPtr;
|
---|
828 | Bar *barPtr = (Bar *)elemPtr;
|
---|
829 | double middle, barWidth;
|
---|
830 | int nPoints;
|
---|
831 |
|
---|
832 | extsPtr->top = extsPtr->left = DBL_MAX;
|
---|
833 | extsPtr->bottom = extsPtr->right = -DBL_MAX;
|
---|
834 |
|
---|
835 | nPoints = NumberOfPoints(barPtr);
|
---|
836 | if (nPoints < 1) {
|
---|
837 | return; /* No data points */
|
---|
838 | }
|
---|
839 | barWidth = graphPtr->barWidth;
|
---|
840 | if (barPtr->barWidth > 0.0) {
|
---|
841 | barWidth = barPtr->barWidth;
|
---|
842 | }
|
---|
843 | middle = barWidth * 0.5;
|
---|
844 | extsPtr->left = barPtr->x.min - middle;
|
---|
845 | extsPtr->right = barPtr->x.max + middle;
|
---|
846 |
|
---|
847 | extsPtr->top = barPtr->y.min;
|
---|
848 | extsPtr->bottom = barPtr->y.max;
|
---|
849 | if (extsPtr->bottom < graphPtr->baseline) {
|
---|
850 | extsPtr->bottom = graphPtr->baseline;
|
---|
851 | }
|
---|
852 | /*
|
---|
853 | * Handle "stacked" bar elements specially.
|
---|
854 | *
|
---|
855 | * If element is stacked, the sum of its ordinates may be outside
|
---|
856 | * the minimum/maximum limits of the element's data points.
|
---|
857 | */
|
---|
858 | if ((graphPtr->mode == MODE_STACKED) && (graphPtr->nStacks > 0)) {
|
---|
859 | CheckStacks(graphPtr, &(elemPtr->axes), &(extsPtr->top),
|
---|
860 | &(extsPtr->bottom));
|
---|
861 | }
|
---|
862 | /* Warning: You get what you deserve if the x-axis is logScale */
|
---|
863 | if (elemPtr->axes.x->logScale) {
|
---|
864 | extsPtr->left = Blt_FindElemVectorMinimum(&(barPtr->x), DBL_MIN) +
|
---|
865 | middle;
|
---|
866 | }
|
---|
867 | /* Fix y-min limits for barchart */
|
---|
868 | if (elemPtr->axes.y->logScale) {
|
---|
869 | if ((extsPtr->top <= 0.0) || (extsPtr->top > 1.0)) {
|
---|
870 | extsPtr->top = 1.0;
|
---|
871 | }
|
---|
872 | } else {
|
---|
873 | if (extsPtr->top > 0.0) {
|
---|
874 | extsPtr->top = 0.0;
|
---|
875 | }
|
---|
876 | }
|
---|
877 | /* Correct the extents for error bars if they exist. */
|
---|
878 | if (elemPtr->xError.nValues > 0) {
|
---|
879 | register int i;
|
---|
880 | double x;
|
---|
881 |
|
---|
882 | /* Correct the data limits for error bars */
|
---|
883 | nPoints = MIN(elemPtr->xError.nValues, nPoints);
|
---|
884 | for (i = 0; i < nPoints; i++) {
|
---|
885 | x = elemPtr->x.valueArr[i] + elemPtr->xError.valueArr[i];
|
---|
886 | if (x > extsPtr->right) {
|
---|
887 | extsPtr->right = x;
|
---|
888 | }
|
---|
889 | x = elemPtr->x.valueArr[i] - elemPtr->xError.valueArr[i];
|
---|
890 | if (elemPtr->axes.x->logScale) {
|
---|
891 | if (x < 0.0) {
|
---|
892 | x = -x; /* Mirror negative values, instead
|
---|
893 | * of ignoring them. */
|
---|
894 | }
|
---|
895 | if ((x > DBL_MIN) && (x < extsPtr->left)) {
|
---|
896 | extsPtr->left = x;
|
---|
897 | }
|
---|
898 | } else if (x < extsPtr->left) {
|
---|
899 | extsPtr->left = x;
|
---|
900 | }
|
---|
901 | }
|
---|
902 | } else {
|
---|
903 | if ((elemPtr->xHigh.nValues > 0) &&
|
---|
904 | (elemPtr->xHigh.max > extsPtr->right)) {
|
---|
905 | extsPtr->right = elemPtr->xHigh.max;
|
---|
906 | }
|
---|
907 | if (elemPtr->xLow.nValues > 0) {
|
---|
908 | double left;
|
---|
909 |
|
---|
910 | if ((elemPtr->xLow.min <= 0.0) &&
|
---|
911 | (elemPtr->axes.x->logScale)) {
|
---|
912 | left = Blt_FindElemVectorMinimum(&elemPtr->xLow, DBL_MIN);
|
---|
913 | } else {
|
---|
914 | left = elemPtr->xLow.min;
|
---|
915 | }
|
---|
916 | if (left < extsPtr->left) {
|
---|
917 | extsPtr->left = left;
|
---|
918 | }
|
---|
919 | }
|
---|
920 | }
|
---|
921 | if (elemPtr->yError.nValues > 0) {
|
---|
922 | register int i;
|
---|
923 | double y;
|
---|
924 |
|
---|
925 | nPoints = MIN(elemPtr->yError.nValues, nPoints);
|
---|
926 | for (i = 0; i < nPoints; i++) {
|
---|
927 | y = elemPtr->y.valueArr[i] + elemPtr->yError.valueArr[i];
|
---|
928 | if (y > extsPtr->bottom) {
|
---|
929 | extsPtr->bottom = y;
|
---|
930 | }
|
---|
931 | y = elemPtr->y.valueArr[i] - elemPtr->yError.valueArr[i];
|
---|
932 | if (elemPtr->axes.y->logScale) {
|
---|
933 | if (y < 0.0) {
|
---|
934 | y = -y; /* Mirror negative values, instead
|
---|
935 | * of ignoring them. */
|
---|
936 | }
|
---|
937 | if ((y > DBL_MIN) && (y < extsPtr->left)) {
|
---|
938 | extsPtr->top = y;
|
---|
939 | }
|
---|
940 | } else if (y < extsPtr->top) {
|
---|
941 | extsPtr->top = y;
|
---|
942 | }
|
---|
943 | }
|
---|
944 | } else {
|
---|
945 | if ((elemPtr->yHigh.nValues > 0) &&
|
---|
946 | (elemPtr->yHigh.max > extsPtr->bottom)) {
|
---|
947 | extsPtr->bottom = elemPtr->yHigh.max;
|
---|
948 | }
|
---|
949 | if (elemPtr->yLow.nValues > 0) {
|
---|
950 | double top;
|
---|
951 |
|
---|
952 | if ((elemPtr->yLow.min <= 0.0) &&
|
---|
953 | (elemPtr->axes.y->logScale)) {
|
---|
954 | top = Blt_FindElemVectorMinimum(&elemPtr->yLow, DBL_MIN);
|
---|
955 | } else {
|
---|
956 | top = elemPtr->yLow.min;
|
---|
957 | }
|
---|
958 | if (top < extsPtr->top) {
|
---|
959 | extsPtr->top = top;
|
---|
960 | }
|
---|
961 | }
|
---|
962 | }
|
---|
963 | }
|
---|
964 |
|
---|
965 | /*
|
---|
966 | * ----------------------------------------------------------------------
|
---|
967 | *
|
---|
968 | * ClosestBar --
|
---|
969 | *
|
---|
970 | * Find the bar segment closest to the window coordinates point
|
---|
971 | * specified.
|
---|
972 | *
|
---|
973 | * Note: This does not return the height of the stacked segment
|
---|
974 | * (in graph coordinates) properly.
|
---|
975 | *
|
---|
976 | * Results:
|
---|
977 | * Returns 1 if the point is width any bar segment, otherwise 0.
|
---|
978 | *
|
---|
979 | * ----------------------------------------------------------------------
|
---|
980 | */
|
---|
981 | /*ARGSUSED*/
|
---|
982 | static void
|
---|
983 | ClosestBar(graphPtr, elemPtr, searchPtr)
|
---|
984 | Graph *graphPtr; /* Graph widget record */
|
---|
985 | Element *elemPtr; /* Bar element */
|
---|
986 | ClosestSearch *searchPtr; /* Info of closest point in element */
|
---|
987 | {
|
---|
988 | Bar *barPtr = (Bar *)elemPtr;
|
---|
989 | Point2D *pointPtr, *endPtr;
|
---|
990 | Point2D t, outline[5];
|
---|
991 | XRectangle *rectPtr;
|
---|
992 | double left, right, top, bottom;
|
---|
993 | double minDist, dist;
|
---|
994 | int imin;
|
---|
995 | register int i;
|
---|
996 |
|
---|
997 | minDist = searchPtr->dist;
|
---|
998 | imin = 0;
|
---|
999 |
|
---|
1000 | rectPtr = barPtr->rectangles;
|
---|
1001 | for (i = 0; i < barPtr->nRects; i++) {
|
---|
1002 | if (PointInRectangle(rectPtr, searchPtr->x, searchPtr->y)) {
|
---|
1003 | imin = barPtr->rectToData[i];
|
---|
1004 | minDist = 0.0;
|
---|
1005 | break;
|
---|
1006 | }
|
---|
1007 | left = rectPtr->x, top = rectPtr->y;
|
---|
1008 | right = (double)(rectPtr->x + rectPtr->width);
|
---|
1009 | bottom = (double)(rectPtr->y + rectPtr->height);
|
---|
1010 | outline[4].x = outline[3].x = outline[0].x = left;
|
---|
1011 | outline[4].y = outline[1].y = outline[0].y = top;
|
---|
1012 | outline[2].x = outline[1].x = right;
|
---|
1013 | outline[3].y = outline[2].y = bottom;
|
---|
1014 |
|
---|
1015 | for (pointPtr = outline, endPtr = outline + 4; pointPtr < endPtr;
|
---|
1016 | pointPtr++) {
|
---|
1017 | t = Blt_GetProjection(searchPtr->x, searchPtr->y,
|
---|
1018 | pointPtr, pointPtr + 1);
|
---|
1019 | if (t.x > right) {
|
---|
1020 | t.x = right;
|
---|
1021 | } else if (t.x < left) {
|
---|
1022 | t.x = left;
|
---|
1023 | }
|
---|
1024 | if (t.y > bottom) {
|
---|
1025 | t.y = bottom;
|
---|
1026 | } else if (t.y < top) {
|
---|
1027 | t.y = top;
|
---|
1028 | }
|
---|
1029 | dist = hypot((t.x - searchPtr->x), (t.y - searchPtr->y));
|
---|
1030 | if (dist < minDist) {
|
---|
1031 | minDist = dist;
|
---|
1032 | imin = barPtr->rectToData[i];
|
---|
1033 | }
|
---|
1034 | }
|
---|
1035 | rectPtr++;
|
---|
1036 | }
|
---|
1037 | if (minDist < searchPtr->dist) {
|
---|
1038 | searchPtr->elemPtr = (Element *)elemPtr;
|
---|
1039 | searchPtr->dist = minDist;
|
---|
1040 | searchPtr->index = imin;
|
---|
1041 | searchPtr->point.x = (double)barPtr->x.valueArr[imin];
|
---|
1042 | searchPtr->point.y = (double)barPtr->y.valueArr[imin];
|
---|
1043 | }
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | /*
|
---|
1047 | *----------------------------------------------------------------------
|
---|
1048 | *
|
---|
1049 | * MergePens --
|
---|
1050 | *
|
---|
1051 | * Reorders the both arrays of points and errorbars to merge pens.
|
---|
1052 | *
|
---|
1053 | * Results:
|
---|
1054 | * None.
|
---|
1055 | *
|
---|
1056 | * Side effects:
|
---|
1057 | * The old arrays are freed and new ones allocated containing
|
---|
1058 | * the reordered points and errorbars.
|
---|
1059 | *
|
---|
1060 | *----------------------------------------------------------------------
|
---|
1061 | */
|
---|
1062 | static void
|
---|
1063 | MergePens(barPtr, dataToStyle)
|
---|
1064 | Bar *barPtr;
|
---|
1065 | PenStyle **dataToStyle;
|
---|
1066 | {
|
---|
1067 | BarPenStyle *stylePtr;
|
---|
1068 | Blt_ChainLink *linkPtr;
|
---|
1069 |
|
---|
1070 | if (Blt_ChainGetLength(barPtr->palette) < 2) {
|
---|
1071 | linkPtr = Blt_ChainFirstLink(barPtr->palette);
|
---|
1072 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1073 | stylePtr->nRects = barPtr->nRects;
|
---|
1074 | stylePtr->rectangles = barPtr->rectangles;
|
---|
1075 | stylePtr->symbolSize = barPtr->rectangles->width / 2;
|
---|
1076 | stylePtr->xErrorBarCnt = barPtr->xErrorBarCnt;
|
---|
1077 | stylePtr->xErrorBars = barPtr->xErrorBars;
|
---|
1078 | stylePtr->yErrorBarCnt = barPtr->yErrorBarCnt;
|
---|
1079 | stylePtr->yErrorBars = barPtr->yErrorBars;
|
---|
1080 | return;
|
---|
1081 | }
|
---|
1082 | /* We have more than one style. Group bar segments of like pen
|
---|
1083 | * styles together. */
|
---|
1084 |
|
---|
1085 | if (barPtr->nRects > 0) {
|
---|
1086 | XRectangle *rectangles;
|
---|
1087 | int *rectToData;
|
---|
1088 | int dataIndex;
|
---|
1089 | register XRectangle *rectPtr;
|
---|
1090 | register int *indexPtr;
|
---|
1091 | register int i;
|
---|
1092 |
|
---|
1093 | rectangles = Blt_Malloc(barPtr->nRects * sizeof(XRectangle));
|
---|
1094 | rectToData = Blt_Malloc(barPtr->nRects * sizeof(int));
|
---|
1095 | assert(rectangles && rectToData);
|
---|
1096 |
|
---|
1097 | rectPtr = rectangles, indexPtr = rectToData;
|
---|
1098 | for (linkPtr = Blt_ChainFirstLink(barPtr->palette); linkPtr != NULL;
|
---|
1099 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
1100 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1101 | stylePtr->symbolSize = rectPtr->width / 2;
|
---|
1102 | stylePtr->rectangles = rectPtr;
|
---|
1103 | for (i = 0; i < barPtr->nRects; i++) {
|
---|
1104 | dataIndex = barPtr->rectToData[i];
|
---|
1105 | if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
|
---|
1106 | *rectPtr++ = barPtr->rectangles[i];
|
---|
1107 | *indexPtr++ = dataIndex;
|
---|
1108 | }
|
---|
1109 | }
|
---|
1110 | stylePtr->nRects = rectPtr - stylePtr->rectangles;
|
---|
1111 | }
|
---|
1112 | Blt_Free(barPtr->rectangles);
|
---|
1113 | barPtr->rectangles = rectangles;
|
---|
1114 | Blt_Free(barPtr->rectToData);
|
---|
1115 | barPtr->rectToData = rectToData;
|
---|
1116 | }
|
---|
1117 | if (barPtr->xErrorBarCnt > 0) {
|
---|
1118 | Segment2D *errorBars, *segPtr;
|
---|
1119 | int *errorToData, *indexPtr;
|
---|
1120 | int dataIndex;
|
---|
1121 | register int i;
|
---|
1122 |
|
---|
1123 | errorBars = Blt_Malloc(barPtr->xErrorBarCnt * sizeof(Segment2D));
|
---|
1124 | errorToData = Blt_Malloc(barPtr->xErrorBarCnt * sizeof(int));
|
---|
1125 | assert(errorBars);
|
---|
1126 | segPtr = errorBars, indexPtr = errorToData;
|
---|
1127 | for (linkPtr = Blt_ChainFirstLink(barPtr->palette);
|
---|
1128 | linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
1129 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1130 | stylePtr->xErrorBars = segPtr;
|
---|
1131 | for (i = 0; i < barPtr->xErrorBarCnt; i++) {
|
---|
1132 | dataIndex = barPtr->xErrorToData[i];
|
---|
1133 | if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
|
---|
1134 | *segPtr++ = barPtr->xErrorBars[i];
|
---|
1135 | *indexPtr++ = dataIndex;
|
---|
1136 | }
|
---|
1137 | }
|
---|
1138 | stylePtr->xErrorBarCnt = segPtr - stylePtr->xErrorBars;
|
---|
1139 | }
|
---|
1140 | Blt_Free(barPtr->xErrorBars);
|
---|
1141 | barPtr->xErrorBars = errorBars;
|
---|
1142 | Blt_Free(barPtr->xErrorToData);
|
---|
1143 | barPtr->xErrorToData = errorToData;
|
---|
1144 | }
|
---|
1145 | if (barPtr->yErrorBarCnt > 0) {
|
---|
1146 | Segment2D *errorBars, *segPtr;
|
---|
1147 | int *errorToData, *indexPtr;
|
---|
1148 | int dataIndex;
|
---|
1149 | register int i;
|
---|
1150 |
|
---|
1151 | errorBars = Blt_Malloc(barPtr->yErrorBarCnt * sizeof(Segment2D));
|
---|
1152 | errorToData = Blt_Malloc(barPtr->yErrorBarCnt * sizeof(int));
|
---|
1153 | assert(errorBars);
|
---|
1154 | segPtr = errorBars, indexPtr = errorToData;
|
---|
1155 | for (linkPtr = Blt_ChainFirstLink(barPtr->palette);
|
---|
1156 | linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
1157 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1158 | stylePtr->yErrorBars = segPtr;
|
---|
1159 | for (i = 0; i < barPtr->yErrorBarCnt; i++) {
|
---|
1160 | dataIndex = barPtr->yErrorToData[i];
|
---|
1161 | if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
|
---|
1162 | *segPtr++ = barPtr->yErrorBars[i];
|
---|
1163 | *indexPtr++ = dataIndex;
|
---|
1164 | }
|
---|
1165 | }
|
---|
1166 | stylePtr->yErrorBarCnt = segPtr - stylePtr->yErrorBars;
|
---|
1167 | }
|
---|
1168 | Blt_Free(barPtr->yErrorBars);
|
---|
1169 | barPtr->yErrorBars = errorBars;
|
---|
1170 | Blt_Free(barPtr->yErrorToData);
|
---|
1171 | barPtr->yErrorToData = errorToData;
|
---|
1172 | }
|
---|
1173 | }
|
---|
1174 |
|
---|
1175 | /*
|
---|
1176 | *----------------------------------------------------------------------
|
---|
1177 | *
|
---|
1178 | * MapActiveBars --
|
---|
1179 | *
|
---|
1180 | * Creates an array of points of the active graph coordinates.
|
---|
1181 | *
|
---|
1182 | * Results:
|
---|
1183 | * None.
|
---|
1184 | *
|
---|
1185 | * Side effects:
|
---|
1186 | * Memory is freed and allocated for the active point array.
|
---|
1187 | *
|
---|
1188 | *----------------------------------------------------------------------
|
---|
1189 | */
|
---|
1190 | static void
|
---|
1191 | MapActiveBars(barPtr)
|
---|
1192 | Bar *barPtr;
|
---|
1193 | {
|
---|
1194 | if (barPtr->activeRects != NULL) {
|
---|
1195 | Blt_Free(barPtr->activeRects);
|
---|
1196 | barPtr->activeRects = NULL;
|
---|
1197 | }
|
---|
1198 | if (barPtr->activeToData != NULL) {
|
---|
1199 | Blt_Free(barPtr->activeToData);
|
---|
1200 | barPtr->activeToData = NULL;
|
---|
1201 | }
|
---|
1202 | barPtr->nActive = 0;
|
---|
1203 |
|
---|
1204 | if (barPtr->nActiveIndices > 0) {
|
---|
1205 | XRectangle *activeRects;
|
---|
1206 | int *activeToData;
|
---|
1207 | register int i, n;
|
---|
1208 | register int count;
|
---|
1209 |
|
---|
1210 | activeRects = Blt_Malloc(sizeof(XRectangle) * barPtr->nActiveIndices);
|
---|
1211 | assert(activeRects);
|
---|
1212 | activeToData = Blt_Malloc(sizeof(int) * barPtr->nActiveIndices);
|
---|
1213 | assert(activeToData);
|
---|
1214 | count = 0;
|
---|
1215 | for (i = 0; i < barPtr->nRects; i++) {
|
---|
1216 | for (n = 0; n < barPtr->nActiveIndices; n++) {
|
---|
1217 | if (barPtr->rectToData[i] == barPtr->activeIndices[n]) {
|
---|
1218 | activeRects[count] = barPtr->rectangles[i];
|
---|
1219 | activeToData[count] = i;
|
---|
1220 | count++;
|
---|
1221 | }
|
---|
1222 | }
|
---|
1223 | }
|
---|
1224 | barPtr->nActive = count;
|
---|
1225 | barPtr->activeRects = activeRects;
|
---|
1226 | barPtr->activeToData = activeToData;
|
---|
1227 | }
|
---|
1228 | barPtr->flags &= ~ACTIVE_PENDING;
|
---|
1229 | }
|
---|
1230 |
|
---|
1231 | static void
|
---|
1232 | ResetBar(barPtr)
|
---|
1233 | Bar *barPtr;
|
---|
1234 | {
|
---|
1235 | /* Release any storage associated with the display of the bar */
|
---|
1236 | ClearPalette(barPtr->palette);
|
---|
1237 | if (barPtr->activeRects != NULL) {
|
---|
1238 | Blt_Free(barPtr->activeRects);
|
---|
1239 | }
|
---|
1240 | if (barPtr->activeToData != NULL) {
|
---|
1241 | Blt_Free(barPtr->activeToData);
|
---|
1242 | }
|
---|
1243 | if (barPtr->xErrorBars != NULL) {
|
---|
1244 | Blt_Free(barPtr->xErrorBars);
|
---|
1245 | }
|
---|
1246 | if (barPtr->xErrorToData != NULL) {
|
---|
1247 | Blt_Free(barPtr->xErrorToData);
|
---|
1248 | }
|
---|
1249 | if (barPtr->yErrorBars != NULL) {
|
---|
1250 | Blt_Free(barPtr->yErrorBars);
|
---|
1251 | }
|
---|
1252 | if (barPtr->yErrorToData != NULL) {
|
---|
1253 | Blt_Free(barPtr->yErrorToData);
|
---|
1254 | }
|
---|
1255 | if (barPtr->rectangles != NULL) {
|
---|
1256 | Blt_Free(barPtr->rectangles);
|
---|
1257 | }
|
---|
1258 | if (barPtr->rectToData != NULL) {
|
---|
1259 | Blt_Free(barPtr->rectToData);
|
---|
1260 | }
|
---|
1261 | barPtr->activeToData = barPtr->xErrorToData = barPtr->yErrorToData =
|
---|
1262 | barPtr->rectToData = NULL;
|
---|
1263 | barPtr->activeRects = barPtr->rectangles = NULL;
|
---|
1264 | barPtr->xErrorBars = barPtr->yErrorBars = NULL;
|
---|
1265 | barPtr->nActive = barPtr->xErrorBarCnt = barPtr->yErrorBarCnt =
|
---|
1266 | barPtr->nRects = 0;
|
---|
1267 | }
|
---|
1268 |
|
---|
1269 | /*
|
---|
1270 | * ----------------------------------------------------------------------
|
---|
1271 | *
|
---|
1272 | * MapBar --
|
---|
1273 | *
|
---|
1274 | * Calculates the actual window coordinates of the bar element.
|
---|
1275 | * The window coordinates are saved in the bar element structure.
|
---|
1276 | *
|
---|
1277 | * Results:
|
---|
1278 | * None.
|
---|
1279 | *
|
---|
1280 | * Notes:
|
---|
1281 | * A bar can have multiple segments (more than one x,y pairs).
|
---|
1282 | * In this case, the bar can be represented as either a set of
|
---|
1283 | * non-contiguous bars or a single multi-segmented (stacked) bar.
|
---|
1284 | *
|
---|
1285 | * The x-axis layout for a barchart may be presented in one of
|
---|
1286 | * two ways. If abscissas are used, the bars are placed at those
|
---|
1287 | * coordinates. Otherwise, the range will represent the number
|
---|
1288 | * of values.
|
---|
1289 | *
|
---|
1290 | * ----------------------------------------------------------------------
|
---|
1291 | */
|
---|
1292 | static void
|
---|
1293 | MapBar(graphPtr, elemPtr)
|
---|
1294 | Graph *graphPtr;
|
---|
1295 | Element *elemPtr;
|
---|
1296 | {
|
---|
1297 | Bar *barPtr = (Bar *)elemPtr;
|
---|
1298 | FreqKey key;
|
---|
1299 | PenStyle **dataToStyle;
|
---|
1300 | Point2D c1, c2; /* Two opposite corners of the rectangle
|
---|
1301 | * in graph coordinates. */
|
---|
1302 | double *x, *y;
|
---|
1303 | double barWidth, barOffset;
|
---|
1304 | double baseline;
|
---|
1305 | double dx, dy;
|
---|
1306 | int *rectToData; /* Maps rectangles to data point indices */
|
---|
1307 | int height;
|
---|
1308 | int invertBar;
|
---|
1309 | int nPoints, count;
|
---|
1310 | register XRectangle *rectPtr, *rectangles;
|
---|
1311 | register int i;
|
---|
1312 | int size;
|
---|
1313 | Blt_ChainLink *linkPtr;
|
---|
1314 | BarPenStyle *stylePtr;
|
---|
1315 |
|
---|
1316 | ResetBar(barPtr);
|
---|
1317 | nPoints = NumberOfPoints(barPtr);
|
---|
1318 | if (nPoints < 1) {
|
---|
1319 | return; /* No data points */
|
---|
1320 | }
|
---|
1321 | barWidth = graphPtr->barWidth;
|
---|
1322 | if (barPtr->barWidth > 0.0) {
|
---|
1323 | barWidth = barPtr->barWidth;
|
---|
1324 | }
|
---|
1325 | baseline = (barPtr->axes.y->logScale) ? 1.0 : graphPtr->baseline;
|
---|
1326 | barOffset = barWidth * 0.5;
|
---|
1327 |
|
---|
1328 | /*
|
---|
1329 | * Create an array of rectangles representing the screen coordinates
|
---|
1330 | * of all the segments in the bar.
|
---|
1331 | */
|
---|
1332 | rectPtr = rectangles = Blt_Malloc(nPoints * sizeof(XRectangle));
|
---|
1333 | assert(rectangles);
|
---|
1334 | rectToData = Blt_Calloc(nPoints, sizeof(int));
|
---|
1335 | assert(rectToData);
|
---|
1336 |
|
---|
1337 | x = barPtr->x.valueArr, y = barPtr->y.valueArr;
|
---|
1338 | count = 0;
|
---|
1339 | for (i = 0; i < nPoints; i++) {
|
---|
1340 | if (((x[i] - barWidth) > barPtr->axes.x->axisRange.max) ||
|
---|
1341 | ((x[i] + barWidth) < barPtr->axes.x->axisRange.min)) {
|
---|
1342 | continue; /* Abscissa is out of range of the x-axis */
|
---|
1343 | }
|
---|
1344 | c1.x = x[i] - barOffset;
|
---|
1345 | c1.y = y[i];
|
---|
1346 | c2.x = c1.x + barWidth;
|
---|
1347 | c2.y = baseline;
|
---|
1348 |
|
---|
1349 | /*
|
---|
1350 | * If the mode is "aligned" or "stacked" we need to adjust the
|
---|
1351 | * x or y coordinates of the two corners.
|
---|
1352 | */
|
---|
1353 |
|
---|
1354 | if ((graphPtr->nStacks > 0) && (graphPtr->mode != MODE_INFRONT)) {
|
---|
1355 | Blt_HashEntry *hPtr;
|
---|
1356 |
|
---|
1357 | key.value = x[i];
|
---|
1358 | key.axes = barPtr->axes;
|
---|
1359 | hPtr = Blt_FindHashEntry(&(graphPtr->freqTable), (char *)&key);
|
---|
1360 | if (hPtr != NULL) {
|
---|
1361 | FreqInfo *infoPtr;
|
---|
1362 | double slice, width;
|
---|
1363 |
|
---|
1364 | infoPtr = (FreqInfo *)Blt_GetHashValue(hPtr);
|
---|
1365 | switch (graphPtr->mode) {
|
---|
1366 | case MODE_STACKED:
|
---|
1367 | c2.y = infoPtr->lastY;
|
---|
1368 | c1.y += c2.y;
|
---|
1369 | infoPtr->lastY = c1.y;
|
---|
1370 | break;
|
---|
1371 |
|
---|
1372 | case MODE_ALIGNED:
|
---|
1373 | infoPtr->count++;
|
---|
1374 | slice = barWidth / (double)infoPtr->freq;
|
---|
1375 | c1.x += slice * (infoPtr->freq - infoPtr->count);
|
---|
1376 | c2.x = c1.x + slice;
|
---|
1377 | break;
|
---|
1378 |
|
---|
1379 | case MODE_OVERLAP:
|
---|
1380 | infoPtr->count++;
|
---|
1381 | slice = barWidth / (double)(infoPtr->freq * 2);
|
---|
1382 | width = slice * (infoPtr->freq + 1);
|
---|
1383 | c1.x += slice * (infoPtr->freq - infoPtr->count);
|
---|
1384 | c2.x = c1.x + width;
|
---|
1385 | break;
|
---|
1386 | case MODE_INFRONT:
|
---|
1387 | break;
|
---|
1388 | }
|
---|
1389 | }
|
---|
1390 | }
|
---|
1391 | invertBar = FALSE;
|
---|
1392 | if (c1.y < c2.y) {
|
---|
1393 | double temp;
|
---|
1394 |
|
---|
1395 | /* Handle negative bar values by swapping ordinates */
|
---|
1396 | temp = c1.y, c1.y = c2.y, c2.y = temp;
|
---|
1397 | invertBar = TRUE;
|
---|
1398 | }
|
---|
1399 | /*
|
---|
1400 | * Get the two corners of the bar segment and compute the rectangle
|
---|
1401 | */
|
---|
1402 | c1 = Blt_Map2D(graphPtr, c1.x, c1.y, &barPtr->axes);
|
---|
1403 | c2 = Blt_Map2D(graphPtr, c2.x, c2.y, &barPtr->axes);
|
---|
1404 |
|
---|
1405 | /* Bound the bars vertically by the size of the graph window */
|
---|
1406 | if (c1.y < 0.0) {
|
---|
1407 | c1.y = 0.0;
|
---|
1408 | } else if (c1.y > (double)graphPtr->height) {
|
---|
1409 | c1.y = (double)graphPtr->height;
|
---|
1410 | }
|
---|
1411 | if (c2.y < 0.0) {
|
---|
1412 | c2.y = 0.0;
|
---|
1413 | } else if (c2.y > (double)graphPtr->height) {
|
---|
1414 | c2.y = (double)graphPtr->height;
|
---|
1415 | }
|
---|
1416 | dx = c1.x - c2.x;
|
---|
1417 | dy = c1.y - c2.y;
|
---|
1418 | height = (int)Round(FABS(dy));
|
---|
1419 | if (invertBar) {
|
---|
1420 | rectPtr->y = (short int)MIN(c1.y, c2.y);
|
---|
1421 | } else {
|
---|
1422 | rectPtr->y = (short int)(MAX(c1.y, c2.y)) - height;
|
---|
1423 | }
|
---|
1424 | rectPtr->x = (short int)MIN(c1.x, c2.x);
|
---|
1425 | rectPtr->width = (short int)Round(FABS(dx)) + 1;
|
---|
1426 | if (rectPtr->width < 1) {
|
---|
1427 | rectPtr->width = 1;
|
---|
1428 | }
|
---|
1429 | rectPtr->height = height + 1;
|
---|
1430 | if (rectPtr->height < 1) {
|
---|
1431 | rectPtr->height = 1;
|
---|
1432 | }
|
---|
1433 | rectToData[count] = i; /* Save the data index corresponding to the
|
---|
1434 | * rectangle */
|
---|
1435 | rectPtr++;
|
---|
1436 | count++;
|
---|
1437 | }
|
---|
1438 | barPtr->nRects = count;
|
---|
1439 | barPtr->rectangles = rectangles;
|
---|
1440 | barPtr->rectToData = rectToData;
|
---|
1441 | if (barPtr->nActiveIndices > 0) {
|
---|
1442 | MapActiveBars(barPtr);
|
---|
1443 | }
|
---|
1444 |
|
---|
1445 | size = 20;
|
---|
1446 | if (count > 0) {
|
---|
1447 | size = rectangles->width;
|
---|
1448 | }
|
---|
1449 | /* Set the symbol size of all the pen styles. */
|
---|
1450 | for (linkPtr = Blt_ChainFirstLink(barPtr->palette); linkPtr != NULL;
|
---|
1451 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
1452 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1453 | stylePtr->symbolSize = size;
|
---|
1454 | stylePtr->errorBarCapWidth = (stylePtr->penPtr->errorBarCapWidth > 0)
|
---|
1455 | ? stylePtr->penPtr->errorBarCapWidth : (int)(size * 0.6666666);
|
---|
1456 | stylePtr->errorBarCapWidth /= 2;
|
---|
1457 | }
|
---|
1458 | dataToStyle = Blt_StyleMap((Element *)barPtr);
|
---|
1459 | if (((barPtr->yHigh.nValues > 0) && (barPtr->yLow.nValues > 0)) ||
|
---|
1460 | ((barPtr->xHigh.nValues > 0) && (barPtr->xLow.nValues > 0)) ||
|
---|
1461 | (barPtr->xError.nValues > 0) || (barPtr->yError.nValues > 0)) {
|
---|
1462 | Blt_MapErrorBars(graphPtr, (Element *)barPtr, dataToStyle);
|
---|
1463 | }
|
---|
1464 | MergePens(barPtr, dataToStyle);
|
---|
1465 | Blt_Free(dataToStyle);
|
---|
1466 | }
|
---|
1467 |
|
---|
1468 | /*
|
---|
1469 | * -----------------------------------------------------------------
|
---|
1470 | *
|
---|
1471 | * DrawSymbol --
|
---|
1472 | *
|
---|
1473 | * Draw a symbol centered at the given x,y window coordinate
|
---|
1474 | * based upon the element symbol type and size.
|
---|
1475 | *
|
---|
1476 | * Results:
|
---|
1477 | * None.
|
---|
1478 | *
|
---|
1479 | * Problems:
|
---|
1480 | * Most notable is the round-off errors generated when
|
---|
1481 | * calculating the centered position of the symbol.
|
---|
1482 | * -----------------------------------------------------------------
|
---|
1483 | */
|
---|
1484 | /*ARGSUSED*/
|
---|
1485 | static void
|
---|
1486 | DrawSymbol(graphPtr, drawable, elemPtr, x, y, size)
|
---|
1487 | Graph *graphPtr;
|
---|
1488 | Drawable drawable; /* Pixmap or window to draw into */
|
---|
1489 | Element *elemPtr;
|
---|
1490 | int x, y;
|
---|
1491 | int size;
|
---|
1492 | {
|
---|
1493 | BarPen *penPtr = ((Bar *)elemPtr)->normalPenPtr;
|
---|
1494 | int radius;
|
---|
1495 |
|
---|
1496 | if ((penPtr->border == NULL) && (penPtr->fgColor == NULL)) {
|
---|
1497 | return;
|
---|
1498 | }
|
---|
1499 | radius = (size / 2);
|
---|
1500 | size--;
|
---|
1501 |
|
---|
1502 | x -= radius;
|
---|
1503 | y -= radius;
|
---|
1504 | XSetTSOrigin(graphPtr->display, penPtr->gc, x, y);
|
---|
1505 | XFillRectangle(graphPtr->display, drawable, penPtr->gc, x, y,
|
---|
1506 | size, size);
|
---|
1507 | XSetTSOrigin(graphPtr->display, penPtr->gc, 0, 0);
|
---|
1508 | }
|
---|
1509 |
|
---|
1510 | /*
|
---|
1511 | * -----------------------------------------------------------------
|
---|
1512 | *
|
---|
1513 | * DrawBarSegments --
|
---|
1514 | *
|
---|
1515 | * Draws each of the rectangular segments for the element.
|
---|
1516 | *
|
---|
1517 | * Results:
|
---|
1518 | * None.
|
---|
1519 | *
|
---|
1520 | * -----------------------------------------------------------------
|
---|
1521 | */
|
---|
1522 | static void
|
---|
1523 | DrawBarSegments(
|
---|
1524 | Graph *graphPtr,
|
---|
1525 | Drawable drawable, /* Pixmap or window to draw into */
|
---|
1526 | BarPen *penPtr,
|
---|
1527 | XRectangle *rectangles,
|
---|
1528 | int nRects)
|
---|
1529 | {
|
---|
1530 | register XRectangle *rectPtr;
|
---|
1531 |
|
---|
1532 | if ((penPtr->border == NULL) && (penPtr->fgColor == NULL)) {
|
---|
1533 | return;
|
---|
1534 | }
|
---|
1535 | XFillRectangles(graphPtr->display, drawable, penPtr->gc, rectangles,
|
---|
1536 | nRects);
|
---|
1537 | if ((penPtr->border != NULL) && (penPtr->borderWidth > 0) &&
|
---|
1538 | (penPtr->relief != TK_RELIEF_FLAT)) {
|
---|
1539 | XRectangle *endPtr;
|
---|
1540 |
|
---|
1541 | for (rectPtr = rectangles, endPtr = rectangles + nRects;
|
---|
1542 | rectPtr < endPtr; rectPtr++) {
|
---|
1543 | Blt_Draw3DRectangle(graphPtr->tkwin, drawable, penPtr->border,
|
---|
1544 | rectPtr->x, rectPtr->y, rectPtr->width, rectPtr->height,
|
---|
1545 | penPtr->borderWidth, penPtr->relief);
|
---|
1546 | }
|
---|
1547 | }
|
---|
1548 | }
|
---|
1549 |
|
---|
1550 | /*
|
---|
1551 | * -----------------------------------------------------------------
|
---|
1552 | *
|
---|
1553 | * DrawBarValues --
|
---|
1554 | *
|
---|
1555 | * Draws the numeric value of the bar.
|
---|
1556 | *
|
---|
1557 | * Results:
|
---|
1558 | * None.
|
---|
1559 | *
|
---|
1560 | * -----------------------------------------------------------------
|
---|
1561 | */
|
---|
1562 | static void
|
---|
1563 | DrawBarValues(
|
---|
1564 | Graph *graphPtr,
|
---|
1565 | Drawable drawable,
|
---|
1566 | Bar *barPtr,
|
---|
1567 | BarPen *penPtr,
|
---|
1568 | XRectangle *rectangles,
|
---|
1569 | int nRects,
|
---|
1570 | int *rectToData)
|
---|
1571 | {
|
---|
1572 | XRectangle *rectPtr, *endPtr;
|
---|
1573 | int count;
|
---|
1574 | char *fmt;
|
---|
1575 | char string[TCL_DOUBLE_SPACE * 2 + 2];
|
---|
1576 | double x, y;
|
---|
1577 | Point2D anchorPos;
|
---|
1578 |
|
---|
1579 | count = 0;
|
---|
1580 | fmt = penPtr->valueFormat;
|
---|
1581 | if (fmt == NULL) {
|
---|
1582 | fmt = "%g";
|
---|
1583 | }
|
---|
1584 | for (rectPtr = rectangles, endPtr = rectangles + nRects; rectPtr < endPtr;
|
---|
1585 | rectPtr++) {
|
---|
1586 | x = barPtr->x.valueArr[rectToData[count]];
|
---|
1587 | y = barPtr->y.valueArr[rectToData[count]];
|
---|
1588 | count++;
|
---|
1589 | if (penPtr->valueShow == SHOW_X) {
|
---|
1590 | sprintf(string, fmt, x);
|
---|
1591 | } else if (penPtr->valueShow == SHOW_Y) {
|
---|
1592 | sprintf(string, fmt, y);
|
---|
1593 | } else if (penPtr->valueShow == SHOW_BOTH) {
|
---|
1594 | sprintf(string, fmt, x);
|
---|
1595 | strcat(string, ",");
|
---|
1596 | sprintf(string + strlen(string), fmt, y);
|
---|
1597 | }
|
---|
1598 | if (graphPtr->inverted) {
|
---|
1599 | anchorPos.y = rectPtr->y + rectPtr->height * 0.5;
|
---|
1600 | anchorPos.x = rectPtr->x + rectPtr->width;
|
---|
1601 | if (y < graphPtr->baseline) {
|
---|
1602 | anchorPos.x -= rectPtr->width;
|
---|
1603 | }
|
---|
1604 | } else {
|
---|
1605 | anchorPos.x = rectPtr->x + rectPtr->width * 0.5;
|
---|
1606 | anchorPos.y = rectPtr->y;
|
---|
1607 | if (y < graphPtr->baseline) {
|
---|
1608 | anchorPos.y += rectPtr->height;
|
---|
1609 | }
|
---|
1610 | }
|
---|
1611 | Blt_DrawText(graphPtr->tkwin, drawable, string, &(penPtr->valueStyle),
|
---|
1612 | (int)anchorPos.x, (int)anchorPos.y);
|
---|
1613 | }
|
---|
1614 | }
|
---|
1615 |
|
---|
1616 |
|
---|
1617 | /*
|
---|
1618 | * ----------------------------------------------------------------------
|
---|
1619 | *
|
---|
1620 | * DrawNormalBar --
|
---|
1621 | *
|
---|
1622 | * Draws the rectangle representing the bar element. If the
|
---|
1623 | * relief option is set to "raised" or "sunken" and the bar
|
---|
1624 | * borderwidth is set (borderwidth > 0), a 3D border is drawn
|
---|
1625 | * around the bar.
|
---|
1626 | *
|
---|
1627 | * Don't draw bars that aren't visible (i.e. within the limits
|
---|
1628 | * of the axis).
|
---|
1629 | *
|
---|
1630 | * Results:
|
---|
1631 | * None.
|
---|
1632 | *
|
---|
1633 | * Side effects:
|
---|
1634 | * X drawing commands are output.
|
---|
1635 | *
|
---|
1636 | * ----------------------------------------------------------------------
|
---|
1637 | */
|
---|
1638 | static void
|
---|
1639 | DrawNormalBar(graphPtr, drawable, elemPtr)
|
---|
1640 | Graph *graphPtr;
|
---|
1641 | Drawable drawable;
|
---|
1642 | Element *elemPtr;
|
---|
1643 | {
|
---|
1644 | Bar *barPtr = (Bar *)elemPtr;
|
---|
1645 | int count;
|
---|
1646 | Blt_ChainLink *linkPtr;
|
---|
1647 | register BarPenStyle *stylePtr;
|
---|
1648 | BarPen *penPtr;
|
---|
1649 |
|
---|
1650 | count = 0;
|
---|
1651 | for (linkPtr = Blt_ChainFirstLink(barPtr->palette); linkPtr != NULL;
|
---|
1652 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
1653 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1654 | penPtr = stylePtr->penPtr;
|
---|
1655 | if (stylePtr->nRects > 0) {
|
---|
1656 | DrawBarSegments(graphPtr, drawable, penPtr, stylePtr->rectangles,
|
---|
1657 | stylePtr->nRects);
|
---|
1658 | }
|
---|
1659 | if ((stylePtr->xErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_X)) {
|
---|
1660 | Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
|
---|
1661 | stylePtr->xErrorBars, stylePtr->xErrorBarCnt);
|
---|
1662 | }
|
---|
1663 | if ((stylePtr->yErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_Y)) {
|
---|
1664 | Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
|
---|
1665 | stylePtr->yErrorBars, stylePtr->yErrorBarCnt);
|
---|
1666 | }
|
---|
1667 | if (penPtr->valueShow != SHOW_NONE) {
|
---|
1668 | DrawBarValues(graphPtr, drawable, barPtr, penPtr,
|
---|
1669 | stylePtr->rectangles, stylePtr->nRects,
|
---|
1670 | barPtr->rectToData + count);
|
---|
1671 | }
|
---|
1672 | count += stylePtr->nRects;
|
---|
1673 | }
|
---|
1674 | }
|
---|
1675 |
|
---|
1676 | /*
|
---|
1677 | * ----------------------------------------------------------------------
|
---|
1678 | *
|
---|
1679 | * DrawActiveBar --
|
---|
1680 | *
|
---|
1681 | * Draws rectangles representing the active segments of the
|
---|
1682 | * bar element. If the -relief option is set (other than "flat")
|
---|
1683 | * and the borderwidth is greater than 0, a 3D border is drawn
|
---|
1684 | * around the each bar segment.
|
---|
1685 | *
|
---|
1686 | * Results:
|
---|
1687 | * None.
|
---|
1688 | *
|
---|
1689 | * Side effects:
|
---|
1690 | * X drawing commands are output.
|
---|
1691 | *
|
---|
1692 | * ----------------------------------------------------------------------
|
---|
1693 | */
|
---|
1694 | static void
|
---|
1695 | DrawActiveBar(graphPtr, drawable, elemPtr)
|
---|
1696 | Graph *graphPtr;
|
---|
1697 | Drawable drawable;
|
---|
1698 | Element *elemPtr;
|
---|
1699 | {
|
---|
1700 | Bar *barPtr = (Bar *)elemPtr;
|
---|
1701 |
|
---|
1702 | if (barPtr->activePenPtr != NULL) {
|
---|
1703 | BarPen *penPtr = barPtr->activePenPtr;
|
---|
1704 |
|
---|
1705 | if (barPtr->nActiveIndices > 0) {
|
---|
1706 | if (barPtr->flags & ACTIVE_PENDING) {
|
---|
1707 | MapActiveBars(barPtr);
|
---|
1708 | }
|
---|
1709 | DrawBarSegments(graphPtr, drawable, penPtr, barPtr->activeRects,
|
---|
1710 | barPtr->nActive);
|
---|
1711 | if (penPtr->valueShow != SHOW_NONE) {
|
---|
1712 | DrawBarValues(graphPtr, drawable, barPtr, penPtr,
|
---|
1713 | barPtr->activeRects, barPtr->nActive,
|
---|
1714 | barPtr->activeToData);
|
---|
1715 | }
|
---|
1716 | } else if (barPtr->nActiveIndices < 0) {
|
---|
1717 | DrawBarSegments(graphPtr, drawable, penPtr, barPtr->rectangles,
|
---|
1718 | barPtr->nRects);
|
---|
1719 | if (penPtr->valueShow != SHOW_NONE) {
|
---|
1720 | DrawBarValues(graphPtr, drawable, barPtr, penPtr,
|
---|
1721 | barPtr->rectangles, barPtr->nRects, barPtr->rectToData);
|
---|
1722 | }
|
---|
1723 | }
|
---|
1724 | }
|
---|
1725 | }
|
---|
1726 |
|
---|
1727 | /*
|
---|
1728 | * -----------------------------------------------------------------
|
---|
1729 | *
|
---|
1730 | * SymbolToPostScript --
|
---|
1731 | *
|
---|
1732 | * Draw a symbol centered at the given x,y window coordinate
|
---|
1733 | * based upon the element symbol type and size.
|
---|
1734 | *
|
---|
1735 | * Results:
|
---|
1736 | * None.
|
---|
1737 | *
|
---|
1738 | * Problems:
|
---|
1739 | * Most notable is the round-off errors generated when
|
---|
1740 | * calculating the centered position of the symbol.
|
---|
1741 | *
|
---|
1742 | * -----------------------------------------------------------------
|
---|
1743 | */
|
---|
1744 | /*ARGSUSED*/
|
---|
1745 | static void
|
---|
1746 | SymbolToPostScript(graphPtr, psToken, elemPtr, x, y, size)
|
---|
1747 | Graph *graphPtr;
|
---|
1748 | PsToken psToken;
|
---|
1749 | Element *elemPtr;
|
---|
1750 | int size;
|
---|
1751 | double x, y;
|
---|
1752 | {
|
---|
1753 | Bar *barPtr = (Bar *)elemPtr;
|
---|
1754 | BarPen *bpPtr = barPtr->normalPenPtr;
|
---|
1755 |
|
---|
1756 | if ((bpPtr->border == NULL) && (bpPtr->fgColor == NULL)) {
|
---|
1757 | return;
|
---|
1758 | }
|
---|
1759 | /*
|
---|
1760 | * Build a PostScript procedure to draw the fill and outline of
|
---|
1761 | * the symbol after the path of the symbol shape has been formed
|
---|
1762 | */
|
---|
1763 | Blt_AppendToPostScript(psToken, "\n",
|
---|
1764 | "/DrawSymbolProc {\n",
|
---|
1765 | " gsave\n ", (char *)NULL);
|
---|
1766 | if (bpPtr->stipple != None) {
|
---|
1767 | if (bpPtr->border != NULL) {
|
---|
1768 | Blt_BackgroundToPostScript(psToken,Tk_3DBorderColor(bpPtr->border));
|
---|
1769 | Blt_AppendToPostScript(psToken, " Fill\n ", (char *)NULL);
|
---|
1770 | }
|
---|
1771 | if (bpPtr->fgColor != NULL) {
|
---|
1772 | Blt_ForegroundToPostScript(psToken, bpPtr->fgColor);
|
---|
1773 | } else {
|
---|
1774 | Blt_ForegroundToPostScript(psToken,Tk_3DBorderColor(bpPtr->border));
|
---|
1775 | }
|
---|
1776 | Blt_StippleToPostScript(psToken, graphPtr->display, bpPtr->stipple);
|
---|
1777 | } else if (bpPtr->fgColor != NULL) {
|
---|
1778 | Blt_ForegroundToPostScript(psToken, bpPtr->fgColor);
|
---|
1779 | Blt_AppendToPostScript(psToken, " fill\n", (char *)NULL);
|
---|
1780 | }
|
---|
1781 | Blt_AppendToPostScript(psToken, " grestore\n", (char *)NULL);
|
---|
1782 | Blt_AppendToPostScript(psToken, "} def\n\n", (char *)NULL);
|
---|
1783 | Blt_FormatToPostScript(psToken, "%g %g %d Sq\n", x, y, size);
|
---|
1784 | }
|
---|
1785 |
|
---|
1786 | static void
|
---|
1787 | SegmentsToPostScript(graphPtr, psToken, penPtr, rectPtr, nRects)
|
---|
1788 | Graph *graphPtr;
|
---|
1789 | PsToken psToken;
|
---|
1790 | BarPen *penPtr;
|
---|
1791 | register XRectangle *rectPtr;
|
---|
1792 | int nRects;
|
---|
1793 | {
|
---|
1794 | XRectangle *endPtr;
|
---|
1795 |
|
---|
1796 | if ((penPtr->border == NULL) && (penPtr->fgColor == NULL)) {
|
---|
1797 | return;
|
---|
1798 | }
|
---|
1799 | for (endPtr = rectPtr + nRects; rectPtr < endPtr; rectPtr++) {
|
---|
1800 | if ((rectPtr->width < 1) || (rectPtr->height < 1)) {
|
---|
1801 | continue;
|
---|
1802 | }
|
---|
1803 | if (penPtr->stipple != None) {
|
---|
1804 | Blt_RegionToPostScript(psToken,
|
---|
1805 | (double)rectPtr->x, (double)rectPtr->y,
|
---|
1806 | (int)rectPtr->width - 1, (int)rectPtr->height - 1);
|
---|
1807 | if (penPtr->border != NULL) {
|
---|
1808 | Blt_BackgroundToPostScript(psToken,
|
---|
1809 | Tk_3DBorderColor(penPtr->border));
|
---|
1810 | Blt_AppendToPostScript(psToken, "Fill\n", (char *)NULL);
|
---|
1811 | }
|
---|
1812 | if (penPtr->fgColor != NULL) {
|
---|
1813 | Blt_ForegroundToPostScript(psToken, penPtr->fgColor);
|
---|
1814 | } else {
|
---|
1815 | Blt_ForegroundToPostScript(psToken,
|
---|
1816 | Tk_3DBorderColor(penPtr->border));
|
---|
1817 | }
|
---|
1818 | Blt_StippleToPostScript(psToken, graphPtr->display,
|
---|
1819 | penPtr->stipple);
|
---|
1820 | } else if (penPtr->fgColor != NULL) {
|
---|
1821 | Blt_ForegroundToPostScript(psToken, penPtr->fgColor);
|
---|
1822 | Blt_RectangleToPostScript(psToken,
|
---|
1823 | (double)rectPtr->x, (double)rectPtr->y,
|
---|
1824 | (int)rectPtr->width - 1, (int)rectPtr->height - 1);
|
---|
1825 | }
|
---|
1826 | if ((penPtr->border != NULL) && (penPtr->borderWidth > 0) &&
|
---|
1827 | (penPtr->relief != TK_RELIEF_FLAT)) {
|
---|
1828 | Blt_Draw3DRectangleToPostScript(psToken, penPtr->border,
|
---|
1829 | (double)rectPtr->x, (double)rectPtr->y,
|
---|
1830 | (int)rectPtr->width, (int)rectPtr->height,
|
---|
1831 | penPtr->borderWidth, penPtr->relief);
|
---|
1832 | }
|
---|
1833 | }
|
---|
1834 | }
|
---|
1835 |
|
---|
1836 | static void
|
---|
1837 | BarValuesToPostScript(
|
---|
1838 | Graph *graphPtr,
|
---|
1839 | PsToken psToken,
|
---|
1840 | Bar *barPtr,
|
---|
1841 | BarPen *penPtr,
|
---|
1842 | XRectangle *rectangles,
|
---|
1843 | int nRects,
|
---|
1844 | int *rectToData)
|
---|
1845 | {
|
---|
1846 | XRectangle *rectPtr, *endPtr;
|
---|
1847 | int count;
|
---|
1848 | char *fmt;
|
---|
1849 | char string[TCL_DOUBLE_SPACE * 2 + 2];
|
---|
1850 | double x, y;
|
---|
1851 | Point2D anchorPos;
|
---|
1852 |
|
---|
1853 | count = 0;
|
---|
1854 | fmt = penPtr->valueFormat;
|
---|
1855 | if (fmt == NULL) {
|
---|
1856 | fmt = "%g";
|
---|
1857 | }
|
---|
1858 | for (rectPtr = rectangles, endPtr = rectangles + nRects; rectPtr < endPtr;
|
---|
1859 | rectPtr++) {
|
---|
1860 | x = barPtr->x.valueArr[rectToData[count]];
|
---|
1861 | y = barPtr->y.valueArr[rectToData[count]];
|
---|
1862 | count++;
|
---|
1863 | if (penPtr->valueShow == SHOW_X) {
|
---|
1864 | sprintf(string, fmt, x);
|
---|
1865 | } else if (penPtr->valueShow == SHOW_Y) {
|
---|
1866 | sprintf(string, fmt, y);
|
---|
1867 | } else if (penPtr->valueShow == SHOW_BOTH) {
|
---|
1868 | sprintf(string, fmt, x);
|
---|
1869 | strcat(string, ",");
|
---|
1870 | sprintf(string + strlen(string), fmt, y);
|
---|
1871 | }
|
---|
1872 | if (graphPtr->inverted) {
|
---|
1873 | anchorPos.y = rectPtr->y + rectPtr->height * 0.5;
|
---|
1874 | anchorPos.x = rectPtr->x + rectPtr->width;
|
---|
1875 | if (y < graphPtr->baseline) {
|
---|
1876 | anchorPos.x -= rectPtr->width;
|
---|
1877 | }
|
---|
1878 | } else {
|
---|
1879 | anchorPos.x = rectPtr->x + rectPtr->width * 0.5;
|
---|
1880 | anchorPos.y = rectPtr->y;
|
---|
1881 | if (y < graphPtr->baseline) {
|
---|
1882 | anchorPos.y += rectPtr->height;
|
---|
1883 | }
|
---|
1884 | }
|
---|
1885 | Blt_TextToPostScript(psToken, string, &(penPtr->valueStyle),
|
---|
1886 | anchorPos.x, anchorPos.y);
|
---|
1887 | }
|
---|
1888 | }
|
---|
1889 |
|
---|
1890 | /*
|
---|
1891 | * ----------------------------------------------------------------------
|
---|
1892 | *
|
---|
1893 | * ActiveBarToPostScript --
|
---|
1894 | *
|
---|
1895 | * Similar to the NormalBarToPostScript procedure, generates
|
---|
1896 | * PostScript commands to display the rectangles representing the
|
---|
1897 | * active bar segments of the element.
|
---|
1898 | *
|
---|
1899 | * Results:
|
---|
1900 | * None.
|
---|
1901 | *
|
---|
1902 | * Side effects:
|
---|
1903 | * PostScript pen width, dashes, and color settings are changed.
|
---|
1904 | *
|
---|
1905 | * ----------------------------------------------------------------------
|
---|
1906 | */
|
---|
1907 | /*ARGSUSED*/
|
---|
1908 | static void
|
---|
1909 | ActiveBarToPostScript(graphPtr, psToken, elemPtr)
|
---|
1910 | Graph *graphPtr;
|
---|
1911 | PsToken psToken;
|
---|
1912 | Element *elemPtr;
|
---|
1913 | {
|
---|
1914 | Bar *barPtr = (Bar *)elemPtr;
|
---|
1915 |
|
---|
1916 | if (barPtr->activePenPtr != NULL) {
|
---|
1917 | BarPen *penPtr = barPtr->activePenPtr;
|
---|
1918 |
|
---|
1919 | if (barPtr->nActiveIndices > 0) {
|
---|
1920 | if (barPtr->flags & ACTIVE_PENDING) {
|
---|
1921 | MapActiveBars(barPtr);
|
---|
1922 | }
|
---|
1923 | SegmentsToPostScript(graphPtr, psToken, penPtr,
|
---|
1924 | barPtr->activeRects, barPtr->nActive);
|
---|
1925 | if (penPtr->valueShow != SHOW_NONE) {
|
---|
1926 | BarValuesToPostScript(graphPtr, psToken, barPtr, penPtr,
|
---|
1927 | barPtr->activeRects, barPtr->nActive, barPtr->activeToData);
|
---|
1928 | }
|
---|
1929 | } else if (barPtr->nActiveIndices < 0) {
|
---|
1930 | SegmentsToPostScript(graphPtr, psToken, penPtr,
|
---|
1931 | barPtr->rectangles, barPtr->nRects);
|
---|
1932 | if (penPtr->valueShow != SHOW_NONE) {
|
---|
1933 | BarValuesToPostScript(graphPtr, psToken, barPtr, penPtr,
|
---|
1934 | barPtr->rectangles, barPtr->nRects, barPtr->rectToData);
|
---|
1935 | }
|
---|
1936 | }
|
---|
1937 | }
|
---|
1938 | }
|
---|
1939 |
|
---|
1940 | /*
|
---|
1941 | * ----------------------------------------------------------------------
|
---|
1942 | *
|
---|
1943 | * NormalBarToPostScript --
|
---|
1944 | *
|
---|
1945 | * Generates PostScript commands to form the rectangles
|
---|
1946 | * representing the segments of the bar element.
|
---|
1947 | *
|
---|
1948 | * Results:
|
---|
1949 | * None.
|
---|
1950 | *
|
---|
1951 | * Side effects:
|
---|
1952 | * PostScript pen width, dashes, and color settings are changed.
|
---|
1953 | *
|
---|
1954 | * ----------------------------------------------------------------------
|
---|
1955 | */
|
---|
1956 | /*ARGSUSED*/
|
---|
1957 | static void
|
---|
1958 | NormalBarToPostScript(graphPtr, psToken, elemPtr)
|
---|
1959 | Graph *graphPtr;
|
---|
1960 | PsToken psToken;
|
---|
1961 | Element *elemPtr;
|
---|
1962 | {
|
---|
1963 | Bar *barPtr = (Bar *)elemPtr;
|
---|
1964 | Blt_ChainLink *linkPtr;
|
---|
1965 | register BarPenStyle *stylePtr;
|
---|
1966 | int count;
|
---|
1967 | BarPen *penPtr;
|
---|
1968 | XColor *colorPtr;
|
---|
1969 |
|
---|
1970 | count = 0;
|
---|
1971 | for (linkPtr = Blt_ChainFirstLink(barPtr->palette); linkPtr != NULL;
|
---|
1972 | linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
1973 | stylePtr = Blt_ChainGetValue(linkPtr);
|
---|
1974 | penPtr = stylePtr->penPtr;
|
---|
1975 | if (stylePtr->nRects > 0) {
|
---|
1976 | SegmentsToPostScript(graphPtr, psToken, penPtr,
|
---|
1977 | stylePtr->rectangles, stylePtr->nRects);
|
---|
1978 | }
|
---|
1979 | colorPtr = penPtr->errorBarColor;
|
---|
1980 | if (colorPtr == COLOR_DEFAULT) {
|
---|
1981 | colorPtr = penPtr->fgColor;
|
---|
1982 | }
|
---|
1983 | if ((stylePtr->xErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_X)) {
|
---|
1984 | Blt_LineAttributesToPostScript(psToken, colorPtr,
|
---|
1985 | penPtr->errorBarLineWidth, NULL, CapButt, JoinMiter);
|
---|
1986 | Blt_2DSegmentsToPostScript(psToken, stylePtr->xErrorBars,
|
---|
1987 | stylePtr->xErrorBarCnt);
|
---|
1988 | }
|
---|
1989 | if ((stylePtr->yErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_Y)) {
|
---|
1990 | Blt_LineAttributesToPostScript(psToken, colorPtr,
|
---|
1991 | penPtr->errorBarLineWidth, NULL, CapButt, JoinMiter);
|
---|
1992 | Blt_2DSegmentsToPostScript(psToken, stylePtr->yErrorBars,
|
---|
1993 | stylePtr->yErrorBarCnt);
|
---|
1994 | }
|
---|
1995 | if (penPtr->valueShow != SHOW_NONE) {
|
---|
1996 | BarValuesToPostScript(graphPtr, psToken, barPtr, penPtr,
|
---|
1997 | stylePtr->rectangles, stylePtr->nRects,
|
---|
1998 | barPtr->rectToData + count);
|
---|
1999 | }
|
---|
2000 | count += stylePtr->nRects;
|
---|
2001 | }
|
---|
2002 | }
|
---|
2003 |
|
---|
2004 | /*
|
---|
2005 | * ----------------------------------------------------------------------
|
---|
2006 | *
|
---|
2007 | * DestroyBar --
|
---|
2008 | *
|
---|
2009 | * Release memory and resources allocated for the bar element.
|
---|
2010 | *
|
---|
2011 | * Results:
|
---|
2012 | * None.
|
---|
2013 | *
|
---|
2014 | * Side effects:
|
---|
2015 | * Everything associated with the bar element is freed up.
|
---|
2016 | *
|
---|
2017 | * ----------------------------------------------------------------------
|
---|
2018 | */
|
---|
2019 | #define FreeElemVector(v) \
|
---|
2020 | if ((v).clientId != NULL) { \
|
---|
2021 | Blt_FreeVectorId((v).clientId); \
|
---|
2022 | } else if ((v).valueArr != NULL) { \
|
---|
2023 | Blt_Free((v).valueArr); \
|
---|
2024 | }
|
---|
2025 |
|
---|
2026 | static void
|
---|
2027 | DestroyBar(graphPtr, elemPtr)
|
---|
2028 | Graph *graphPtr;
|
---|
2029 | Element *elemPtr;
|
---|
2030 | {
|
---|
2031 | Bar *barPtr = (Bar *)elemPtr;
|
---|
2032 |
|
---|
2033 | if (barPtr->normalPenPtr != &(barPtr->builtinPen)) {
|
---|
2034 | Blt_FreePen(graphPtr, (Pen *)barPtr->normalPenPtr);
|
---|
2035 | }
|
---|
2036 | DestroyPen(graphPtr, (Pen *)&(barPtr->builtinPen));
|
---|
2037 | if (barPtr->activePenPtr != NULL) {
|
---|
2038 | Blt_FreePen(graphPtr, (Pen *)barPtr->activePenPtr);
|
---|
2039 | }
|
---|
2040 | FreeElemVector(barPtr->x);
|
---|
2041 | FreeElemVector(barPtr->y);
|
---|
2042 | FreeElemVector(barPtr->w);
|
---|
2043 | FreeElemVector(barPtr->xHigh);
|
---|
2044 | FreeElemVector(barPtr->xLow);
|
---|
2045 | FreeElemVector(barPtr->xError);
|
---|
2046 | FreeElemVector(barPtr->yHigh);
|
---|
2047 | FreeElemVector(barPtr->yLow);
|
---|
2048 | FreeElemVector(barPtr->yError);
|
---|
2049 |
|
---|
2050 | ResetBar(barPtr);
|
---|
2051 | if (barPtr->activeIndices != NULL) {
|
---|
2052 | Blt_Free(barPtr->activeIndices);
|
---|
2053 | }
|
---|
2054 | if (barPtr->palette != NULL) {
|
---|
2055 | Blt_FreePalette(graphPtr, barPtr->palette);
|
---|
2056 | Blt_ChainDestroy(barPtr->palette);
|
---|
2057 | }
|
---|
2058 | if (barPtr->tags != NULL) {
|
---|
2059 | Blt_Free(barPtr->tags);
|
---|
2060 | }
|
---|
2061 | }
|
---|
2062 |
|
---|
2063 | /*
|
---|
2064 | * ----------------------------------------------------------------------
|
---|
2065 | *
|
---|
2066 | * Blt_BarElement --
|
---|
2067 | *
|
---|
2068 | * Allocate memory and initialize methods for the new bar element.
|
---|
2069 | *
|
---|
2070 | * Results:
|
---|
2071 | * The pointer to the newly allocated element structure is returned.
|
---|
2072 | *
|
---|
2073 | * Side effects:
|
---|
2074 | * Memory is allocated for the bar element structure.
|
---|
2075 | *
|
---|
2076 | * ----------------------------------------------------------------------
|
---|
2077 | */
|
---|
2078 |
|
---|
2079 | static ElementProcs barProcs =
|
---|
2080 | {
|
---|
2081 | ClosestBar,
|
---|
2082 | ConfigureBar,
|
---|
2083 | DestroyBar,
|
---|
2084 | DrawActiveBar,
|
---|
2085 | DrawNormalBar,
|
---|
2086 | DrawSymbol,
|
---|
2087 | GetBarExtents,
|
---|
2088 | ActiveBarToPostScript,
|
---|
2089 | NormalBarToPostScript,
|
---|
2090 | SymbolToPostScript,
|
---|
2091 | MapBar,
|
---|
2092 | };
|
---|
2093 |
|
---|
2094 |
|
---|
2095 | Element *
|
---|
2096 | Blt_BarElement(graphPtr, name, type)
|
---|
2097 | Graph *graphPtr;
|
---|
2098 | char *name;
|
---|
2099 | Blt_Uid type;
|
---|
2100 | {
|
---|
2101 | register Bar *barPtr;
|
---|
2102 |
|
---|
2103 | barPtr = Blt_Calloc(1, sizeof(Bar));
|
---|
2104 | assert(barPtr);
|
---|
2105 | barPtr->normalPenPtr = &(barPtr->builtinPen);
|
---|
2106 | barPtr->procsPtr = &barProcs;
|
---|
2107 | barPtr->specsPtr = barElemConfigSpecs;
|
---|
2108 | barPtr->labelRelief = TK_RELIEF_FLAT;
|
---|
2109 | barPtr->classUid = type;
|
---|
2110 | /* By default, an element's name and label are the same. */
|
---|
2111 | barPtr->label = Blt_Strdup(name);
|
---|
2112 | barPtr->name = Blt_Strdup(name);
|
---|
2113 |
|
---|
2114 | barPtr->graphPtr = graphPtr;
|
---|
2115 | barPtr->hidden = FALSE;
|
---|
2116 |
|
---|
2117 | InitPen(barPtr->normalPenPtr);
|
---|
2118 | barPtr->palette = Blt_ChainCreate();
|
---|
2119 | return (Element *)barPtr;
|
---|
2120 | }
|
---|
2121 |
|
---|
2122 | /*
|
---|
2123 | * ----------------------------------------------------------------------
|
---|
2124 | *
|
---|
2125 | * Blt_InitFreqTable --
|
---|
2126 | *
|
---|
2127 | * Generate a table of abscissa frequencies. Duplicate
|
---|
2128 | * x-coordinates (depending upon the bar drawing mode) indicate
|
---|
2129 | * that something special should be done with each bar segment
|
---|
2130 | * mapped to the same abscissa (i.e. it should be stacked,
|
---|
2131 | * aligned, or overlay-ed with other segments)
|
---|
2132 | *
|
---|
2133 | * Results:
|
---|
2134 | * None.
|
---|
2135 | *
|
---|
2136 | * Side effects:
|
---|
2137 | * Memory is allocated for the bar element structure.
|
---|
2138 | *
|
---|
2139 | * ----------------------------------------------------------------------
|
---|
2140 | */
|
---|
2141 | void
|
---|
2142 | Blt_InitFreqTable(graphPtr)
|
---|
2143 | Graph *graphPtr;
|
---|
2144 | {
|
---|
2145 | register Element *elemPtr;
|
---|
2146 | Blt_ChainLink *linkPtr;
|
---|
2147 | Blt_HashEntry *hPtr;
|
---|
2148 | Blt_HashSearch cursor;
|
---|
2149 | Bar *barPtr;
|
---|
2150 | int isNew, count;
|
---|
2151 | int nStacks, nSegs;
|
---|
2152 | int nPoints;
|
---|
2153 | FreqKey key;
|
---|
2154 | Blt_HashTable freqTable;
|
---|
2155 | register int i;
|
---|
2156 | double *xArr;
|
---|
2157 | /*
|
---|
2158 | * Free resources associated with a previous frequency table. This
|
---|
2159 | * includes the array of frequency information and the table itself
|
---|
2160 | */
|
---|
2161 | if (graphPtr->freqArr != NULL) {
|
---|
2162 | Blt_Free(graphPtr->freqArr);
|
---|
2163 | graphPtr->freqArr = NULL;
|
---|
2164 | }
|
---|
2165 | if (graphPtr->nStacks > 0) {
|
---|
2166 | Blt_DeleteHashTable(&(graphPtr->freqTable));
|
---|
2167 | graphPtr->nStacks = 0;
|
---|
2168 | }
|
---|
2169 | if (graphPtr->mode == MODE_INFRONT) {
|
---|
2170 | return; /* No frequency table is needed for
|
---|
2171 | * "infront" mode */
|
---|
2172 | }
|
---|
2173 | Blt_InitHashTable(&(graphPtr->freqTable), sizeof(FreqKey) / sizeof(int));
|
---|
2174 |
|
---|
2175 | /*
|
---|
2176 | * Initialize a hash table and fill it with unique abscissas.
|
---|
2177 | * Keep track of the frequency of each x-coordinate and how many
|
---|
2178 | * abscissas have duplicate mappings.
|
---|
2179 | */
|
---|
2180 | Blt_InitHashTable(&freqTable, sizeof(FreqKey) / sizeof(int));
|
---|
2181 | nSegs = nStacks = 0;
|
---|
2182 | for (linkPtr = Blt_ChainFirstLink(graphPtr->elements.displayList);
|
---|
2183 | linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
2184 | elemPtr = Blt_ChainGetValue(linkPtr);
|
---|
2185 | if ((elemPtr->hidden) || (elemPtr->classUid != bltBarElementUid)) {
|
---|
2186 | continue;
|
---|
2187 | }
|
---|
2188 | nSegs++;
|
---|
2189 | barPtr = (Bar *)elemPtr;
|
---|
2190 | xArr = barPtr->x.valueArr;
|
---|
2191 | nPoints = NumberOfPoints(barPtr);
|
---|
2192 | for (i = 0; i < nPoints; i++) {
|
---|
2193 | key.value = xArr[i];
|
---|
2194 | key.axes = barPtr->axes;
|
---|
2195 | hPtr = Blt_CreateHashEntry(&freqTable, (char *)&key, &isNew);
|
---|
2196 | assert(hPtr != NULL);
|
---|
2197 | if (isNew) {
|
---|
2198 | count = 1;
|
---|
2199 | } else {
|
---|
2200 | count = (int)Blt_GetHashValue(hPtr);
|
---|
2201 | if (count == 1) {
|
---|
2202 | nStacks++;
|
---|
2203 | }
|
---|
2204 | count++;
|
---|
2205 | }
|
---|
2206 | Blt_SetHashValue(hPtr, (ClientData)count);
|
---|
2207 | }
|
---|
2208 | }
|
---|
2209 | if (nSegs == 0) {
|
---|
2210 | return; /* No bar elements to be displayed */
|
---|
2211 | }
|
---|
2212 | if (nStacks > 0) {
|
---|
2213 | FreqInfo *infoPtr;
|
---|
2214 | FreqKey *keyPtr;
|
---|
2215 | Blt_HashEntry *h2Ptr;
|
---|
2216 |
|
---|
2217 | graphPtr->freqArr = Blt_Calloc(nStacks, sizeof(FreqInfo));
|
---|
2218 | assert(graphPtr->freqArr);
|
---|
2219 | infoPtr = graphPtr->freqArr;
|
---|
2220 | for (hPtr = Blt_FirstHashEntry(&freqTable, &cursor); hPtr != NULL;
|
---|
2221 | hPtr = Blt_NextHashEntry(&cursor)) {
|
---|
2222 | count = (int)Blt_GetHashValue(hPtr);
|
---|
2223 | keyPtr = (FreqKey *)Blt_GetHashKey(&freqTable, hPtr);
|
---|
2224 | if (count > 1) {
|
---|
2225 | h2Ptr = Blt_CreateHashEntry(&(graphPtr->freqTable),
|
---|
2226 | (char *)keyPtr, &isNew);
|
---|
2227 | count = (int)Blt_GetHashValue(hPtr);
|
---|
2228 | infoPtr->freq = count;
|
---|
2229 | infoPtr->axes = keyPtr->axes;
|
---|
2230 | Blt_SetHashValue(h2Ptr, infoPtr);
|
---|
2231 | infoPtr++;
|
---|
2232 | }
|
---|
2233 | }
|
---|
2234 | }
|
---|
2235 | Blt_DeleteHashTable(&freqTable);
|
---|
2236 | graphPtr->nStacks = nStacks;
|
---|
2237 | }
|
---|
2238 |
|
---|
2239 | /*
|
---|
2240 | * ----------------------------------------------------------------------
|
---|
2241 | *
|
---|
2242 | * Blt_ComputeStacks --
|
---|
2243 | *
|
---|
2244 | * Determine the height of each stack of bar segments. A stack
|
---|
2245 | * is created by designating two or more points with the same
|
---|
2246 | * abscissa. Each ordinate defines the height of a segment in
|
---|
2247 | * the stack. This procedure simply looks at all the data points
|
---|
2248 | * summing the heights of each stacked segment. The sum is saved
|
---|
2249 | * in the frequency information table. This value will be used
|
---|
2250 | * to calculate the y-axis limits (data limits aren't sufficient).
|
---|
2251 | *
|
---|
2252 | * Results:
|
---|
2253 | * None.
|
---|
2254 | *
|
---|
2255 | * Side effects:
|
---|
2256 | * The heights of each stack is computed. CheckStacks will
|
---|
2257 | * use this information to adjust the y-axis limits if necessary.
|
---|
2258 | *
|
---|
2259 | * ----------------------------------------------------------------------
|
---|
2260 | */
|
---|
2261 | void
|
---|
2262 | Blt_ComputeStacks(graphPtr)
|
---|
2263 | Graph *graphPtr;
|
---|
2264 | {
|
---|
2265 | Element *elemPtr;
|
---|
2266 | Bar *barPtr;
|
---|
2267 | FreqKey key;
|
---|
2268 | Blt_ChainLink *linkPtr;
|
---|
2269 | Blt_HashEntry *hPtr;
|
---|
2270 | int nPoints;
|
---|
2271 | register int i;
|
---|
2272 | register FreqInfo *infoPtr;
|
---|
2273 | double *xArr, *yArr;
|
---|
2274 |
|
---|
2275 | if ((graphPtr->mode != MODE_STACKED) || (graphPtr->nStacks == 0)) {
|
---|
2276 | return;
|
---|
2277 | }
|
---|
2278 | /* Reset the sums for all duplicate values to zero. */
|
---|
2279 |
|
---|
2280 | infoPtr = graphPtr->freqArr;
|
---|
2281 | for (i = 0; i < graphPtr->nStacks; i++) {
|
---|
2282 | infoPtr->sum = 0.0;
|
---|
2283 | infoPtr++;
|
---|
2284 | }
|
---|
2285 |
|
---|
2286 | /* Look at each bar point, adding the ordinates of duplicate abscissas */
|
---|
2287 |
|
---|
2288 | for (linkPtr = Blt_ChainFirstLink(graphPtr->elements.displayList);
|
---|
2289 | linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
|
---|
2290 | elemPtr = Blt_ChainGetValue(linkPtr);
|
---|
2291 | if ((elemPtr->hidden) || (elemPtr->classUid != bltBarElementUid)) {
|
---|
2292 | continue;
|
---|
2293 | }
|
---|
2294 | barPtr = (Bar *)elemPtr;
|
---|
2295 | xArr = barPtr->x.valueArr;
|
---|
2296 | yArr = barPtr->y.valueArr;
|
---|
2297 | nPoints = NumberOfPoints(barPtr);
|
---|
2298 | for (i = 0; i < nPoints; i++) {
|
---|
2299 | key.value = xArr[i];
|
---|
2300 | key.axes = barPtr->axes;
|
---|
2301 | hPtr = Blt_FindHashEntry(&(graphPtr->freqTable), (char *)&key);
|
---|
2302 | if (hPtr == NULL) {
|
---|
2303 | continue;
|
---|
2304 | }
|
---|
2305 | infoPtr = (FreqInfo *)Blt_GetHashValue(hPtr);
|
---|
2306 | infoPtr->sum += yArr[i];
|
---|
2307 | }
|
---|
2308 | }
|
---|
2309 | }
|
---|
2310 |
|
---|
2311 | void
|
---|
2312 | Blt_ResetStacks(graphPtr)
|
---|
2313 | Graph *graphPtr;
|
---|
2314 | {
|
---|
2315 | register FreqInfo *infoPtr, *endPtr;
|
---|
2316 |
|
---|
2317 | for (infoPtr = graphPtr->freqArr,
|
---|
2318 | endPtr = graphPtr->freqArr + graphPtr->nStacks;
|
---|
2319 | infoPtr < endPtr; infoPtr++) {
|
---|
2320 | infoPtr->lastY = 0.0;
|
---|
2321 | infoPtr->count = 0;
|
---|
2322 | }
|
---|
2323 | }
|
---|
2324 |
|
---|