1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #include "ProgressP.h"
50 #include <stdio.h>
51 #include <sys/time.h>
52 #include <time.h>
53
54 static void ClassInitialize(
void);
55 static void Initialize(Widget , Widget, ArgList, Cardinal *);
56 static void Resize(Widget);
57 static void Destroy(Widget);
58 static void Realize(Widget w, XtValueMask *valueMask,
59 XSetWindowAttributes *attr);
60 static void Redisplay(Widget, XEvent *, Region);
61 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
62 static void CopyRenderTable(XmLProgressWidget p);
63 static void TimeStr(
char *,
int);
64 static void DrawBarMeter(XmLProgressWidget p, XRectangle *rect);
65 static void DrawBoxesMeter(XmLProgressWidget p, XRectangle *rect);
66 static void DrawString(XmLProgressWidget, XmString,
int,
int,
67 int, XRectangle *, XRectangle *);
68 static Boolean CvtStringToMeterStyle(Display *dpy, XrmValuePtr args,
69 Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
70 XtPointer *data);
71 static void CheckSetRenderTable(Widget wid,
72 int offset,
73 XrmValue *value);
74
75
76 static XtResource resources[] =
77 {
78 {
79 XmNcompleteValue, XmCCompleteValue,
80 XtRInt,
sizeof(
int),
81 XtOffset(XmLProgressWidget, progress.completeValue),
82 XtRImmediate, (
caddr_t)
100
83 },
84 {
85 XmNnumBoxes, XmCNumBoxes,
86 XtRInt,
sizeof(
int),
87 XtOffset(XmLProgressWidget, progress.numBoxes),
88 XtRImmediate, (
caddr_t)
10
89 },
90 {
91 XmNvalue, XmCValue,
92 XtRInt,
sizeof(
int),
93 XtOffset(XmLProgressWidget, progress.value),
94 XtRImmediate, (
caddr_t)
0
95 },
96 {
97 "pri.vate",
"Pri.vate",XmRBoolean,
98 sizeof(Boolean), XtOffset(XmLProgressWidget, progress.check_set_render_table),
99 XmRImmediate, (XtPointer) False
100 },
101 {
102 XmNfontList, XmCFontList,
103 XmRFontList,
sizeof(XmFontList),
104 XtOffset(XmLProgressWidget, progress.renderTable),
105 XmRCallProc, (XtPointer)CheckSetRenderTable,
106 },
107 {
108 XmNrenderTable, XmCRenderTable,
109 XmRRenderTable,
sizeof(XmRenderTable),
110 XtOffset(XmLProgressWidget, progress.renderTable),
111 XmRCallProc, (XtPointer)CheckSetRenderTable,
112 },
113 {
114 XmNmeterStyle, XmCMeterStyle,
115 XmRMeterStyle,
sizeof(
unsigned char),
116 XtOffset(XmLProgressWidget, progress.meterStyle),
117 XmRImmediate, (XtPointer)XmMETER_BAR,
118 },
119 {
120 XmNshowTime, XmCShowTime,
121 XmRBoolean,
sizeof(Boolean),
122 XtOffset(XmLProgressWidget, progress.showTime),
123 XmRImmediate, (XtPointer)False
124 },
125 {
126 XmNshowPercentage, XmCShowPercentage,
127 XmRBoolean,
sizeof(Boolean),
128 XtOffset(XmLProgressWidget, progress.showPercentage),
129 XmRImmediate, (XtPointer)True
130 }
131 };
132
133 XmLProgressClassRec xmlProgressClassRec =
134 {
135 {
136 (WidgetClass)&xmPrimitiveClassRec,
137 "XmLProgress",
138 sizeof(XmLProgressRec),
139 ClassInitialize,
140 NULL,
141 FALSE,
142 (XtInitProc)Initialize,
143 NULL,
144 (XtRealizeProc)Realize,
145 NULL,
146 0,
147 resources,
148 XtNumber(resources),
149 NULLQUARK,
150 TRUE,
151 FALSE,
152 TRUE,
153 TRUE,
154 (XtWidgetProc)Destroy,
155 (XtWidgetProc)Resize,
156 (XtExposeProc)Redisplay,
157 (XtSetValuesFunc)SetValues,
158 NULL,
159 XtInheritSetValuesAlmost,
160 NULL,
161 NULL,
162 XtVersion,
163 NULL,
164 XtInheritTranslations,
165 NULL,
166 NULL,
167 NULL,
168 },
169 {
170 (XtWidgetProc)_XtInherit,
171 (XtWidgetProc)_XtInherit,
172 XtInheritTranslations,
173 NULL,
174 NULL,
175 0,
176 NULL,
177 },
178 {
179 0,
180 }
181 };
182
183 WidgetClass xmlProgressWidgetClass = (WidgetClass)&xmlProgressClassRec;
184
185 static void
186 CheckSetRenderTable(Widget wid,
187 int offset,
188 XrmValue *value)
189 {
190 XmLProgressWidget lw = (XmLProgressWidget)wid;
191
192
193 if (lw->progress.check_set_render_table)
194 value->addr =
NULL;
195 else {
196 lw->progress.check_set_render_table = True;
197 value->addr = (
char*)&(lw->progress.renderTable);
198 }
199
200 }
201
202 static void
203 ClassInitialize(
void)
204 {
205 XmLInitialize();
206
207 XtSetTypeConverter(XmRString, XmRMeterStyle, CvtStringToMeterStyle,
208 0,
0, XtCacheNone,
0);
209 }
210
211 static void
212 Initialize(Widget reqW,
213 Widget newW,
214 ArgList args,
215 Cardinal *narg)
216 {
217 XmLProgressWidget p;
218
219 p = (XmLProgressWidget)newW;
220
221 if (!p->core.width)
222 p->core.width =
200;
223 if (!p->core.height)
224 p->core.height =
30;
225
226 p->progress.gc =
0;
227 p->progress.startTime = time(
0);
228 CopyRenderTable(p);
229 if (p->progress.completeValue <
1)
230 {
231 XmLWarning(newW,
"Initialize() - complete value can''t be < 1");
232 p->progress.completeValue =
1;
233 }
234 if (p->progress.numBoxes <
1)
235 {
236 XmLWarning(newW,
"Initialize() - number of boxes can''t be < 1");
237 p->progress.numBoxes =
1;
238 }
239 if (p->progress.value <
0)
240 {
241 XmLWarning(newW,
"Initialize() - value can''t be < 0");
242 p->progress.value =
0;
243 }
244 if (p->progress.value > p->progress.completeValue)
245 {
246 XmLWarning(newW,
"Initialize() - value can''t be > completeValue");
247 p->progress.value = p->progress.completeValue;
248 }
249 XtVaSetValues(newW, XmNtraversalOn, False,
NULL);
250 }
251
252 static void
253 Resize(Widget w)
254 {
255 Display *dpy;
256 Window win;
257
258 if (!XtIsRealized(w))
259 return;
260 dpy = XtDisplay(w);
261 win = XtWindow(w);
262 XClearArea(dpy, win,
0,
0,
0,
0, True);
263 }
264
265 static void
266 Destroy(Widget w)
267 {
268 Display *dpy;
269 XmLProgressWidget p;
270
271 p = (XmLProgressWidget)w;
272 dpy = XtDisplay(w);
273 if (p->progress.gc)
274 {
275 XFreeGC(dpy, p->progress.gc);
276 XFreeFont(dpy, p->progress.fallbackFont);
277 }
278 XmRenderTableFree(p->progress.renderTable);
279 }
280
281 static void
282 Realize(Widget w,
283 XtValueMask *valueMask,
284 XSetWindowAttributes *attr)
285 {
286 XmLProgressWidget p;
287 Display *dpy;
288 WidgetClass superClass;
289 XtRealizeProc realize;
290 XGCValues values;
291
292
293 p = (XmLProgressWidget)w;
294 dpy = XtDisplay(p);
295 superClass = xmlProgressWidgetClass->core_class.superclass;
296 realize = superClass->core_class.realize;
297 (*realize)(w, valueMask, attr);
298
299 if (!p->progress.gc)
300 {
301 p->progress.fallbackFont = XLoadQueryFont(dpy,
"fixed");
302 values.font = p->progress.fallbackFont->fid;
303 p->progress.gc = XCreateGC(dpy, XtWindow(p), GCFont, &values);
304 }
305 }
306
307 static void
308 Redisplay(Widget w,
309 XEvent *event,
310 Region region)
311 {
312 XmLProgressWidget p;
313 Display *dpy;
314 Window win;
315 XRectangle rect;
316 int st;
317
318 if (!XtIsRealized(w) || !w->core.visible)
319 return;
320
321 p = (XmLProgressWidget)w;
322 dpy = XtDisplay(w);
323 win = XtWindow(w);
324 st = p->primitive.shadow_thickness;
325 rect.x = st;
326 rect.y = st;
327 rect.width = p->core.width - st *
2;
328 rect.height = p->core.height - st *
2;
329
330 if (p->progress.meterStyle == XmMETER_BAR)
331 DrawBarMeter(p, &rect);
332 else if (p->progress.meterStyle == XmMETER_BOXES)
333 DrawBoxesMeter(p, &rect);
334
335 #ifdef MOTIF11
336 _XmDrawShadow(dpy, win,
337 p->primitive.bottom_shadow_GC,
338 p->primitive.top_shadow_GC,
339 p->primitive.shadow_thickness,
340 0,
0, p->core.width, p->core.height);
341 #else
342 _XmDrawShadows(dpy, win,
343 p->primitive.top_shadow_GC,
344 p->primitive.bottom_shadow_GC,
345 0,
0, p->core.width, p->core.height,
346 p->primitive.shadow_thickness,
347 XmSHADOW_IN);
348 #endif
349 }
350
351 static void
352 DrawBoxesMeter(XmLProgressWidget p,
353 XRectangle *rect)
354 {
355 Display *dpy;
356 Window win;
357 int i, j, st, nb, x1, x2;
358
359 dpy = XtDisplay(p);
360 win = XtWindow(p);
361 st = p->primitive.shadow_thickness;
362 nb = p->progress.numBoxes;
363 if (nb * st *
2 > (
int)rect->width)
364 return;
365
366 if (p->progress.completeValue)
367 j = (
int)((
long)nb * (
long)p->progress.value /
368 (
long)p->progress.completeValue);
369 else
370 j =
0;
371 x2 =
0;
372 for (i =
0; i < nb; i++)
373 {
374 if (i < j)
375 XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
376 else
377 XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
378 x1 = x2;
379 if (i == nb -
1)
380 x2 = rect->width;
381 else
382 x2 = ((
int)rect->width * (i +
1)) / nb;
383 XFillRectangle(dpy, win, p->progress.gc,
384 rect->x + x1 + st, rect->y + st,
385 x2 - x1 - st *
2, rect->height - st *
2);
386 #ifdef MOTIF11
387 _XmDrawShadow(dpy, win,
388 p->primitive.bottom_shadow_GC,
389 p->primitive.top_shadow_GC,
390 p->primitive.shadow_thickness,
391 rect->x + x1, rect->y,
392 x2 - x1, rect->height);
393 #else
394 _XmDrawShadows(dpy, win,
395 p->primitive.top_shadow_GC,
396 p->primitive.bottom_shadow_GC,
397 rect->x + x1, rect->y,
398 x2 - x1, rect->height,
399 p->primitive.shadow_thickness,
400 XmSHADOW_IN);
401 #endif
402 }
403 }
404
405 static void
406 DrawBarMeter(XmLProgressWidget p,
407 XRectangle *rect)
408 {
409 Display *dpy;
410 Window win;
411 int timeLeft, timeSoFar;
412 time_t currentTime;
413 XmString str;
414 Dimension strWidth, strHeight;
415 XRectangle lRect, rRect;
416 int percent;
417 char c[
10];
418 long l;
419
420 dpy = XtDisplay(p);
421 win = XtWindow(p);
422
423
424 if (p->progress.completeValue)
425 l = (
long)rect->width * (
long)p->progress.value /
426 (
long)p->progress.completeValue;
427 else
428 l =
0;
429 lRect.x = rect->x;
430 lRect.y = rect->y;
431 lRect.width = (Dimension)l;
432 lRect.height = rect->height;
433 XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
434 XFillRectangle(dpy, win, p->progress.gc, lRect.x, lRect.y,
435 lRect.width, lRect.height);
436
437
438 rRect.x = rect->x + (
int)l;
439 rRect.y = rect->y;
440 rRect.width = rect->width - (Dimension)l;
441 rRect.height = rect->height;
442 XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
443 XFillRectangle(dpy, win, p->progress.gc, rRect.x, rRect.y,
444 rRect.width, rRect.height);
445
446 if (p->progress.completeValue)
447 percent = (
int)(((
long)p->progress.value *
100) /
448 (
long)p->progress.completeValue);
449 else
450 percent =
0;
451
452
453 sprintf(c,
"%d%c", percent,
'%');
454 str = XmStringCreateSimple(c);
455 XmStringExtent(p->progress.renderTable, str, &strWidth, &strHeight);
456 if (p->progress.showPercentage)
457 DrawString(p, str, rect->x + rect->width /
2 - (
int)strWidth /
2,
458 rect->y + rect->height /
2 - (
int)strHeight /
2, strWidth,
459 &lRect, &rRect);
460 XmStringFree(str);
461
462
463 currentTime = time(
0);
464 timeSoFar = (
int)(currentTime - p->progress.startTime);
465 if (p->progress.showTime && p->progress.value &&
466 p->progress.value != p->progress.completeValue && timeSoFar)
467 {
468 TimeStr(c, timeSoFar);
469 str = XmStringCreateSimple(c);
470 XmStringExtent(p->progress.renderTable, str,
471 &strWidth, &strHeight);
472 DrawString(p, str, rect->x +
5, rect->y + rect->height /
2 -
473 (
int)strHeight /
2, strWidth, &lRect, &rRect);
474 XmStringFree(str);
475 }
476
477
478 timeLeft =
0;
479 if (percent)
480 timeLeft = (timeSoFar *
100 / percent) - timeSoFar;
481 if (p->progress.showTime && percent && percent !=
100 && timeLeft)
482 {
483 TimeStr(c, timeLeft);
484 str = XmStringCreateSimple(c);
485 XmStringExtent(p->progress.renderTable, str,
486 &strWidth, &strHeight);
487 DrawString(p, str, rect->x + rect->width - strWidth -
5,
488 rect->y + rect->height /
2 - (
int)strHeight /
2,
489 strWidth, &lRect, &rRect);
490 XmStringFree(str);
491 }
492 }
493
494 static void
495 DrawString(XmLProgressWidget p,
496 XmString str,
497 int x,
498 int y,
499 int strWidth,
500 XRectangle *lRect,
501 XRectangle *rRect)
502 {
503 Display *dpy;
504 Window win;
505
506 dpy = XtDisplay(p);
507 win = XtWindow(p);
508 if (lRect->width && lRect->height)
509 {
510 XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
511 XSetClipRectangles(dpy, p->progress.gc,
0,
0, lRect,
1, Unsorted);
512 XmStringDraw(dpy, win, p->progress.renderTable, str,
513 p->progress.gc, x, y, strWidth, XmALIGNMENT_BEGINNING,
514 XmSTRING_DIRECTION_L_TO_R,
0);
515 XSetClipMask(dpy, p->progress.gc, None);
516 }
517 if (rRect->width && rRect->height)
518 {
519 XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
520 XSetClipRectangles(dpy, p->progress.gc,
0,
0, rRect,
1, Unsorted);
521 XmStringDraw(dpy, win, p->progress.renderTable, str,
522 p->progress.gc, x, y, strWidth, XmALIGNMENT_BEGINNING,
523 XmSTRING_DIRECTION_L_TO_R,
0);
524 XSetClipMask(dpy, p->progress.gc, None);
525 }
526 }
527
528 static void
529 TimeStr(
char *c,
530 int seconds)
531 {
532 int h, m, s;
533
534 s = seconds;
535 m = s /
60;
536 s -= m *
60;
537 h = m /
60;
538 m -= h *
60;
539 if (h >
99)
540 h =
99;
541 if (h >
0 && m <
10)
542 sprintf(c,
"%d:0%d hr", h, m);
543 else if (h >
0)
544 sprintf(c,
"%d:%d hr", h, m);
545 else if (m >
0 && s <
10)
546 sprintf(c,
"%d:0%d min", m, s);
547 else if (m >
0)
548 sprintf(c,
"%d:%d min", m, s);
549 else
550 sprintf(c,
"%d sec", s);
551 }
552
553 static Boolean
554 SetValues(Widget curW,
555 Widget reqW,
556 Widget newW,
557 ArgList args,
558 Cardinal *narg)
559 {
560 XmLProgressWidget cur, p;
561
562 cur = (XmLProgressWidget)curW;
563 p = (XmLProgressWidget)newW;
564 if (p->progress.value ==
0)
565 p->progress.startTime = time(
0);
566 if (p->progress.completeValue <
1)
567 {
568 XmLWarning(newW,
"SetValues() - complete value can''t be < 1");
569 p->progress.completeValue =
1;
570 }
571 if (p->progress.numBoxes <
1)
572 {
573 XmLWarning(newW,
"SetValues() - number of boxes can''t be < 1");
574 p->progress.numBoxes =
1;
575 }
576 if (p->progress.value <
0)
577 {
578 XmLWarning(newW,
"SetValues() - value can''t be < 0");
579 p->progress.value =
0;
580 }
581 if (p->progress.value > p->progress.completeValue)
582 {
583 XmLWarning(newW,
"SetValues() - value can''t be > completeValue");
584 p->progress.value = p->progress.completeValue;
585 }
586 if (p->progress.renderTable != cur->progress.renderTable)
587 {
588 XmRenderTableFree(cur->progress.renderTable);
589 CopyRenderTable(p);
590 }
591
592
593 if (p->core.background_pixel != cur->core.background_pixel ||
594 p->primitive.foreground != cur->primitive.foreground ||
595 p->progress.value != cur->progress.value ||
596 p->progress.completeValue != cur->progress.completeValue ||
597 p->progress.renderTable != cur->progress.renderTable ||
598 p->progress.showTime != cur->progress.showTime ||
599 p->progress.showPercentage != cur->progress.showPercentage ||
600 p->progress.meterStyle != cur->progress.meterStyle ||
601 p->progress.numBoxes != cur->progress.numBoxes ||
602 p->primitive.shadow_thickness != cur->primitive.shadow_thickness)
603 {
604 Redisplay(newW,
0,
0);
605 XFlush(XtDisplay(newW));
606 XmUpdateDisplay(newW);
607 }
608 return FALSE;
609 }
610
611 static void
612 CopyRenderTable(XmLProgressWidget p)
613 {
614 if (!p->progress.renderTable)
615 p->progress.renderTable = XmLRenderTableCopyDefault((Widget)p);
616 else
617 p->progress.renderTable = XmRenderTableCopy(p->progress.renderTable,
NULL,
0);
618 if (!p->progress.renderTable)
619 XmLWarning((Widget)p,
"- fatal error - font list NULL");
620 }
621
622 static Boolean
623 CvtStringToMeterStyle(Display *dpy,
624 XrmValuePtr args,
625 Cardinal *narg,
626 XrmValuePtr fromVal,
627 XrmValuePtr toVal,
628 XtPointer *data)
629 {
630 static XmLStringToUCharMap map[] =
631 {
632 {
"METER_BAR", XmMETER_BAR },
633 {
"METER_BOXES", XmMETER_BOXES },
634 {
0,
0 },
635 };
636
637 return XmLCvtStringToUChar(dpy,
"XmRMeterStyle", map, fromVal, toVal);
638 }
639
640
641
642
643
644 Widget
645 XmLCreateProgress(Widget parent,
646 char *name,
647 ArgList arglist,
648 Cardinal argcount)
649 {
650 return XtCreateWidget(name, xmlProgressWidgetClass, parent,
651 arglist, argcount);
652 }
653
654
655