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();
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
));
46 memset(pPtr
, 0, sizeof(ProgressIndicator
));
48 pPtr
->widgetClass
= WC_ProgressIndicator
;
50 pPtr
->view
= W_CreateView(W_VIEW(parent
));
56 pPtr
->view
->self
= pPtr
;
58 pPtr
->view
->delegate
= &_ProgressIndicatorDelegate
;
60 WMCreateEventHandler(pPtr
->view
, ExposureMask
| StructureNotifyMask
, handleEvents
, pPtr
);
62 W_ResizeView(pPtr
->view
, DEFAULT_PROGRESS_INDICATOR_WIDTH
, DEFAULT_PROGRESS_INDICATOR_HEIGHT
);
64 /* Initialize ProgressIndicator Values */
72 void WMSetProgressIndicatorMinValue(WMProgressIndicator
* progressindicator
, int value
)
74 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
76 progressindicator
->minValue
= value
;
77 if (progressindicator
->value
< value
) {
78 progressindicator
->value
= value
;
79 if (progressindicator
->view
->flags
.mapped
) {
80 paintProgressIndicator(progressindicator
);
85 void WMSetProgressIndicatorMaxValue(WMProgressIndicator
* progressindicator
, int value
)
87 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
89 progressindicator
->maxValue
= value
;
90 if (progressindicator
->value
> value
) {
91 progressindicator
->value
= value
;
92 if (progressindicator
->view
->flags
.mapped
) {
93 paintProgressIndicator(progressindicator
);
98 void WMSetProgressIndicatorValue(WMProgressIndicator
* progressindicator
, int value
)
100 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
102 progressindicator
->value
= value
;
104 /* Check if value is within min/max-range */
105 if (progressindicator
->minValue
> value
)
106 progressindicator
->value
= progressindicator
->minValue
;
108 if (progressindicator
->maxValue
< value
)
109 progressindicator
->value
= progressindicator
->maxValue
;
111 if (progressindicator
->view
->flags
.mapped
) {
112 paintProgressIndicator(progressindicator
);
116 int WMGetProgressIndicatorMinValue(WMProgressIndicator
* progressindicator
)
118 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
120 return progressindicator
->minValue
;
123 int WMGetProgressIndicatorMaxValue(WMProgressIndicator
* progressindicator
)
125 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
127 return progressindicator
->maxValue
;
130 int WMGetProgressIndicatorValue(WMProgressIndicator
* progressindicator
)
132 CHECK_CLASS(progressindicator
, WC_ProgressIndicator
);
134 return progressindicator
->value
;
137 static void didResizeProgressIndicator(W_ViewDelegate
* self
, WMView
* view
)
139 WMProgressIndicator
*pPtr
= (WMProgressIndicator
*) view
->self
;
140 int width
= pPtr
->view
->size
.width
;
141 int height
= pPtr
->view
->size
.height
;
147 static void paintProgressIndicator(ProgressIndicator
* pPtr
)
149 W_Screen
*scr
= pPtr
->view
->screen
;
154 WMSize size
= pPtr
->view
->size
;
159 bgc
= WMColorGC(scr
->black
);
160 wgc
= WMColorGC(scr
->white
);
161 lgc
= WMColorGC(scr
->gray
);
162 dgc
= WMColorGC(scr
->darkGray
);
164 unit
= (double)(size
.width
- 3.0) / 100;
166 buffer
= XCreatePixmap(scr
->display
, pPtr
->view
->window
, size
.width
, size
.height
, scr
->depth
);
168 XFillRectangle(scr
->display
, buffer
, lgc
, 0, 0, size
.width
, size
.height
);
170 /* Calculate size of Progress to draw and paint ticks */
171 perc
= (pPtr
->value
- pPtr
->minValue
) * 100 / (pPtr
->maxValue
- pPtr
->minValue
);
173 w
= (int)((double)(perc
* unit
));
176 if (w
> (size
.width
- 3))
180 XFillRectangle(scr
->display
, buffer
, lgc
, 2, 1, w
, h
);
181 XFillRectangle(scr
->display
, buffer
, scr
->stippleGC
, 2, 1, w
, h
);
182 W_DrawRelief(scr
, buffer
, 2, 1, w
, h
, WRFlat
);
184 /* Draw Progress Marks */
187 #ifdef SHOW_PROGRESS_TICKS_ONLY
188 while ((int)i
< w
+ 5) {
190 while ((int)i
< (size
.width
- 3)) {
192 XDrawLine(scr
->display
, buffer
, dgc
, (int)i
+ 2, h
- 1, i
+ 2, h
- 3);
196 #ifdef SHOW_PROGRESS_TICKS_ONLY
201 XDrawLine(scr
->display
, buffer
, dgc
, (int)i
+ 2, h
- 1, i
+ 2, h
- 6);
207 XDrawLine(scr
->display
, buffer
, bgc
, w
+ 2, 1, w
+ 2, h
+ 1);
208 XDrawLine(scr
->display
, buffer
, lgc
, 2, h
, w
+ 2, h
);
210 XDrawLine(scr
->display
, buffer
, dgc
, 0, 0, 0, size
.height
- 1);
211 XDrawLine(scr
->display
, buffer
, dgc
, 0, 0, size
.width
, 0);
212 XDrawLine(scr
->display
, buffer
, bgc
, 1, 1, 1, size
.height
- 1);
213 XDrawLine(scr
->display
, buffer
, bgc
, 1, 1, size
.width
- 1, 1);
215 XDrawLine(scr
->display
, buffer
, wgc
, size
.width
- 1, 0, size
.width
- 1, size
.height
- 1);
216 XDrawLine(scr
->display
, buffer
, wgc
, 0, size
.height
- 1, size
.width
- 1, size
.height
- 1);
218 XCopyArea(scr
->display
, buffer
, pPtr
->view
->window
, scr
->copyGC
, 0, 0, size
.width
, size
.height
, 0, 0);
220 XFreePixmap(scr
->display
, buffer
);
223 static void handleEvents(XEvent
* event
, void *data
)
225 ProgressIndicator
*pPtr
= (ProgressIndicator
*) data
;
227 CHECK_CLASS(data
, WC_ProgressIndicator
);
229 switch (event
->type
) {
231 if (event
->xexpose
.count
!= 0)
233 paintProgressIndicator(pPtr
);
236 destroyProgressIndicator(pPtr
);
241 static void destroyProgressIndicator(ProgressIndicator
* pPtr
)
243 WMRemoveNotificationObserver(pPtr
);