source: trunk/kitgen/8.x/blt/generic/bltGrHairs.c@ 201

Last change on this file since 201 was 175, checked in by demin, 12 years ago

initial commit

File size: 14.0 KB
Line 
1
2/*
3 * bltGrHairs.c --
4 *
5 * This module implements crosshairs 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 * Graph widget created by Sani Nassif and George Howlett.
28*/
29
30#include "bltGraph.h"
31
32extern Tk_CustomOption bltPointOption;
33extern Tk_CustomOption bltDistanceOption;
34extern Tk_CustomOption bltDashesOption;
35
36/*
37 * -------------------------------------------------------------------
38 *
39 * Crosshairs
40 *
41 * Contains the line segments positions and graphics context used
42 * to simulate crosshairs (by XORing) on the graph.
43 *
44 * -------------------------------------------------------------------
45 */
46
47struct CrosshairsStruct {
48
49 XPoint hotSpot; /* Hot spot for crosshairs */
50 int visible; /* Internal state of crosshairs. If non-zero,
51 * crosshairs are displayed. */
52 int hidden; /* If non-zero, crosshairs are not displayed.
53 * This is not necessarily consistent with the
54 * internal state variable. This is true when
55 * the hot spot is off the graph. */
56 Blt_Dashes dashes; /* Dashstyle of the crosshairs. This represents
57 * an array of alternatingly drawn pixel
58 * values. If NULL, the hairs are drawn as a
59 * solid line */
60 int lineWidth; /* Width of the simulated crosshair lines */
61 XSegment segArr[2]; /* Positions of line segments representing the
62 * simulated crosshairs. */
63 XColor *colorPtr; /* Foreground color of crosshairs */
64 GC gc; /* Graphics context for crosshairs. Set to
65 * GXxor to not require redraws of graph */
66};
67
68#define DEF_HAIRS_DASHES (char *)NULL
69#define DEF_HAIRS_FOREGROUND RGB_BLACK
70#define DEF_HAIRS_FG_MONO RGB_BLACK
71#define DEF_HAIRS_LINE_WIDTH "0"
72#define DEF_HAIRS_HIDE "yes"
73#define DEF_HAIRS_POSITION (char *)NULL
74
75static Tk_ConfigSpec configSpecs[] =
76{
77 {TK_CONFIG_COLOR, "-color", "color", "Color",
78 DEF_HAIRS_FOREGROUND, Tk_Offset(Crosshairs, colorPtr), TK_CONFIG_COLOR_ONLY},
79 {TK_CONFIG_COLOR, "-color", "color", "Color",
80 DEF_HAIRS_FG_MONO, Tk_Offset(Crosshairs, colorPtr), TK_CONFIG_MONO_ONLY},
81 {TK_CONFIG_CUSTOM, "-dashes", "dashes", "Dashes",
82 DEF_HAIRS_DASHES, Tk_Offset(Crosshairs, dashes),
83 TK_CONFIG_NULL_OK, &bltDashesOption},
84 {TK_CONFIG_BOOLEAN, "-hide", "hide", "Hide",
85 DEF_HAIRS_HIDE, Tk_Offset(Crosshairs, hidden),
86 TK_CONFIG_DONT_SET_DEFAULT},
87 {TK_CONFIG_CUSTOM, "-linewidth", "lineWidth", "Linewidth",
88 DEF_HAIRS_LINE_WIDTH, Tk_Offset(Crosshairs, lineWidth),
89 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
90 {TK_CONFIG_CUSTOM, "-position", "position", "Position",
91 DEF_HAIRS_POSITION, Tk_Offset(Crosshairs, hotSpot),
92 0, &bltPointOption},
93 {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
94};
95
96/*
97 *----------------------------------------------------------------------
98 *
99 * TurnOffHairs --
100 *
101 * XOR's the existing line segments (representing the crosshairs),
102 * thereby erasing them. The internal state of the crosshairs is
103 * tracked.
104 *
105 * Results:
106 * None
107 *
108 * Side Effects:
109 * Crosshairs are erased.
110 *
111 *----------------------------------------------------------------------
112 */
113static void
114TurnOffHairs(tkwin, chPtr)
115 Tk_Window tkwin;
116 Crosshairs *chPtr;
117{
118 if (Tk_IsMapped(tkwin) && (chPtr->visible)) {
119 XDrawSegments(Tk_Display(tkwin), Tk_WindowId(tkwin), chPtr->gc,
120 chPtr->segArr, 2);
121 chPtr->visible = FALSE;
122 }
123}
124
125/*
126 *----------------------------------------------------------------------
127 *
128 * TurnOnHairs --
129 *
130 * Draws (by XORing) new line segments, creating the effect of
131 * crosshairs. The internal state of the crosshairs is tracked.
132 *
133 * Results:
134 * None
135 *
136 * Side Effects:
137 * Crosshairs are displayed.
138 *
139 *----------------------------------------------------------------------
140 */
141static void
142TurnOnHairs(graphPtr, chPtr)
143 Graph *graphPtr;
144 Crosshairs *chPtr;
145{
146 if (Tk_IsMapped(graphPtr->tkwin) && (!chPtr->visible)) {
147 if (!PointInGraph(graphPtr, chPtr->hotSpot.x, chPtr->hotSpot.y)) {
148 return; /* Coordinates are off the graph */
149 }
150 XDrawSegments(graphPtr->display, Tk_WindowId(graphPtr->tkwin),
151 chPtr->gc, chPtr->segArr, 2);
152 chPtr->visible = TRUE;
153 }
154}
155
156/*
157 *----------------------------------------------------------------------
158 *
159 * ConfigureCrosshairs --
160 *
161 * Configures attributes of the crosshairs such as line width,
162 * dashes, and position. The crosshairs are first turned off
163 * before any of the attributes changes.
164 *
165 * Results:
166 * None
167 *
168 * Side Effects:
169 * Crosshair GC is allocated.
170 *
171 *----------------------------------------------------------------------
172 */
173void
174Blt_ConfigureCrosshairs(graphPtr)
175 Graph *graphPtr;
176{
177 XGCValues gcValues;
178 unsigned long gcMask;
179 GC newGC;
180 long colorValue;
181 Crosshairs *chPtr = graphPtr->crosshairs;
182
183 /*
184 * Turn off the crosshairs temporarily. This is in case the new
185 * configuration changes the size, style, or position of the lines.
186 */
187 TurnOffHairs(graphPtr->tkwin, chPtr);
188
189 gcValues.function = GXxor;
190
191 if (graphPtr->plotBg == NULL) {
192 /* The graph's color option may not have been set yet */
193 colorValue = WhitePixelOfScreen(Tk_Screen(graphPtr->tkwin));
194 } else {
195 colorValue = graphPtr->plotBg->pixel;
196 }
197 gcValues.background = colorValue;
198 gcValues.foreground = (colorValue ^ chPtr->colorPtr->pixel);
199
200 gcValues.line_width = LineWidth(chPtr->lineWidth);
201 gcMask = (GCForeground | GCBackground | GCFunction | GCLineWidth);
202 if (LineIsDashed(chPtr->dashes)) {
203 gcValues.line_style = LineOnOffDash;
204 gcMask |= GCLineStyle;
205 }
206 newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
207 if (LineIsDashed(chPtr->dashes)) {
208 Blt_SetDashes(graphPtr->display, newGC, &(chPtr->dashes));
209 }
210 if (chPtr->gc != NULL) {
211 Blt_FreePrivateGC(graphPtr->display, chPtr->gc);
212 }
213 chPtr->gc = newGC;
214
215 /*
216 * Are the new coordinates on the graph?
217 */
218 chPtr->segArr[0].x2 = chPtr->segArr[0].x1 = chPtr->hotSpot.x;
219 chPtr->segArr[0].y1 = graphPtr->bottom;
220 chPtr->segArr[0].y2 = graphPtr->top;
221 chPtr->segArr[1].y2 = chPtr->segArr[1].y1 = chPtr->hotSpot.y;
222 chPtr->segArr[1].x1 = graphPtr->left;
223 chPtr->segArr[1].x2 = graphPtr->right;
224
225 if (!chPtr->hidden) {
226 TurnOnHairs(graphPtr, chPtr);
227 }
228}
229
230void
231Blt_EnableCrosshairs(graphPtr)
232 Graph *graphPtr;
233{
234 if (!graphPtr->crosshairs->hidden) {
235 TurnOnHairs(graphPtr, graphPtr->crosshairs);
236 }
237}
238
239void
240Blt_DisableCrosshairs(graphPtr)
241 Graph *graphPtr;
242{
243 if (!graphPtr->crosshairs->hidden) {
244 TurnOffHairs(graphPtr->tkwin, graphPtr->crosshairs);
245 }
246}
247
248/*
249 *----------------------------------------------------------------------
250 *
251 * UpdateCrosshairs --
252 *
253 * Update the length of the hairs (not the hot spot).
254 *
255 * Results:
256 * None.
257 *
258 *----------------------------------------------------------------------
259 */
260void
261Blt_UpdateCrosshairs(graphPtr)
262 Graph *graphPtr;
263{
264 Crosshairs *chPtr = graphPtr->crosshairs;
265
266 chPtr->segArr[0].y1 = graphPtr->bottom;
267 chPtr->segArr[0].y2 = graphPtr->top;
268 chPtr->segArr[1].x1 = graphPtr->left;
269 chPtr->segArr[1].x2 = graphPtr->right;
270}
271
272/*
273 *----------------------------------------------------------------------
274 *
275 * Blt_DestroyCrosshairs --
276 *
277 * Results:
278 * None
279 *
280 * Side Effects:
281 * Crosshair GC is allocated.
282 *
283 *----------------------------------------------------------------------
284 */
285void
286Blt_DestroyCrosshairs(graphPtr)
287 Graph *graphPtr;
288{
289 Crosshairs *chPtr = graphPtr->crosshairs;
290
291 Tk_FreeOptions(configSpecs, (char *)chPtr, graphPtr->display, 0);
292 if (chPtr->gc != NULL) {
293 Blt_FreePrivateGC(graphPtr->display, chPtr->gc);
294 }
295 Blt_Free(chPtr);
296}
297
298/*
299 *----------------------------------------------------------------------
300 *
301 * Blt_CreateCrosshairs --
302 *
303 * Creates and initializes a new crosshair structure.
304 *
305 * Results:
306 * Returns TCL_ERROR if the crosshair structure can't be created,
307 * otherwise TCL_OK.
308 *
309 * Side Effects:
310 * Crosshair GC is allocated.
311 *
312 *----------------------------------------------------------------------
313 */
314int
315Blt_CreateCrosshairs(graphPtr)
316 Graph *graphPtr;
317{
318 Crosshairs *chPtr;
319
320 chPtr = Blt_Calloc(1, sizeof(Crosshairs));
321 assert(chPtr);
322 chPtr->hidden = TRUE;
323 chPtr->hotSpot.x = chPtr->hotSpot.y = -1;
324 graphPtr->crosshairs = chPtr;
325
326 if (Blt_ConfigureWidgetComponent(graphPtr->interp, graphPtr->tkwin,
327 "crosshairs", "Crosshairs", configSpecs, 0, (char **)NULL,
328 (char *)chPtr, 0) != TCL_OK) {
329 return TCL_ERROR;
330 }
331 return TCL_OK;
332}
333
334/*
335 *----------------------------------------------------------------------
336 *
337 * CgetOp --
338 *
339 * Queries configuration attributes of the crosshairs such as
340 * line width, dashes, and position.
341 *
342 * Results:
343 * A standard Tcl result.
344 *
345 *----------------------------------------------------------------------
346 */
347/* ARGSUSED */
348static int
349CgetOp(graphPtr, interp, argc, argv)
350 Graph *graphPtr;
351 Tcl_Interp *interp;
352 int argc; /* Not used. */
353 char **argv;
354{
355 Crosshairs *chPtr = graphPtr->crosshairs;
356
357 return Tk_ConfigureValue(interp, graphPtr->tkwin, configSpecs,
358 (char *)chPtr, argv[3], 0);
359}
360
361/*
362 *----------------------------------------------------------------------
363 *
364 * ConfigureOp --
365 *
366 * Queries or resets configuration attributes of the crosshairs
367 * such as line width, dashes, and position.
368 *
369 * Results:
370 * A standard Tcl result.
371 *
372 * Side Effects:
373 * Crosshairs are reset.
374 *
375 *----------------------------------------------------------------------
376 */
377static int
378ConfigureOp(graphPtr, interp, argc, argv)
379 Graph *graphPtr;
380 Tcl_Interp *interp;
381 int argc;
382 char **argv;
383{
384 Crosshairs *chPtr = graphPtr->crosshairs;
385
386 if (argc == 3) {
387 return Tk_ConfigureInfo(interp, graphPtr->tkwin, configSpecs,
388 (char *)chPtr, (char *)NULL, 0);
389 } else if (argc == 4) {
390 return Tk_ConfigureInfo(interp, graphPtr->tkwin, configSpecs,
391 (char *)chPtr, argv[3], 0);
392 }
393 if (Tk_ConfigureWidget(interp, graphPtr->tkwin, configSpecs, argc - 3,
394 argv + 3, (char *)chPtr, TK_CONFIG_ARGV_ONLY) != TCL_OK) {
395 return TCL_ERROR;
396 }
397 Blt_ConfigureCrosshairs(graphPtr);
398 return TCL_OK;
399}
400
401/*
402 *----------------------------------------------------------------------
403 *
404 * OnOp --
405 *
406 * Maps the crosshairs.
407 *
408 * Results:
409 * A standard Tcl result.
410 *
411 * Side Effects:
412 * Crosshairs are reset if necessary.
413 *
414 *----------------------------------------------------------------------
415 */
416/*ARGSUSED*/
417static int
418OnOp(graphPtr, interp, argc, argv)
419 Graph *graphPtr;
420 Tcl_Interp *interp;
421 int argc;
422 char **argv;
423{
424 Crosshairs *chPtr = graphPtr->crosshairs;
425
426 if (chPtr->hidden) {
427 TurnOnHairs(graphPtr, chPtr);
428 chPtr->hidden = FALSE;
429 }
430 return TCL_OK;
431}
432
433/*
434 *----------------------------------------------------------------------
435 *
436 * OffOp --
437 *
438 * Unmaps the crosshairs.
439 *
440 * Results:
441 * A standard Tcl result.
442 *
443 * Side Effects:
444 * Crosshairs are reset if necessary.
445 *
446 *----------------------------------------------------------------------
447 */
448/*ARGSUSED*/
449static int
450OffOp(graphPtr, interp, argc, argv)
451 Graph *graphPtr;
452 Tcl_Interp *interp;
453 int argc;
454 char **argv;
455{
456 Crosshairs *chPtr = graphPtr->crosshairs;
457
458 if (!chPtr->hidden) {
459 TurnOffHairs(graphPtr->tkwin, chPtr);
460 chPtr->hidden = TRUE;
461 }
462 return TCL_OK;
463}
464
465/*
466 *----------------------------------------------------------------------
467 *
468 * ToggleOp --
469 *
470 * Toggles the state of the crosshairs.
471 *
472 * Results:
473 * A standard Tcl result.
474 *
475 * Side Effects:
476 * Crosshairs are reset.
477 *
478 *----------------------------------------------------------------------
479 */
480/*ARGSUSED*/
481static int
482ToggleOp(graphPtr, interp, argc, argv)
483 Graph *graphPtr;
484 Tcl_Interp *interp;
485 int argc;
486 char **argv;
487{
488 Crosshairs *chPtr = graphPtr->crosshairs;
489
490 chPtr->hidden = (chPtr->hidden == 0);
491 if (chPtr->hidden) {
492 TurnOffHairs(graphPtr->tkwin, chPtr);
493 } else {
494 TurnOnHairs(graphPtr, chPtr);
495 }
496 return TCL_OK;
497}
498
499
500static Blt_OpSpec xhairOps[] =
501{
502 {"cget", 2, (Blt_Op)CgetOp, 4, 4, "option",},
503 {"configure", 2, (Blt_Op)ConfigureOp, 3, 0, "?options...?",},
504 {"off", 2, (Blt_Op)OffOp, 3, 3, "",},
505 {"on", 2, (Blt_Op)OnOp, 3, 3, "",},
506 {"toggle", 1, (Blt_Op)ToggleOp, 3, 3, "",},
507};
508static int nXhairOps = sizeof(xhairOps) / sizeof(Blt_OpSpec);
509
510/*
511 *----------------------------------------------------------------------
512 *
513 * Blt_CrosshairsOp --
514 *
515 * User routine to configure crosshair simulation. Crosshairs
516 * are simulated by drawing line segments parallel to both axes
517 * using the XOR drawing function. The allows the lines to be
518 * erased (by drawing them again) without redrawing the entire
519 * graph. Care must be taken to erase crosshairs before redrawing
520 * the graph and redraw them after the graph is redraw.
521 *
522 * Results:
523 * The return value is a standard Tcl result.
524 *
525 * Side Effects:
526 * Crosshairs may be drawn in the plotting area.
527 *
528 *----------------------------------------------------------------------
529 */
530int
531Blt_CrosshairsOp(graphPtr, interp, argc, argv)
532 Graph *graphPtr;
533 Tcl_Interp *interp;
534 int argc;
535 char **argv;
536{
537 Blt_Op proc;
538
539 proc = Blt_GetOp(interp, nXhairOps, xhairOps, BLT_OP_ARG2, argc, argv, 0);
540 if (proc == NULL) {
541 return TCL_ERROR;
542 }
543 return (*proc) (graphPtr, interp, argc, argv);
544}
Note: See TracBrowser for help on using the repository browser.