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 }