1 /*******************************************************************
2 FILE: BarGraf.c
3 CONTENTS: Definitions for structures, methods, and actions of the
4 BarGraph widget.
5 AUTHOR: Paul D. Johnston
6 HISTORY:
7 Date Action
8 --------- ------------------------------------
9 5/23/92 Changed the widget class name so that it is preceded
10 by 'xc' with the first major word capitalized.
11 5/19/92 Added range checking to the callback processing and the
12 XcBGUpdateValue function.
13 4/15/92 Created.
14
15 ********************************************************************/
16
17 #include <stdio.h>
18
19 /* Xlib includes */
20 #include <X11/Xlib.h>
21
22 /* Xt includes */
23 #include <X11/StringDefs.h>
24 #include <X11/IntrinsicP.h>
25
26
27 /* Widget includes */
28 #include <X11/Xc/Xc.h>
29 #include <X11/Xc/Control.h>
30 #include <X11/Xc/Value.h>
31 #include <X11/Xc/BarGrafP.h> /* (includes BarGraf.h also) */
32
33
34 /* Macro redefinition for offset. */
35 #define offset(field) XtOffset(BarGraphWidget, field)
36
37
38 /* Declare widget methods */
39 static void ClassInitialize();
40 static void Initialize();
41 static void Redisplay();
42 static void Destroy();
43 static void Resize();
44 static XtGeometryResult QueryGeometry();
45 static Boolean SetValues();
46
47
48 /* Declare functions and variables private to this widget */
49 static void Update_value();
50 static void Draw_display();
51 static void Get_value();
52 static void Print_bounds();
53
54
55
56 /* Define the widget's resource list */
57 static XtResource resources[] =
58 {
59 {
60 XcNorient,
61 XcCOrient,
62 XcROrient,
63 sizeof(XcOrient),
64 offset(barGraph.orient),
65 XtRString,
66 "vertical"
67 },
68 {
69 XcNbarForeground,
70 XtCColor,
71 XtRPixel,
72 sizeof(Pixel),
73 offset(barGraph.bar_foreground),
74 XtRString,
75 XtDefaultForeground
76 },
77 {
78 XcNbarBackground,
79 XtCColor,
80 XtRPixel,
81 sizeof(Pixel),
82 offset(barGraph.bar_background),
83 XtRString,
84 XtDefaultBackground
85 },
86 {
87 XcNscaleColor,
88 XtCColor,
89 XtRPixel,
90 sizeof(Pixel),
91 offset(barGraph.scale_pixel),
92 XtRString,
93 XtDefaultForeground
94 },
95 {
96 XcNscaleSegments,
97 XcCScaleSegments,
98 XtRInt,
99 sizeof(int),
100 offset(barGraph.num_segments),
101 XtRImmediate,
102 (XtPointer)7
103 },
104 {
105 XcNvalueVisible,
106 XtCBoolean,
107 XtRBoolean,
108 sizeof(Boolean),
109 offset(barGraph.value_visible),
110 XtRString,
111 "True"
112 },
113 {
114 XcNinterval,
115 XcCInterval,
116 XtRInt,
117 sizeof(int),
118 offset(barGraph.interval),
119 XtRImmediate,
120 (XtPointer)0
121 },
122 {
123 XcNupdateCallback,
124 XtCCallback,
125 XtRCallback,
126 sizeof(caddr_t),
127 offset(barGraph.update_callback),
128 XtRCallback,
129 NULL
130 },
131 };
132
133
134
135
136 /* Widget Class Record initialization */
137 BarGraphClassRec barGraphClassRec =
138 {
139 {
140 /* core_class part */
141 (WidgetClass) &valueClassRec, /* superclass */
142 "BarGraph", /* class_name */
143 sizeof(BarGraphRec), /* widget_size */
144 ClassInitialize, /* class_initialize */
145 NULL, /* class_part_initialize */
146 FALSE, /* class_inited */
147 Initialize, /* initialize */
148 NULL, /* initialize_hook */
149 XtInheritRealize, /* realize */
150 NULL, /* actions */
151 0, /* num_actions */
152 resources, /* resources */
153 XtNumber(resources), /* num_resources */
154 NULLQUARK, /* xrm_class */
155 TRUE, /* compress_motion */
156 TRUE, /* compress_exposure */
157 TRUE, /* compress_enterleave */
158 TRUE, /* visible_interest */
159 Destroy, /* destroy */
160 Resize, /* resize */
161 Redisplay, /* expose */
162 SetValues, /* set_values */
163 NULL, /* set_values_hook */
164 XtInheritSetValuesAlmost, /* set_values_almost */
165 NULL, /* get_values_hook */
166 NULL, /* accept_focus */
167 XtVersion, /* version */
168 NULL, /* callback_private */
169 NULL, /* tm_table */
170 QueryGeometry, /* query_geometry */
171 NULL, /* display_accelerator */
172 NULL, /* extension */
173 },
174 {
175 /* Control class part */
176 0, /* dummy_field */
177 },
178 {
179 /* Value class part */
180 0, /* dummy_field */
181 },
182 {
183 /* BarGraph class part */
184 0, /* dummy_field */
185 }
186 };
187
188 WidgetClass xcBarGraphWidgetClass = (WidgetClass)&barGraphClassRec;
189
190
191 /* Widget method function definitions */
192
193 /*******************************************************************
194 NAME: ClassInitialize.
195 DESCRIPTION:
196 This method initializes the BarGraph widget class. Specifically,
197 it registers resource value converter functions with Xt.
198
199 *******************************************************************/
200
ClassInitialize()201 static void ClassInitialize()
202 {
203
204 XtAddConverter(XtRString, XcROrient, CvtStringToOrient, NULL, 0);
205
206 } /* end of ClassInitialize */
207
208
209
210
211
212
213 /*******************************************************************
214 NAME: Initialize.
215 DESCRIPTION:
216 This is the initialize method for the BarGraph widget. It
217 validates user-modifiable instance resources and initializes private
218 widget variables and structures. This function also creates any server
219 resources (i.e., GCs, fonts, Pixmaps, etc.) used by this widget. This
220 method is called by Xt when the application calls XtCreateWidget().
221
222 *******************************************************************/
223
Initialize(request,new)224 static void Initialize(request, new)
225 BarGraphWidget request, new;
226 {
227 /* Local variables */
228 Display *display = XtDisplay(new);
229
230
231 DPRINTF(("BarGraph: executing Initialize...\n"));
232
233 /*
234 * Validate public instance variable settings.
235 */
236 /* Check orientation resource setting. */
237 if ((new->barGraph.orient != XcVert) && (new->barGraph.orient != XcHoriz))
238 {
239 XtWarning("BarGraph: invalid orientation setting");
240 new->barGraph.orient = XcVert;
241 }
242
243 /* Check the interval resource setting. */
244 if (new->barGraph.interval >0)
245 {
246 new->barGraph.interval_id =
247 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)new),
248 new->barGraph.interval, Get_value, new);
249 }
250
251 /* Check the scaleSegments resource setting. */
252 if (new->barGraph.num_segments < MIN_SCALE_SEGS)
253 {
254 XtWarning("BarGraph: invalid number of scale segments");
255 new->barGraph.num_segments = MIN_SCALE_SEGS;
256 }
257 else if (new->barGraph.num_segments > MAX_SCALE_SEGS)
258 {
259 XtWarning("BarGraph: invalid number of scale segments");
260 new->barGraph.num_segments = MAX_SCALE_SEGS;
261 }
262
263 /* Check the valueVisible resource setting. */
264 if ((new->barGraph.value_visible != True) &&
265 (new->barGraph.value_visible != False))
266 {
267 XtWarning("BarGraph: invalid valueVisible setting");
268 new->barGraph.value_visible = True;
269 }
270
271 /* Initialize the BarGraph width and height. */
272 if (new->core.width < MIN_BG_WIDTH)
273 new->core.width = MIN_BG_WIDTH;
274 if (new->core.height < MIN_BG_HEIGHT)
275 new->core.height = MIN_BG_HEIGHT;
276
277 /* Initialize private instance variables. */
278
279 /* Set the initial geometry of the BarGraph elements. */
280 Resize(new);
281
282
283 DPRINTF(("BarGraph: done Initialize\n"));
284
285 } /* end of Initialize */
286
287
288
289
290
291 /*******************************************************************
292 NAME: Redisplay.
293 DESCRIPTION:
294 This function is the BarGraph's Expose method. It redraws the
295 BarGraph's 3D rectangle background, Value Box, label, Bar indicator,
296 and the Scale. All drawing takes place within the widget's window
297 (no need for an off-screen pixmap).
298
299 *******************************************************************/
300
Redisplay(w,event)301 static void Redisplay(w, event)
302 BarGraphWidget w;
303 XExposeEvent *event;
304 {
305 /* Local variables */
306 int j;
307 char upper[30], lower[30];
308
309 /*
310 * Check to see whether or not the widget's window is mapped. You can't
311 * draw into a window that is not mapped. Realizing a widget doesn't
312 * mean its mapped, but this call will work for most Window Managers.
313 */
314 if (!XtIsRealized((Widget)w))
315 return;
316
317 DPRINTF(("BarGraph: executing Redisplay\n"));
318
319 /* Draw the 3D rectangle background for the BarGraph. */
320 XSetClipMask(XtDisplay(w), w->control.gc, None);
321 Rect3d(w, XtDisplay(w), XtWindow(w), w->control.gc,
322 0, 0, w->core.width, w->core.height, RAISED);
323
324 /* Draw the Label string. */
325 XSetClipRectangles(XtDisplay(w), w->control.gc, 0, 0,
326 &(w->barGraph.face), 1, Unsorted);
327 XSetForeground(XtDisplay(w), w->control.gc,
328 w->control.label_pixel);
329 XDrawString(XtDisplay(w), XtWindow(w), w->control.gc,
330 w->barGraph.lbl.x, w->barGraph.lbl.y,
331 w->control.label, strlen(w->control.label));
332
333 /* Draw the Scale along the Bar indicator */
334 XSetForeground(XtDisplay(w), w->control.gc,
335 w->barGraph.scale_pixel);
336 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
337 w->barGraph.scale_line.x1, w->barGraph.scale_line.y1,
338 w->barGraph.scale_line.x2, w->barGraph.scale_line.y2);
339
340 /* Draw the max and min value segments. */
341 if (w->barGraph.orient == XcVert)
342 {
343 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
344 w->barGraph.scale_line.x1 - w->barGraph.seg_length,
345 w->barGraph.scale_line.y1, w->barGraph.scale_line.x1,
346 w->barGraph.scale_line.y1);
347 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
348 w->barGraph.scale_line.x2 - w->barGraph.seg_length,
349 w->barGraph.scale_line.y2, w->barGraph.scale_line.x2,
350 w->barGraph.scale_line.y2);
351 }
352 else
353 {
354 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
355 w->barGraph.scale_line.x1,
356 w->barGraph.scale_line.y1 - w->barGraph.seg_length,
357 w->barGraph.scale_line.x1, w->barGraph.scale_line.y1);
358 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
359 w->barGraph.scale_line.x2,
360 w->barGraph.scale_line.y2 - w->barGraph.seg_length,
361 w->barGraph.scale_line.x2, w->barGraph.scale_line.y2);
362 }
363
364 /* Now draw the rest of the Scale segments. */
365 if (w->barGraph.num_segments > 0)
366 {
367 for (j = 0; j < w->barGraph.num_segments; j++)
368 {
369 if (w->barGraph.orient == XcVert)
370 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
371 w->barGraph.segs[j].x, w->barGraph.segs[j].y,
372 w->barGraph.scale_line.x1, w->barGraph.segs[j].y);
373 else
374 XDrawLine(XtDisplay(w), XtWindow(w), w->control.gc,
375 w->barGraph.segs[j].x, w->barGraph.segs[j].y,
376 w->barGraph.segs[j].x, w->barGraph.scale_line.y1);
377 }
378 }
379
380
381 /* Draw the max and min value string indicators */
382 Print_bounds(w, upper, lower);
383 XDrawString(XtDisplay(w), XtWindow(w), w->control.gc,
384 w->barGraph.max_val.x, w->barGraph.max_val.y,
385 upper, strlen(upper));
386 XDrawString(XtDisplay(w), XtWindow(w), w->control.gc,
387 w->barGraph.min_val.x, w->barGraph.min_val.y,
388 lower, strlen(lower));
389
390
391 /* Draw the Bar indicator border */
392 Rect3d(w, XtDisplay(w), XtWindow(w), w->control.gc,
393 w->barGraph.bar.x - w->control.shade_depth,
394 w->barGraph.bar.y - w->control.shade_depth,
395 w->barGraph.bar.width + (2 * w->control.shade_depth),
396 w->barGraph.bar.height + (2 * w->control.shade_depth), DEPRESSED);
397
398 /* Draw the Value Box */
399 if (w->barGraph.value_visible == True)
400 Rect3d(w, XtDisplay(w), XtWindow(w), w->control.gc,
401 w->value.value_box.x - w->control.shade_depth,
402 w->value.value_box.y - w->control.shade_depth,
403 w->value.value_box.width + (2 * w->control.shade_depth),
404 w->value.value_box.height + (2 * w->control.shade_depth),
405 DEPRESSED);
406
407 /* Draw the new value represented by the Bar indicator and the value string */
408 Draw_display(w, XtDisplay(w), XtWindow(w), w->control.gc);
409
410
411 DPRINTF(("BarGraph: done Redisplay\n"));
412
413 } /* end of Redisplay */
414
415
416
417
418
419 /*******************************************************************
420 NAME: SetValues.
421 DESCRIPTION:
422 This is the set_values method for this widget. It validates resource
423 settings set with XtSetValues. If a resource is changed that would
424 require re-drawing the widget, return True.
425
426 *******************************************************************/
427
SetValues(cur,req,new)428 static Boolean SetValues(cur, req, new)
429 BarGraphWidget cur, req, new;
430 {
431 /* Local variables */
432 Boolean do_redisplay = False;
433
434
435 DPRINTF(("BarGraph: executing SetValues \n"));
436
437 /* Validate new resource settings. */
438
439 /* Check widget color resource settings. */
440 if ((new->barGraph.bar_foreground != cur->barGraph.bar_foreground) ||
441 (new->barGraph.bar_background != cur->barGraph.bar_background) ||
442 (new->barGraph.scale_pixel != cur->barGraph.scale_pixel))
443 do_redisplay = True;
444
445 /* Check orientation resource setting. */
446 if (new->barGraph.orient != cur->barGraph.orient)
447 {
448 do_redisplay = True;
449 if ((new->barGraph.orient != XcVert) && (new->barGraph.orient != XcHoriz))
450 {
451 XtWarning("BarGraph: invalid orientation setting");
452 new->barGraph.orient = XcVert;
453 }
454 }
455
456 /* Check the interval resource setting. */
457 if (new->barGraph.interval != cur->barGraph.interval)
458 {
459 if (cur->barGraph.interval > 0)
460 XtRemoveTimeOut (cur->barGraph.interval_id);
461 if (new->barGraph.interval > 0)
462 new->barGraph.interval_id =
463 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)new),
464 new->barGraph.interval, Get_value, new);
465 }
466
467 /* Check the scaleSegments resource setting. */
468 if (new->barGraph.num_segments != cur->barGraph.num_segments)
469 {
470 if (new->barGraph.num_segments < MIN_SCALE_SEGS)
471 {
472 XtWarning("BarGraph: invalid number of scale segments");
473 new->barGraph.num_segments = MIN_SCALE_SEGS;
474 }
475 else if (new->barGraph.num_segments > MAX_SCALE_SEGS)
476 {
477 XtWarning("BarGraph: invalid number of scale segments");
478 new->barGraph.num_segments = MAX_SCALE_SEGS;
479 }
480 }
481
482 /* Check the valueVisible resource setting. */
483 if (new->barGraph.value_visible != cur->barGraph.value_visible)
484 {
485 do_redisplay = True;
486 if ((new->barGraph.value_visible != True) &&
487 (new->barGraph.value_visible != False))
488 {
489 XtWarning("BarGraph: invalid valueVisible setting");
490 new->barGraph.value_visible = True;
491 }
492 }
493
494 /* Check to see if the value has changed. */
495 if ((((new->value.datatype == XcLval) || (new->value.datatype == XcHval)) &&
496 (new->value.val.lval != cur->value.val.lval))
497 || ((new->value.datatype == XcFval) &&
498 (new->value.val.fval != cur->value.val.fval)))
499 {
500 do_redisplay = True;
501 }
502
503
504 DPRINTF(("BarGraph: done SetValues\n"));
505 return do_redisplay;
506
507
508 } /* end of SetValues */
509
510
511
512
513 /*******************************************************************
514 NAME: Resize.
515 DESCRIPTION:
516 This is the resize method of the BarGraph widget. It resizes the
517 BarGraph's graphics based on the new width and height of the widget's
518 window.
519
520 *******************************************************************/
521
Resize(w)522 static void Resize(w)
523 BarGraphWidget w;
524 {
525 /* Local variables */
526 int j;
527 int seg_spacing;
528 int max_val_width, min_val_width;
529 int font_center;
530 char upper[30], lower[30];
531
532 DPRINTF(("BarGraph: executing Resize\n"));
533
534 /* Set the widgets new width and height. */
535 w->barGraph.face.x = w->barGraph.face.y = w->control.shade_depth;
536 w->barGraph.face.width = w->core.width - (2*w->control.shade_depth);
537 w->barGraph.face.height = w->core.height - (2*w->control.shade_depth);
538
539 /* Establish the new Value Box geometry. */
540 if (w->barGraph.orient == XcVert)
541 {
542 w->value.value_box.x = w->barGraph.face.x + (2*w->control.shade_depth);
543 w->value.value_box.y = w->barGraph.face.y + w->barGraph.face.height -
544 (short)(w->barGraph.face.height / 8 + 0.5) +
545 (2 * w->control.shade_depth);
546 w->value.value_box.width = w->barGraph.face.width -
547 (4 * w->control.shade_depth);
548 w->value.value_box.height = (short)(w->barGraph.face.height / 8 +0.5) -
549 (2*w->control.shade_depth);
550 }
551 else
552 {
553 w->value.value_box.x = w->barGraph.face.x +
554 (short)(w->barGraph.face.width / 3 + 0.5) +
555 w->control.shade_depth;
556 w->value.value_box.y = w->barGraph.face.y +
557 (short)((3 * w->barGraph.face.height) / 4 + 0.5) +
558 (2 * w->control.shade_depth);
559 w->value.value_box.width = (short)(w->barGraph.face.width / 3 +0.5) -
560 (2 * w->control.shade_depth);
561 w->value.value_box.height = (short)(w->barGraph.face.height / 4 +0.5) -
562 (2*w->control.shade_depth);
563 }
564
565 /* Set the position of the displayed value within the Value Box. */
566 Position_val(w);
567
568 /* Set the new label location. */
569 w->barGraph.lbl.x = (w->core.width / 2 + 0.5) -
570 (XTextWidth(w->control.font, w->control.label,
571 strlen(w->control.label)) / 2 + 0.5);
572 w->barGraph.lbl.y = w->barGraph.face.y + w->control.font->ascent + 1;
573
574
575 /* Resize the Bar indicator */
576 if (w->barGraph.orient == XcVert)
577 {
578 w->barGraph.bar.x = w->barGraph.face.x +
579 (short)((2 * w->barGraph.face.width) / 3 +0.5) +
580 w->control.shade_depth;
581 w->barGraph.bar.y = w->barGraph.face.y +
582 (short)(w->barGraph.face.height / 8 +0.5) +
583 w->control.shade_depth;
584 w->barGraph.bar.width = (short)(w->barGraph.face.width / 3 +0.5) -
585 (2*w->control.shade_depth);
586 w->barGraph.bar.height = (short)((6*w->barGraph.face.height) / 8 +0.5) -
587 (2*w->control.shade_depth);
588 }
589 else
590 {
591 w->barGraph.bar.x = w->barGraph.face.x +
592 (short)(w->barGraph.face.width / 8 +0.5) +
593 w->control.shade_depth;
594 w->barGraph.bar.y = w->barGraph.face.y +
595 (short)(w->barGraph.face.height / 2 +0.5) +
596 w->control.shade_depth;
597 w->barGraph.bar.width = (short)((6 * w->barGraph.face.width) / 8 +0.5) -
598 (2*w->control.shade_depth);
599 w->barGraph.bar.height = (short)(w->barGraph.face.height / 4 +0.5) -
600 (2*w->control.shade_depth);
601 }
602
603
604 /* Resize the Scale line. */
605 if (w->barGraph.orient == XcVert)
606 {
607 w->barGraph.scale_line.x1 = w->barGraph.bar.x - w->control.shade_depth -
608 (w->barGraph.face.width / 32 + 0.5);
609 w->barGraph.scale_line.y1 = w->barGraph.bar.y;
610 w->barGraph.scale_line.x2 = w->barGraph.scale_line.x1;
611 w->barGraph.scale_line.y2 = w->barGraph.bar.y + w->barGraph.bar.height;
612 }
613 else
614 {
615 w->barGraph.scale_line.x1 = w->barGraph.bar.x;
616 w->barGraph.scale_line.y1 = w->barGraph.bar.y - w->control.shade_depth -
617 (w->barGraph.face.height / 32 + 0.5);
618 w->barGraph.scale_line.x2 = w->barGraph.bar.x + w->barGraph.bar.width;
619 w->barGraph.scale_line.y2 = w->barGraph.scale_line.y1;
620 }
621
622 /* Now, resize Scale line segments */
623 if (w->barGraph.num_segments > 0)
624 {
625 if (w->barGraph.orient == XcVert)
626 {
627 w->barGraph.seg_length = (w->barGraph.face.width / 16 + 0.5);
628 seg_spacing = (w->barGraph.bar.height /
629 (w->barGraph.num_segments + 1) + 0.5);
630 for (j = 0; j < w->barGraph.num_segments; j++)
631 {
632 w->barGraph.segs[j].x = w->barGraph.scale_line.x1 -
633 w->barGraph.seg_length;
634 w->barGraph.segs[j].y = w->barGraph.scale_line.y1 +
635 ((j+1) * seg_spacing);
636 }
637 }
638 else
639 {
640 w->barGraph.seg_length = (w->barGraph.face.height / 16 + 0.5);
641 seg_spacing = (w->barGraph.bar.width /
642 (w->barGraph.num_segments + 1) + 0.5);
643 for (j = 0; j < w->barGraph.num_segments; j++)
644 {
645 w->barGraph.segs[j].x = w->barGraph.scale_line.x1 +
646 ((j+1) * seg_spacing);
647 w->barGraph.segs[j].y = w->barGraph.scale_line.y1 -
648 w->barGraph.seg_length;
649 }
650 }
651 }
652
653 /* Set the position of the max and min value strings */
654 Print_bounds(w, upper, lower);
655 max_val_width = XTextWidth(w->control.font, upper, strlen(upper));
656 min_val_width = XTextWidth(w->control.font, lower, strlen(lower));
657
658 if (w->barGraph.orient == XcVert)
659 {
660 font_center = ((w->control.font->ascent +
661 w->control.font->descent) / 2 + 0.5)
662 - w->control.font->descent;
663 w->barGraph.max_val.x = w->barGraph.scale_line.x1 -
664 w->barGraph.seg_length - max_val_width;
665 w->barGraph.max_val.y = w->barGraph.scale_line.y1 + font_center;
666 w->barGraph.min_val.x = w->barGraph.scale_line.x2 -
667 w->barGraph.seg_length - min_val_width;
668 w->barGraph.min_val.y = w->barGraph.scale_line.y2 + font_center;
669 }
670 else
671 {
672 w->barGraph.max_val.x = w->barGraph.scale_line.x2 - (max_val_width / 2);
673 w->barGraph.max_val.y = w->barGraph.min_val.y =
674 w->barGraph.scale_line.y1 - w->barGraph.seg_length -
675 w->control.font->descent;
676 w->barGraph.min_val.x = w->barGraph.scale_line.x1 - (min_val_width / 2);
677 }
678
679
680 DPRINTF(("BarGraph: done Resize\n"));
681
682 } /* end of Resize */
683
684
685
686
687 /*******************************************************************
688 NAME: QueryGeometry.
689 DESCRIPTION:
690 This function is the widget's query_geometry method. It simply
691 checks the proposed size and returns the appropriate value based on
692 the proposed size. If the proposed size is greater than the maximum
693 appropriate size for this widget, QueryGeometry returns the recommended
694 size.
695
696 *******************************************************************/
697
QueryGeometry(w,proposed,answer)698 static XtGeometryResult QueryGeometry(w, proposed, answer)
699 BarGraphWidget w;
700 XtWidgetGeometry *proposed, *answer;
701 {
702 /* Set the request mode mask for the returned answer. */
703 answer->request_mode = CWWidth | CWHeight;
704
705 /* Set the recommended size. */
706 answer->width = (w->core.width > MAX_BG_WIDTH)
707 ? MAX_BG_WIDTH : w->core.width;
708 answer->height = (w->core.height > MAX_BG_HEIGHT)
709 ? MAX_BG_HEIGHT : w->core.height;
710
711 /*
712 * Check the proposed dimensions. If the proposed size is larger than
713 * appropriate, return the recommended size.
714 */
715 if (((proposed->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
716 && proposed->width == answer->width
717 && proposed->height == answer->height)
718 return XtGeometryYes;
719 else if (answer->width == w->core.width && answer->height == w->core.height)
720 return XtGeometryNo;
721 else
722 return XtGeometryAlmost;
723
724 } /* end of QueryGeometry */
725
726
727
728
729 /*******************************************************************
730 NAME: Destroy.
731 DESCRIPTION:
732 This function is the widget's destroy method. It simply releases
733 any server resources acquired during the life of the widget.
734
735 *******************************************************************/
736
Destroy(w)737 static void Destroy(w)
738 BarGraphWidget w;
739 {
740
741 if (w->barGraph.interval > 0)
742 XtRemoveTimeOut (w->barGraph.interval_id);
743
744 } /* end of Destroy */
745
746
747
748
749
750 /* Widget action functions. */
751
752 /*******************************************************************
753 NAME: Get_value.
754 DESCRIPTION:
755 This function is the time out procedure called at XcNinterval
756 intervals. It calls the application registered callback function to
757 get the latest value and updates the BarGraph display accordingly.
758
759 *******************************************************************/
760
Get_value(client_data,id)761 static void Get_value(client_data, id)
762 caddr_t client_data;
763 XtIntervalId *id; /* unused */
764 {
765 /* Local variables */
766 static XcCallData call_data;
767 BarGraphWidget w = (BarGraphWidget)client_data;
768
769 /* Get the new value by calling the application's callback if it exists. */
770 if (w->barGraph.update_callback == NULL)
771 return;
772
773 /* Re-register this TimeOut procedure for the next interval. */
774 if (w->barGraph.interval > 0)
775 w->barGraph.interval_id =
776 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w),
777 w->barGraph.interval, Get_value, client_data);
778
779 /* Set the widget's current value and datatype before calling the callback. */
780 call_data.dtype = w->value.datatype;
781 call_data.decimals = w->value.decimals;
782 if ((w->value.datatype == XcLval) || (w->value.datatype == XcHval))
783 call_data.value.lval = w->value.val.lval;
784 else if (w->value.datatype == XcFval)
785 call_data.value.fval = w->value.val.fval;
786 XtCallCallbacks((Widget)w, XcNupdateCallback, &call_data);
787
788
789 /* Update the new value, update the BarGraph display. */
790 if ((w->value.datatype == XcLval) || (w->value.datatype == XcHval))
791 {
792 if ((call_data.value.lval <= w->value.upper_bound.lval) &&
793 (call_data.value.lval >= w->value.lower_bound.lval))
794 w->value.val.lval = call_data.value.lval;
795 }
796 else if (w->value.datatype == XcFval)
797 {
798 if ((call_data.value.fval <= w->value.upper_bound.fval) &&
799 (call_data.value.fval >= w->value.lower_bound.fval))
800 w->value.val.fval = call_data.value.fval;
801 }
802
803 if (XtIsRealized((Widget)w))
804 Draw_display(w, XtDisplay(w), XtWindow(w), w->control.gc);
805
806
807 } /* end of Get_value */
808
809
810
811
812 /*******************************************************************
813 NAME: XcBGUpdateValue.
814 DESCRIPTION:
815 This convenience function is called by the application in order to
816 update the value (a little quicker than using XtSetArg/XtSetValue).
817 The application passes the new value to be updated with.
818
819 *******************************************************************/
820
XcBGUpdateValue(w,value)821 void XcBGUpdateValue(w, value)
822 BarGraphWidget w;
823 XcVType *value;
824 {
825 /* Local variables */
826
827 /* Update the new value, then update the BarGraph display. */
828 if (value != NULL)
829 {
830 if ((w->value.datatype == XcLval) || (w->value.datatype == XcHval))
831 {
832 if ((value->lval <= w->value.upper_bound.lval) &&
833 (value->lval >= w->value.lower_bound.lval))
834 w->value.val.lval = value->lval;
835 }
836 else if (w->value.datatype == XcFval)
837 {
838 if ((value->fval <= w->value.upper_bound.fval) &&
839 (value->fval >= w->value.lower_bound.fval))
840 w->value.val.fval = value->fval;
841 }
842
843 if (XtIsRealized((Widget)w))
844 Draw_display(w, XtDisplay(w), XtWindow(w), w->control.gc);
845
846 }
847
848 } /* end of XcBGUpdateValue */
849
850
851
852
853 /*******************************************************************
854 NAME: Draw_display.
855 DESCRIPTION:
856 This function redraws the Bar indicator and the value string in the
857 Value Box.
858
859 *******************************************************************/
860
Draw_display(w,display,drawable,gc)861 static void Draw_display( w, display, drawable, gc)
862 BarGraphWidget w;
863 Display *display;
864 Drawable drawable;
865 GC gc;
866 {
867 /* Local variables */
868 char *temp;
869 float range, dim;
870
871 /* Draw the Bar indicator */
872 /* Fill the Bar with its background color. */
873 XSetForeground(display, gc, w->barGraph.bar_background);
874 XFillRectangle(display, drawable, gc,
875 w->barGraph.bar.x, w->barGraph.bar.y,
876 w->barGraph.bar.width, w->barGraph.bar.height);
877
878 /* Draw the Bar in its foreground color according to the value. */
879 if (w->barGraph.orient == XcVert)
880 range = (float)(w->barGraph.bar.height);
881 else
882 range = (float)(w->barGraph.bar.width);
883
884 if ((w->value.datatype == XcLval) || (w->value.datatype == XcHval))
885 dim = Correlate(((float)(w->value.val.lval) -
886 (float)(w->value.lower_bound.lval)),
887 ((float)(w->value.upper_bound.lval) -
888 (float)(w->value.lower_bound.lval)), range);
889 else if (w->value.datatype == XcFval)
890 dim = Correlate((w->value.val.fval - w->value.lower_bound.fval),
891 (w->value.upper_bound.fval -
892 w->value.lower_bound.fval), range);
893
894 if ((int)dim < 1)
895 dim = 1;
896 XSetForeground(display, gc, w->barGraph.bar_foreground);
897 if (w->barGraph.orient == XcVert)
898 XFillRectangle(display, drawable, gc, w->barGraph.bar.x,
899 (w->barGraph.bar.y + w->barGraph.bar.height - (int)dim),
900 w->barGraph.bar.width, (int)dim);
901 else
902 XFillRectangle(display, drawable, gc, w->barGraph.bar.x,
903 w->barGraph.bar.y, (int)dim, w->barGraph.bar.height);
904
905
906 /* If the value string is supposed to be displayed, draw it. */
907 if (w->barGraph.value_visible == True)
908 {
909 /* Clear the Value Box by re-filling it with its background color. */
910 XSetForeground(display, gc, w->value.value_bg_pixel);
911 XFillRectangle(display, drawable, gc,
912 w->value.value_box.x, w->value.value_box.y,
913 w->value.value_box.width, w->value.value_box.height);
914
915 /*
916 * Now draw the value string in its foreground color, clipped by the
917 * Value Box.
918 */
919 XSetForeground(display, gc, w->value.value_fg_pixel);
920 XSetClipRectangles(display, gc, 0, 0,
921 &(w->value.value_box), 1, Unsorted);
922
923 temp = Print_value(w->value.datatype, &w->value.val, w->value.decimals);
924
925 Position_val(w);
926
927 XDrawString(display, drawable, gc,
928 w->value.vp.x, w->value.vp.y, temp, strlen(temp));
929 }
930
931 /* Reset the clip_mask to no clipping. */
932 XSetClipMask(display, gc, None);
933
934 } /* end of Draw_display */
935
936
937
938
939 /*******************************************************************
940 NAME: Print_bounds.
941 DESCRIPTION:
942 This is a utility function used by the Redisplay and Resize methods to
943 print the upper and lower bound values as strings for displaying and resizing
944 purposes.
945
946 *******************************************************************/
947
Print_bounds(w,upper,lower)948 static void Print_bounds(w, upper, lower)
949 BarGraphWidget w;
950 char *upper, *lower;
951 {
952
953 if (w->value.datatype == XcLval)
954 {
955 sprintf(upper, "%ld", w->value.upper_bound.lval);
956 sprintf(lower, "%ld", w->value.lower_bound.lval);
957 }
958 else if (w->value.datatype == XcHval)
959 {
960 sprintf(upper, "%lX", w->value.upper_bound.lval);
961 sprintf(lower, "%lX", w->value.lower_bound.lval);
962 }
963 else if (w->value.datatype == XcFval)
964 {
965 sprintf(upper, "%.*f", w->value.decimals, w->value.upper_bound.fval);
966 sprintf(lower, "%.*f", w->value.decimals, w->value.lower_bound.fval);
967 }
968
969 } /* end of Print_bounds */
970
971
972 /* end of BarGraf.c */
973
974