fixed many bugs, removed linked list
[wmaker-crm.git] / WINGs / wprogressindicator.c
blob14a762c7cb7a460204295a351c32bb4d9adb819d
1 /*
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
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;
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 #define SHOW_PROGRESS_TICKS_ONLY
29 static void didResizeProgressIndicator();
32 W_ViewDelegate _ProgressIndicatorDelegate = {
33 NULL,
34 NULL,
35 didResizeProgressIndicator,
36 NULL,
37 NULL
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);
53 WMProgressIndicator*
54 WMCreateProgressIndicator(WMWidget *parent)
56 ProgressIndicator *pPtr;
57 W_Screen *scrPtr = W_VIEW(parent)->screen;
59 pPtr = wmalloc(sizeof(ProgressIndicator));
60 memset(pPtr, 0, sizeof(ProgressIndicator));
62 pPtr->widgetClass = WC_ProgressIndicator;
64 pPtr->view = W_CreateView(W_VIEW(parent));
65 if (!pPtr->view) {
66 free(pPtr);
67 return NULL;
70 pPtr->view->self = pPtr;
72 pPtr->view->delegate = &_ProgressIndicatorDelegate;
74 WMCreateEventHandler(pPtr->view, ExposureMask|StructureNotifyMask,
75 handleEvents, pPtr);
78 W_ResizeView(pPtr->view, DEFAULT_PROGRESS_INDICATOR_WIDTH,
79 DEFAULT_PROGRESS_INDICATOR_HEIGHT);
81 /* Initialize ProgressIndicator Values */
82 pPtr->value = 0;
83 pPtr->minValue = 0;
84 pPtr->maxValue = 100;
86 WMAddNotificationObserver(realizeObserver, pPtr,
87 WMViewRealizedNotification, pPtr->view);
89 return pPtr;
93 void
94 WMSetProgressIndicatorMinValue(WMProgressIndicator *progressindicator, int value)
96 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
98 progressindicator->minValue = value;
99 if (progressindicator->value < value) {
100 progressindicator->value = value;
101 if (progressindicator->view->flags.mapped) {
102 paintProgressIndicator(progressindicator);
108 void
109 WMSetProgressIndicatorMaxValue(WMProgressIndicator *progressindicator, int value)
111 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
113 progressindicator->maxValue = value;
114 if (progressindicator->value > value) {
115 progressindicator->value = value;
116 if (progressindicator->view->flags.mapped) {
117 paintProgressIndicator(progressindicator);
123 void
124 WMSetProgressIndicatorValue(WMProgressIndicator *progressindicator, int value)
126 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
128 progressindicator->value = value;
130 /* Check if value is within min/max-range */
131 if (progressindicator->minValue > value)
132 progressindicator->value = progressindicator->minValue;
134 if (progressindicator->maxValue < value)
135 progressindicator->value = progressindicator->maxValue;
138 if (progressindicator->view->flags.mapped) {
139 paintProgressIndicator(progressindicator);
145 WMGetProgressIndicatorMinValue(WMProgressIndicator *progressindicator)
147 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
149 return progressindicator->minValue;
154 WMGetProgressIndicatorMaxValue(WMProgressIndicator *progressindicator)
156 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
158 return progressindicator->maxValue;
163 WMGetProgressIndicatorValue(WMProgressIndicator *progressindicator)
165 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
167 return progressindicator->value;
171 static void
172 realizeProgressIndicator(ProgressIndicator *pPtr)
174 W_RealizeView(pPtr->view);
178 static void
179 didResizeProgressIndicator(W_ViewDelegate *self, WMView *view)
181 WMProgressIndicator *pPtr = (WMProgressIndicator*)view->self;
182 int width = pPtr->view->size.width;
183 int height = pPtr->view->size.height;
185 assert(width > 0);
186 assert(height > 0);
190 static void
191 paintProgressIndicator(ProgressIndicator *pPtr)
193 W_Screen *scr = pPtr->view->screen;
194 GC bgc;
195 GC wgc;
196 GC lgc;
197 GC dgc;
198 WMSize size = pPtr->view->size;
199 int perc, w, h;
200 double unit, i;
201 Pixmap buffer;
203 bgc = WMColorGC(scr->black);
204 wgc = WMColorGC(scr->white);
205 lgc = WMColorGC(scr->gray);
206 dgc = WMColorGC(scr->darkGray);
208 unit = (double)(size.width - 3.0) / 100;
210 buffer = XCreatePixmap(scr->display, pPtr->view->window,
211 size.width, size.height, scr->depth);
213 XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width, size.height);
215 /* Calculate size of Progress to draw and paint ticks*/
216 perc = (pPtr->value - pPtr->minValue) * 100 / (pPtr->maxValue - pPtr->minValue);
218 w = (int)((double)(perc * unit));
219 h = size.height - 2;
221 if (w > (size.width - 3))
222 w = size.width - 3;
224 if (w > 0) {
225 XFillRectangle(scr->display, buffer, lgc, 2, 1, w, h);
226 XFillRectangle(scr->display, buffer, scr->stippleGC, 2, 1, w, h);
227 W_DrawRelief(scr, buffer, 2, 1, w, h, WRFlat);
229 /* Draw Progress Marks */
230 i=(5.0*unit);
232 #ifdef SHOW_PROGRESS_TICKS_ONLY
233 while((int)i<w+5) {
234 #else
235 while ((int)i < (size.width - 3)) {
236 #endif
237 XDrawLine(scr->display, buffer, dgc, (int)i+2, h-1, i+2, h-3);
239 i+=(5.0*unit);
241 #ifdef SHOW_PROGRESS_TICKS_ONLY
242 if((int)i>=w)
243 break;
244 #endif
246 XDrawLine(scr->display, buffer, dgc, (int)i+2, h-1, i+2, h-6);
248 i+=(5.0*unit);
252 XDrawLine(scr->display, buffer, bgc, w+2, 1, w+2, h+1);
253 XDrawLine(scr->display, buffer, lgc, 2, h, w+2, h);
256 XDrawLine(scr->display, buffer, dgc, 0, 0, 0, size.height-1);
257 XDrawLine(scr->display, buffer, dgc, 0, 0, size.width, 0);
258 XDrawLine(scr->display, buffer, bgc, 1, 1, 1, size.height-1);
259 XDrawLine(scr->display, buffer, bgc, 1, 1, size.width-1, 1);
261 XDrawLine(scr->display, buffer, wgc, size.width-1, 0,
262 size.width-1, size.height-1);
263 XDrawLine(scr->display, buffer, wgc, 0, size.height-1,
264 size.width-1, size.height-1);
266 XCopyArea(scr->display, buffer, pPtr->view->window, scr->copyGC, 0, 0,
267 size.width, size.height, 0, 0);
269 XFreePixmap(scr->display, buffer);
272 static void
273 handleEvents(XEvent *event, void *data)
275 ProgressIndicator *pPtr = (ProgressIndicator*)data;
277 CHECK_CLASS(data, WC_ProgressIndicator);
279 switch (event->type) {
280 case Expose:
281 if (event->xexpose.count!=0)
282 break;
283 paintProgressIndicator(pPtr);
284 break;
285 case DestroyNotify:
286 destroyProgressIndicator(pPtr);
287 break;
292 static void
293 destroyProgressIndicator(ProgressIndicator *pPtr)
295 WMRemoveNotificationObserver(pPtr);
297 free(pPtr);