2 * Original idea and implementation by Frederik Schueler <fr.schueler@netsurf.de>
3 * Rewritten by Pascal Hofstee <daeron@windowmaker.info>
4 * - Added options to set min/max values
5 * - centralized drawing into one pain function
10 typedef struct W_ProgressIndicator
{
21 #define DEFAULT_PROGRESS_INDICATOR_WIDTH 276
22 #define DEFAULT_PROGRESS_INDICATOR_HEIGHT 16
24 /* define if only the ticks within the progress region should be displayed */
25 #undef SHOW_PROGRESS_TICKS_ONLY
27 static void didResizeProgressIndicator(W_ViewDelegate
* self
, WMView
* view
);
29 W_ViewDelegate _ProgressIndicatorDelegate
= {
32 didResizeProgressIndicator
,
37 static void destroyProgressIndicator(ProgressIndicator
* pPtr
);
38 static void paintProgressIndicator(ProgressIndicator
* pPtr
);
39 static void handleEvents(XEvent
* event
, void *data
);
41 WMProgressIndicator
*WMCreateProgressIndicator(WMWidget
* parent
)
43 ProgressIndicator
*pPtr
;
45 pPtr
= wmalloc(sizeof(ProgressIndicator
));
47 pPtr
->widgetClass
= WC_ProgressIndicator
;
49 pPtr
->view
= W_CreateView(W_VIEW(parent
));
55 pPtr
->view
->self
= pPtr
;
57 pPtr
->view
->delegate
= &_ProgressIndicatorDelegate
;
59 WMCreateEventHandler(pPtr
->view
, ExposureMask
| StructureNotifyMask
, handleEvents
, pPtr
);
61 W_ResizeView(pPtr
->view
, DEFAULT_PROGRESS_INDICATOR_WIDTH
, DEFAULT_PROGRESS_INDICATOR_HEIGHT
);
63 /* Initialize ProgressIndicator Values */
71 void WMSetProgressIndicatorMinValue(WMProgressIndicator
* progressindicator
, int value
)
73 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
75 progressindicator
->minValue
= value
;
76 if (progressindicator
->value
< value
) {
77 progressindicator
->value
= value
;
78 if (progressindicator
->view
->flags
.mapped
) {
79 paintProgressIndicator(progressindicator
);
84 void WMSetProgressIndicatorMaxValue(WMProgressIndicator
* progressindicator
, int value
)
86 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
88 progressindicator
->maxValue
= value
;
89 if (progressindicator
->value
> value
) {
90 progressindicator
->value
= value
;
91 if (progressindicator
->view
->flags
.mapped
) {
92 paintProgressIndicator(progressindicator
);
97 void WMSetProgressIndicatorValue(WMProgressIndicator
* progressindicator
, int value
)
99 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
101 progressindicator
->value
= value
;
103 /* Check if value is within min/max-range */
104 if (progressindicator
->minValue
> value
)
105 progressindicator
->value
= progressindicator
->minValue
;
107 if (progressindicator
->maxValue
< value
)
108 progressindicator
->value
= progressindicator
->maxValue
;
110 if (progressindicator
->view
->flags
.mapped
) {
111 paintProgressIndicator(progressindicator
);
115 int WMGetProgressIndicatorMinValue(WMProgressIndicator
* progressindicator
)
117 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
119 return progressindicator
->minValue
;
122 int WMGetProgressIndicatorMaxValue(WMProgressIndicator
* progressindicator
)
124 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
126 return progressindicator
->maxValue
;
129 int WMGetProgressIndicatorValue(WMProgressIndicator
* progressindicator
)
131 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
133 return progressindicator
->value
;
136 static void didResizeProgressIndicator(W_ViewDelegate
* self
, WMView
* view
)
138 WMProgressIndicator
*pPtr
= (WMProgressIndicator
*) view
->self
;
139 int width
= pPtr
->view
->size
.width
;
140 int height
= pPtr
->view
->size
.height
;
142 /* Parameter not used, but tell the compiler that it is ok */
151 static void paintProgressIndicator(ProgressIndicator
* pPtr
)
153 W_Screen
*scr
= pPtr
->view
->screen
;
158 WMSize size
= pPtr
->view
->size
;
163 bgc
= WMColorGC(scr
->black
);
164 wgc
= WMColorGC(scr
->white
);
165 lgc
= WMColorGC(scr
->gray
);
166 dgc
= WMColorGC(scr
->darkGray
);
168 unit
= (double)(size
.width
- 3.0) / 100;
170 buffer
= XCreatePixmap(scr
->display
, pPtr
->view
->window
, size
.width
, size
.height
, scr
->depth
);
172 XFillRectangle(scr
->display
, buffer
, lgc
, 0, 0, size
.width
, size
.height
);
174 /* Calculate size of Progress to draw and paint ticks */
175 perc
= (pPtr
->value
- pPtr
->minValue
) * 100 / (pPtr
->maxValue
- pPtr
->minValue
);
177 w
= (int)((double)(perc
* unit
));
180 if (w
> (size
.width
- 3))
184 XFillRectangle(scr
->display
, buffer
, lgc
, 2, 1, w
, h
);
185 XFillRectangle(scr
->display
, buffer
, scr
->stippleGC
, 2, 1, w
, h
);
186 W_DrawRelief(scr
, buffer
, 2, 1, w
, h
, WRFlat
);
188 /* Draw Progress Marks */
191 #ifdef SHOW_PROGRESS_TICKS_ONLY
192 while ((int)i
< w
+ 5) {
194 while ((int)i
< (size
.width
- 3)) {
196 XDrawLine(scr
->display
, buffer
, dgc
, (int)i
+ 2, h
- 1, i
+ 2, h
- 3);
200 #ifdef SHOW_PROGRESS_TICKS_ONLY
205 XDrawLine(scr
->display
, buffer
, dgc
, (int)i
+ 2, h
- 1, i
+ 2, h
- 6);
211 XDrawLine(scr
->display
, buffer
, bgc
, w
+ 2, 1, w
+ 2, h
+ 1);
212 XDrawLine(scr
->display
, buffer
, lgc
, 2, h
, w
+ 2, h
);
214 XDrawLine(scr
->display
, buffer
, dgc
, 0, 0, 0, size
.height
- 1);
215 XDrawLine(scr
->display
, buffer
, dgc
, 0, 0, size
.width
, 0);
216 XDrawLine(scr
->display
, buffer
, bgc
, 1, 1, 1, size
.height
- 1);
217 XDrawLine(scr
->display
, buffer
, bgc
, 1, 1, size
.width
- 1, 1);
219 XDrawLine(scr
->display
, buffer
, wgc
, size
.width
- 1, 0, size
.width
- 1, size
.height
- 1);
220 XDrawLine(scr
->display
, buffer
, wgc
, 0, size
.height
- 1, size
.width
- 1, size
.height
- 1);
222 XCopyArea(scr
->display
, buffer
, pPtr
->view
->window
, scr
->copyGC
, 0, 0, size
.width
, size
.height
, 0, 0);
224 XFreePixmap(scr
->display
, buffer
);
227 static void handleEvents(XEvent
* event
, void *data
)
229 ProgressIndicator
*pPtr
= (ProgressIndicator
*) data
;
231 CHECK_CLASS(data
, WC_ProgressIndicator
);
233 switch (event
->type
) {
235 if (event
->xexpose
.count
!= 0)
237 paintProgressIndicator(pPtr
);
240 destroyProgressIndicator(pPtr
);
245 static void destroyProgressIndicator(ProgressIndicator
* pPtr
)
247 WMRemoveNotificationObserver(pPtr
);