- Updated WINGs/NEWS with info about hw the API changed how how things
[wmaker-crm.git] / WINGs / wprogressindicator.c
blob36d5de5c5866246557ad563407f0575ab7ca5a44
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 #undef 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 handleEvents(XEvent *event, void *data);
47 WMProgressIndicator*
48 WMCreateProgressIndicator(WMWidget *parent)
50 ProgressIndicator *pPtr;
52 pPtr = wmalloc(sizeof(ProgressIndicator));
53 memset(pPtr, 0, sizeof(ProgressIndicator));
55 pPtr->widgetClass = WC_ProgressIndicator;
57 pPtr->view = W_CreateView(W_VIEW(parent));
58 if (!pPtr->view) {
59 wfree(pPtr);
60 return NULL;
63 pPtr->view->self = pPtr;
65 pPtr->view->delegate = &_ProgressIndicatorDelegate;
67 WMCreateEventHandler(pPtr->view, ExposureMask|StructureNotifyMask,
68 handleEvents, pPtr);
71 W_ResizeView(pPtr->view, DEFAULT_PROGRESS_INDICATOR_WIDTH,
72 DEFAULT_PROGRESS_INDICATOR_HEIGHT);
74 /* Initialize ProgressIndicator Values */
75 pPtr->value = 0;
76 pPtr->minValue = 0;
77 pPtr->maxValue = 100;
79 return pPtr;
83 void
84 WMSetProgressIndicatorMinValue(WMProgressIndicator *progressindicator, int value)
86 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
88 progressindicator->minValue = value;
89 if (progressindicator->value < value) {
90 progressindicator->value = value;
91 if (progressindicator->view->flags.mapped) {
92 paintProgressIndicator(progressindicator);
98 void
99 WMSetProgressIndicatorMaxValue(WMProgressIndicator *progressindicator, int value)
101 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
103 progressindicator->maxValue = value;
104 if (progressindicator->value > value) {
105 progressindicator->value = value;
106 if (progressindicator->view->flags.mapped) {
107 paintProgressIndicator(progressindicator);
113 void
114 WMSetProgressIndicatorValue(WMProgressIndicator *progressindicator, int value)
116 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
118 progressindicator->value = value;
120 /* Check if value is within min/max-range */
121 if (progressindicator->minValue > value)
122 progressindicator->value = progressindicator->minValue;
124 if (progressindicator->maxValue < value)
125 progressindicator->value = progressindicator->maxValue;
128 if (progressindicator->view->flags.mapped) {
129 paintProgressIndicator(progressindicator);
135 WMGetProgressIndicatorMinValue(WMProgressIndicator *progressindicator)
137 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
139 return progressindicator->minValue;
144 WMGetProgressIndicatorMaxValue(WMProgressIndicator *progressindicator)
146 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
148 return progressindicator->maxValue;
153 WMGetProgressIndicatorValue(WMProgressIndicator *progressindicator)
155 CHECK_CLASS(progressindicator, WC_ProgressIndicator);
157 return progressindicator->value;
161 static void
162 didResizeProgressIndicator(W_ViewDelegate *self, WMView *view)
164 WMProgressIndicator *pPtr = (WMProgressIndicator*)view->self;
165 int width = pPtr->view->size.width;
166 int height = pPtr->view->size.height;
168 assert(width > 0);
169 assert(height > 0);
173 static void
174 paintProgressIndicator(ProgressIndicator *pPtr)
176 W_Screen *scr = pPtr->view->screen;
177 GC bgc;
178 GC wgc;
179 GC lgc;
180 GC dgc;
181 WMSize size = pPtr->view->size;
182 int perc, w, h;
183 double unit, i;
184 Pixmap buffer;
186 bgc = WMColorGC(scr->black);
187 wgc = WMColorGC(scr->white);
188 lgc = WMColorGC(scr->gray);
189 dgc = WMColorGC(scr->darkGray);
191 unit = (double)(size.width - 3.0) / 100;
193 buffer = XCreatePixmap(scr->display, pPtr->view->window,
194 size.width, size.height, scr->depth);
196 XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width, size.height);
198 /* Calculate size of Progress to draw and paint ticks*/
199 perc = (pPtr->value - pPtr->minValue) * 100 / (pPtr->maxValue - pPtr->minValue);
201 w = (int)((double)(perc * unit));
202 h = size.height - 2;
204 if (w > (size.width - 3))
205 w = size.width - 3;
207 if (w > 0) {
208 XFillRectangle(scr->display, buffer, lgc, 2, 1, w, h);
209 XFillRectangle(scr->display, buffer, scr->stippleGC, 2, 1, w, h);
210 W_DrawRelief(scr, buffer, 2, 1, w, h, WRFlat);
212 /* Draw Progress Marks */
213 i=(5.0*unit);
215 #ifdef SHOW_PROGRESS_TICKS_ONLY
216 while((int)i<w+5) {
217 #else
218 while ((int)i < (size.width - 3)) {
219 #endif
220 XDrawLine(scr->display, buffer, dgc, (int)i+2, h-1, i+2, h-3);
222 i+=(5.0*unit);
224 #ifdef SHOW_PROGRESS_TICKS_ONLY
225 if((int)i>=w)
226 break;
227 #endif
229 XDrawLine(scr->display, buffer, dgc, (int)i+2, h-1, i+2, h-6);
231 i+=(5.0*unit);
235 XDrawLine(scr->display, buffer, bgc, w+2, 1, w+2, h+1);
236 XDrawLine(scr->display, buffer, lgc, 2, h, w+2, h);
239 XDrawLine(scr->display, buffer, dgc, 0, 0, 0, size.height-1);
240 XDrawLine(scr->display, buffer, dgc, 0, 0, size.width, 0);
241 XDrawLine(scr->display, buffer, bgc, 1, 1, 1, size.height-1);
242 XDrawLine(scr->display, buffer, bgc, 1, 1, size.width-1, 1);
244 XDrawLine(scr->display, buffer, wgc, size.width-1, 0,
245 size.width-1, size.height-1);
246 XDrawLine(scr->display, buffer, wgc, 0, size.height-1,
247 size.width-1, size.height-1);
249 XCopyArea(scr->display, buffer, pPtr->view->window, scr->copyGC, 0, 0,
250 size.width, size.height, 0, 0);
252 XFreePixmap(scr->display, buffer);
256 static void
257 handleEvents(XEvent *event, void *data)
259 ProgressIndicator *pPtr = (ProgressIndicator*)data;
261 CHECK_CLASS(data, WC_ProgressIndicator);
263 switch (event->type) {
264 case Expose:
265 if (event->xexpose.count!=0)
266 break;
267 paintProgressIndicator(pPtr);
268 break;
269 case DestroyNotify:
270 destroyProgressIndicator(pPtr);
271 break;
276 static void
277 destroyProgressIndicator(ProgressIndicator *pPtr)
279 WMRemoveNotificationObserver(pPtr);
281 wfree(pPtr);