Old Bar.c
  1 /* #include <X11/copyright.h> */
  2 
  3 /* $XConsortium: Bar.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
  4 /* Copyright    Massachusetts Institute of Technology   1987, 1988 */
  5 
  6 #include <X11/IntrinsicP.h>
  7 #include <X11/StringDefs.h>
  8 #include "array.h"
  9 #include "BarP.h"
 10 
 11 static Dimension def_dimension  = (Dimension)~0;
 12 static XtOrientation def_orient = XtorientHorizontal;
 13 static Boolean def_true = True;
 14 
 15 #define DEF_LENGTH  ((Dimension) 200)
 16 #define DEF_THICKNESS   ((Dimension) 15)
 17 
 18 /*
 19  * !! should provide converters for Arrays of some supported types, and
 20  * for fillstyles
 21  */
 22 static XtResource resources[] = {
 23 #define offset(field) XtOffset(BarWidget, bar.field)
 24 #define Offset(field) XtOffset(BarWidget, field)
 25     /* {name, class, type, size, offset, default_type, default_addr}, */
 26     /*
 27      * We define these core class values to set defaults, so we can
 28      * initialize correctly
 29      */
 30     {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
 31         Offset(core.width), XtRDimension, (caddr_t)&def_dimension},
 32     {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
 33         Offset(core.height), XtRDimension, (caddr_t)&def_dimension},
 34     /* Private bar widget resources */
 35     {XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
 36         offset(length), XtRDimension, (caddr_t) &def_dimension},
 37     {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
 38         offset(thickness), XtRDimension, (caddr_t) &def_dimension},
 39     {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
 40         offset(orientation), XtROrientation, (caddr_t) &def_orient},
 41     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
 42         offset(foreground), XtRString, XtDefaultForeground},
 43     {XtNfillStyle, XtCFillStyle, XtRInt, sizeof(int),
 44         offset(fillstyle), XtRInt, (caddr_t) 0},
 45     {XtNpixmaps, XtCPixmaps, XtRArray, sizeof(Array *),
 46         offset(pixmaps), XtRArray, (caddr_t) NULL},
 47 #undef offset
 48 #undef Offset
 49 };
 50 
 51 static void ClassInitialize();
 52 static void Initialize();
 53 static void Resize();
 54 static void Redisplay();
 55 
 56 BarClassRec barClassRec = {
 57   { /* core fields */
 58     /* superclass               */      (WidgetClass) &widgetClassRec,
 59     /* class_name               */      "Bar",
 60     /* widget_size              */      sizeof(BarRec),
 61     /* class_initialize         */      ClassInitialize,
 62     /* class_part_initialize    */      NULL,
 63     /* class_inited             */      FALSE,
 64     /* initialize               */      Initialize,
 65     /* initialize_hook          */      NULL,
 66     /* realize                  */      XtInheritRealize,
 67     /* actions                  */      NULL,
 68     /* num_actions              */      0,
 69     /* resources                */      resources,
 70     /* num_resources            */      XtNumber(resources),
 71     /* xrm_class                */      NULLQUARK,
 72     /* compress_motion          */      TRUE,
 73     /* compress_exposure        */      TRUE,
 74     /* compress_enterleave      */      TRUE,
 75     /* visible_interest         */      FALSE,
 76     /* destroy                  */      NULL,
 77     /* resize                   */      Resize,
 78     /* expose                   */      Redisplay,
 79     /* set_values               */      NULL,
 80     /* set_values_hook          */      NULL,
 81     /* set_values_almost        */      XtInheritSetValuesAlmost,
 82     /* get_values_hook          */      NULL,
 83     /* accept_focus             */      NULL,
 84     /* version                  */      XtVersion,
 85     /* callback_private         */      NULL,
 86     /* tm_table                 */      NULL,
 87     /* query_geometry           */      XtInheritQueryGeometry,
 88     /* display_accelerator      */      XtInheritDisplayAccelerator,
 89     /* extension                */      NULL
 90   },
 91   { /* Bar class fields */
 92     /* extension                */      NULL
 93   }
 94 };
 95 
 96 WidgetClass barWidgetClass = (WidgetClass)&barClassRec;
 97 
 98 static void
 99 ClassInitialize()
