Fixes missing appicons after restarting Window Maker
[wmaker-crm.git] / WINGs / wprogressindicator.c
blob61b4e2e72907605525f0f7663d0218f0d044a342
1 /*
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
6 */
8 #include "WINGsP.h"
10 typedef struct W_ProgressIndicator {
11 W_Class widgetClass;
12 W_View *view;
14 int value;
15 int minValue;
16 int maxValue;
18 void *clientData;
19 } 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 = {
30 NULL,
31 NULL,
32 didResizeProgressIndicator,
33 NULL,
34 NULL
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));
50 if (!pPtr->view) {
51 wfree(pPtr);
52 return NULL;
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 */
64 pPtr->value = 0;
65 pPtr->minValue = 0;
66 pPtr->maxValue = 100;
68 return pPtr;
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 */
143 (void) self;
144 (void) width;
145 (void) height;
147 assert(width > 0);
148 assert(height > 0);
151 static void paintProgressIndicator(ProgressIndicator * pPtr)
153 W_Screen *scr = pPtr->view->screen;
154 GC bgc;
155 GC wgc;
156 GC lgc;
157 GC dgc;
158 WMSize size = pPtr->view->size;
159 int perc, w, h;
160 double unit, i;
161 Pixmap buffer;
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));
178 h = size.height - 2;
180 if (w > (size.width - 3))
181 w = size.width - 3;
183 if (w > 0) {
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 */
189 i = (5.0 * unit);
191 #ifdef SHOW_PROGRESS_TICKS_ONLY
192 while ((int)i < w + 5) {
193 #else
194 while ((int)i < (size.width - 3)) {
195 #endif
196 XDrawLine(scr->display, buffer, dgc, (int)i + 2, h - 1, i + 2, h - 3);
198 i += (5.0 * unit);
200 #ifdef SHOW_PROGRESS_TICKS_ONLY
201 if ((int)i >= w)
202 break;
203 #endif
205 XDrawLine(scr->display, buffer, dgc, (int)i + 2, h - 1, i + 2, h - 6);
207 i += (5.0 * unit);
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) {
234 case Expose:
235 if (event->xexpose.count != 0)
236 break;
237 paintProgressIndicator(pPtr);
238 break;
239 case DestroyNotify:
240 destroyProgressIndicator(pPtr);
241 break;
245 static void destroyProgressIndicator(ProgressIndicator * pPtr)
247 WMRemoveNotificationObserver(pPtr);
249 wfree(pPtr);