2 * Original idea and implementation by Frederik Schueler <fr.schueler@netsurf.de>
3 * Rewritten by Pascal Hofstee <daeron@windowmaker.org>
4 * - Added options to set min/max values
5 * - centralized drawing into one pain function
10 typedef struct W_ProgressIndicator
{
22 #define DEFAULT_PROGRESS_INDICATOR_WIDTH 276
23 #define DEFAULT_PROGRESS_INDICATOR_HEIGHT 16
25 /* define if only the ticks within the progress region should be displayed */
26 #undef SHOW_PROGRESS_TICKS_ONLY
29 static void didResizeProgressIndicator();
32 W_ViewDelegate _ProgressIndicatorDelegate
= {
35 didResizeProgressIndicator
,
41 static void destroyProgressIndicator(ProgressIndicator
*pPtr
);
42 static void paintProgressIndicator(ProgressIndicator
*pPtr
);
43 static void realizeProgressIndicator(ProgressIndicator
*pPtr
);
44 static void handleEvents(XEvent
*event
, void *data
);
46 static void realizeObserver(void *self
, WMNotification
*not) {
48 realizeProgressIndicator(self
);
54 WMCreateProgressIndicator(WMWidget
*parent
)
56 ProgressIndicator
*pPtr
;
58 pPtr
= wmalloc(sizeof(ProgressIndicator
));
59 memset(pPtr
, 0, sizeof(ProgressIndicator
));
61 pPtr
->widgetClass
= WC_ProgressIndicator
;
63 pPtr
->view
= W_CreateView(W_VIEW(parent
));
69 pPtr
->view
->self
= pPtr
;
71 pPtr
->view
->delegate
= &_ProgressIndicatorDelegate
;
73 WMCreateEventHandler(pPtr
->view
, ExposureMask
|StructureNotifyMask
,
77 W_ResizeView(pPtr
->view
, DEFAULT_PROGRESS_INDICATOR_WIDTH
,
78 DEFAULT_PROGRESS_INDICATOR_HEIGHT
);
80 /* Initialize ProgressIndicator Values */
85 WMAddNotificationObserver(realizeObserver
, pPtr
,
86 WMViewRealizedNotification
, pPtr
->view
);
93 WMSetProgressIndicatorMinValue(WMProgressIndicator
*progressindicator
, int value
)
95 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
97 progressindicator
->minValue
= value
;
98 if (progressindicator
->value
< value
) {
99 progressindicator
->value
= value
;
100 if (progressindicator
->view
->flags
.mapped
) {
101 paintProgressIndicator(progressindicator
);
108 WMSetProgressIndicatorMaxValue(WMProgressIndicator
*progressindicator
, int value
)
110 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
112 progressindicator
->maxValue
= value
;
113 if (progressindicator
->value
> value
) {
114 progressindicator
->value
= value
;
115 if (progressindicator
->view
->flags
.mapped
) {
116 paintProgressIndicator(progressindicator
);
123 WMSetProgressIndicatorValue(WMProgressIndicator
*progressindicator
, int value
)
125 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
127 progressindicator
->value
= value
;
129 /* Check if value is within min/max-range */
130 if (progressindicator
->minValue
> value
)
131 progressindicator
->value
= progressindicator
->minValue
;
133 if (progressindicator
->maxValue
< value
)
134 progressindicator
->value
= progressindicator
->maxValue
;
137 if (progressindicator
->view
->flags
.mapped
) {
138 paintProgressIndicator(progressindicator
);
144 WMGetProgressIndicatorMinValue(WMProgressIndicator
*progressindicator
)
146 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
148 return progressindicator
->minValue
;
153 WMGetProgressIndicatorMaxValue(WMProgressIndicator
*progressindicator
)
155 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
157 return progressindicator
->maxValue
;
162 WMGetProgressIndicatorValue(WMProgressIndicator
*progressindicator
)
164 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
166 return progressindicator
->value
;
171 realizeProgressIndicator(ProgressIndicator
*pPtr
)
173 W_RealizeView(pPtr
->view
);
178 didResizeProgressIndicator(W_ViewDelegate
*self
, WMView
*view
)
180 WMProgressIndicator
*pPtr
= (WMProgressIndicator
*)view
->self
;
181 int width
= pPtr
->view
->size
.width
;
182 int height
= pPtr
->view
->size
.height
;
190 paintProgressIndicator(ProgressIndicator
*pPtr
)
192 W_Screen
*scr
= pPtr
->view
->screen
;
197 WMSize size
= pPtr
->view
->size
;
202 bgc
= WMColorGC(scr
->black
);
203 wgc
= WMColorGC(scr
->white
);
204 lgc
= WMColorGC(scr
->gray
);
205 dgc
= WMColorGC(scr
->darkGray
);
207 unit
= (double)(size
.width
- 3.0) / 100;
209 buffer
= XCreatePixmap(scr
->display
, pPtr
->view
->window
,
210 size
.width
, size
.height
, scr
->depth
);
212 XFillRectangle(scr
->display
, buffer
, lgc
, 0, 0, size
.width
, size
.height
);
214 /* Calculate size of Progress to draw and paint ticks*/
215 perc
= (pPtr
->value
- pPtr
->minValue
) * 100 / (pPtr
->maxValue
- pPtr
->minValue
);
217 w
= (int)((double)(perc
* unit
));
220 if (w
> (size
.width
- 3))
224 XFillRectangle(scr
->display
, buffer
, lgc
, 2, 1, w
, h
);
225 XFillRectangle(scr
->display
, buffer
, scr
->stippleGC
, 2, 1, w
, h
);
226 W_DrawRelief(scr
, buffer
, 2, 1, w
, h
, WRFlat
);
228 /* Draw Progress Marks */
231 #ifdef SHOW_PROGRESS_TICKS_ONLY
234 while ((int)i
< (size
.width
- 3)) {
236 XDrawLine(scr
->display
, buffer
, dgc
, (int)i
+2, h
-1, i
+2, h
-3);
240 #ifdef SHOW_PROGRESS_TICKS_ONLY
245 XDrawLine(scr
->display
, buffer
, dgc
, (int)i
+2, h
-1, i
+2, h
-6);
251 XDrawLine(scr
->display
, buffer
, bgc
, w
+2, 1, w
+2, h
+1);
252 XDrawLine(scr
->display
, buffer
, lgc
, 2, h
, w
+2, h
);
255 XDrawLine(scr
->display
, buffer
, dgc
, 0, 0, 0, size
.height
-1);
256 XDrawLine(scr
->display
, buffer
, dgc
, 0, 0, size
.width
, 0);
257 XDrawLine(scr
->display
, buffer
, bgc
, 1, 1, 1, size
.height
-1);
258 XDrawLine(scr
->display
, buffer
, bgc
, 1, 1, size
.width
-1, 1);
260 XDrawLine(scr
->display
, buffer
, wgc
, size
.width
-1, 0,
261 size
.width
-1, size
.height
-1);
262 XDrawLine(scr
->display
, buffer
, wgc
, 0, size
.height
-1,
263 size
.width
-1, size
.height
-1);
265 XCopyArea(scr
->display
, buffer
, pPtr
->view
->window
, scr
->copyGC
, 0, 0,
266 size
.width
, size
.height
, 0, 0);
268 XFreePixmap(scr
->display
, buffer
);
272 handleEvents(XEvent
*event
, void *data
)
274 ProgressIndicator
*pPtr
= (ProgressIndicator
*)data
;
276 CHECK_CLASS(data
, WC_ProgressIndicator
);
278 switch (event
->type
) {
280 if (event
->xexpose
.count
!=0)
282 paintProgressIndicator(pPtr
);
285 destroyProgressIndicator(pPtr
);
292 destroyProgressIndicator(ProgressIndicator
*pPtr
)
294 WMRemoveNotificationObserver(pPtr
);