100 {
101     XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
102                     NULL, (Cardinal)0 );
103 }
104 
105 static void
106 SetDimensions(w)
107 BarWidget w;
108 {
109     if (w->bar.orientation == XtorientVertical) {
110         w->bar.length = w->core.height;
111         w->bar.thickness = w->core.width;
112     }
113     else {
114         w->bar.length = w->core.width;
115         w->bar.thickness = w->core.height;
116     }
117 }
118 
119 /* 
120  * We can't use XtGetGC, since we're going to write to the GC, so we use
121  * a simple caching scheme to share a gc between Bar widgets of the same
122  * fillstyle on the same display.  The first Bar widget in gets to be
123  * the GC we cache.  For most applications, all Bars will be on one
124  * display and use the same fillStyle, we hope.
125  */
126 static GC gc_cache;
127 static Display *dpy_cache;
128 static int fstyle_cache;
129 
130 /* ARGSUSED */
131 static void
132 Initialize(request, new)
133 Widget request;         /* what the client asked for */
134 Widget new;             /* what we're going to give him */
135 {
136     BarWidget w = (BarWidget) new;
137     XGCValues gcv;
138     Display *dpy = XtDisplay(new);
139 
140     if (dpy_cache == NULL || w->bar.fillstyle != fstyle_cache ||
141         dpy_cache != dpy) {
142         gcv.fill_style = w->bar.fillstyle;
143         gcv.foreground = w->bar.foreground;
144         gcv.background = w->core.background_pixel;
145         w->bar.gc = XCreateGC(dpy, DefaultRootWindow(dpy),
146                               GCFillStyle | GCForeground | GCBackground, &gcv);
147         if (dpy_cache == NULL) {
148             dpy_cache = dpy;
149             fstyle_cache = w->bar.fillstyle;
150             gc_cache = w->bar.gc;
151         }
152     } else {
153         w->bar.gc = gc_cache;
154     }
155     /* Width and height override length and thickness */
156     if (w->bar.length == def_dimension)
157         w->bar.length = DEF_LENGTH;
158         
159     if (w->bar.thickness == def_dimension)
160         w->bar.thickness = DEF_THICKNESS;
161         
162     if (w->core.width == def_dimension)
163         w->core.width = (w->bar.orientation == XtorientVertical)
164             ? w->bar.thickness : w->bar.length;
165 
166     if (w->core.height == def_dimension)
167         w->core.height = (w->bar.orientation == XtorientHorizontal)
168             ? w->bar.thickness : w->bar.length;
169     w->bar.values = NULL;
170     w->bar.nvalues = 0;
171 
172     SetDimensions(w);
173 }
174 
175 /* ARGSUSED */
176 static void
177 Resize(gw)
178 Widget gw;
179 {
180     SetDimensions((BarWidget)gw);
181     Redisplay(gw, (XEvent*)NULL, (Region)NULL);
182 }
183 
184 /* ARGSUSED */
185 static void
186 Redisplay(gw, event, region)
187 Widget gw;
188 XEvent *event;
189 Region region;
190 {
191     BarWidget w = (BarWidget) gw;
192     int x, y;
193     unsigned int width, height;
194     int maxvalue, i;
195     int vertical = (w->bar.orientation == XtorientVertical);;
196 
197     if (! XtIsRealized(gw))
198         return;
199     for(maxvalue = 0, i = 0; i < w->bar.nvalues; i++)
200         maxvalue += w->bar.values[i];
201     if(maxvalue <= 0)
202         return;
203     x = y = 0;
204     if(vertical)
205         width = w->bar.thickness;
206     else
207         height = w->bar.thickness;
208     if (w->bar.nvalues > w->bar.pixmaps->nitems) {
209         XtWarning("Too many values to represent in a bar");
210         return;
211     }
212     for(i = 0; i < w->bar.nvalues; i++) {
213         unsigned int rectlen = (w->bar.length * w->bar.values[i] +
214                                 maxvalue / 2) / (unsigned int)maxvalue;
215         if (rectlen == 0)
216             continue;
217         if (i == w->bar.nvalues - 1) {
218             if (vertical)
219                 rectlen = w->core.height - y;
220             else
221                 rectlen = w->core.width - x;
222         }
223         switch (w->bar.fillstyle) {
224         case FillSolid:
225             XSetForeground(XtDisplay(gw), w->bar.gc,
226                            ((Pixel *) w->bar.pixmaps->items)[i]);
227             break;
228         case FillTiled:
229             XSetTile(XtDisplay(gw), w->bar.gc,
230                            ((Pixmap *) w->bar.pixmaps->items)[i]);
231             break;
232         case FillStippled:
233         case FillOpaqueStippled:
234             XSetStipple(XtDisplay(gw), w->bar.gc,
235                            ((Pixmap *) w->bar.pixmaps->items)[i]);
236             break;
237         }
238         if(vertical) {
239             XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
240              x, y, width, rectlen);
241             y += rectlen;
242         } else {
243             XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
244              x, y, rectlen, height);
245             x += rectlen;
246         }
247     }
248 }
249 
250 /* !! We really should make the widget support Xt{Get,Set}Values fully */
251 /* Public routines. */
252 void
253 SetBarValues(gw, values, nvalues)
254 Widget gw;
255 int *values;
256 int nvalues;
257 {
258     BarWidget w = (BarWidget) gw;
259     int i;
260 
261     if (nvalues > w->bar.pixmaps->nitems) {
262 #define ERRFMT "Tried to set %d values for bar - maximum is %d\n"
263         char errbuf[sizeof(ERRFMT) + 32];
264         (void) sprintf(errbuf, ERRFMT, nvalues, w->bar.pixmaps->nitems);
265 #undef ERRFMT
266         XtWarning(errbuf);
267         nvalues = w->bar.pixmaps->nitems;
268     }
269     if (nvalues <= 0) {
270 #define ERRFMT "Tried to set %d values for bar - it must be > 0\n"
271         char errbuf[sizeof(ERRFMT) + 32];
272         (void) sprintf(errbuf, ERRFMT, nvalues);
273         XtWarning(errbuf);
274 #undef ERRFMT
275         return;
276     }
277     if (w->bar.values == NULL || w->bar.nvalues < nvalues) {
278         if (w->bar.values) XtFree((char *) w->bar.values);
279         w->bar.values = (int *) XtMalloc(nvalues * sizeof(int));
280     }
281     w->bar.nvalues = nvalues;
282     for(i = 0; i < nvalues; i++)
283         w->bar.values[i] = values[i];
284     Redisplay( gw, (XEvent*)NULL, (Region)NULL );
285 }