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);