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