8 #undef STRICT_NEXT_BEHAVIOUR
11 typedef struct W_Slider
{
26 unsigned int continuous
:1;
28 unsigned int vertical
:1;
29 unsigned int dragging
:1;
36 #define SLIDER_LENGTH 20
39 static void resizeSlider();
42 W_ViewProcedureTable _SliderViewProcedures
= {
50 static void destroySlider(Slider
*sPtr
);
51 static void paintSlider(Slider
*sPtr
);
52 static void realizeSlider(Slider
*sPtr
);
54 static void handleEvents(XEvent
*event
, void *data
);
55 static void handleActionEvents(XEvent
*event
, void *data
);
59 realizeObserver(void *self
, WMNotification
*not)
67 WMCreateSlider(WMWidget
*parent
)
71 sPtr
= wmalloc(sizeof(Slider
));
72 memset(sPtr
, 0, sizeof(Slider
));
74 sPtr
->widgetClass
= WC_Slider
;
76 sPtr
->view
= W_CreateView(W_VIEW(parent
));
81 sPtr
->view
->self
= sPtr
;
83 WMCreateEventHandler(sPtr
->view
, ExposureMask
|StructureNotifyMask
,
87 WMCreateEventHandler(sPtr
->view
, ButtonPressMask
|ButtonReleaseMask
88 |EnterWindowMask
|LeaveWindowMask
|ButtonMotionMask
,
89 handleActionEvents
, sPtr
);
91 W_ResizeView(sPtr
->view
, 100, 16);
92 sPtr
->flags
.vertical
= 0;
97 sPtr
->flags
.continuous
= 1;
99 WMAddNotificationObserver(realizeObserver
, sPtr
,
100 WMViewRealizedNotification
, sPtr
->view
);
108 WMGetSliderMinValue(WMSlider
*slider
)
110 CHECK_CLASS(slider
, WC_Slider
);
112 return slider
->minValue
;
117 WMGetSliderMaxValue(WMSlider
*slider
)
119 CHECK_CLASS(slider
, WC_Slider
);
121 return slider
->maxValue
;
126 WMGetSliderValue(WMSlider
*slider
)
128 CHECK_CLASS(slider
, WC_Slider
);
130 return slider
->value
;
135 WMSetSliderMinValue(WMSlider
*slider
, int value
)
137 CHECK_CLASS(slider
, WC_Slider
);
139 slider
->minValue
= value
;
140 if (slider
->value
< value
) {
141 slider
->value
= value
;
142 if (slider
->view
->flags
.mapped
)
149 WMSetSliderMaxValue(WMSlider
*slider
, int value
)
151 CHECK_CLASS(slider
, WC_Slider
);
153 slider
->maxValue
= value
;
154 if (slider
->value
> value
) {
155 slider
->value
= value
;
156 if (slider
->view
->flags
.mapped
)
163 WMSetSliderValue(WMSlider
*slider
, int value
)
165 CHECK_CLASS(slider
, WC_Slider
);
167 if (value
< slider
->minValue
)
168 slider
->value
= slider
->minValue
;
169 else if (value
> slider
->maxValue
)
170 slider
->value
= slider
->maxValue
;
172 slider
->value
= value
;
174 if (slider
->view
->flags
.mapped
)
180 WMSetSliderContinuous(WMSlider
*slider
, Bool flag
)
182 CHECK_CLASS(slider
, WC_Slider
);
184 slider
->flags
.continuous
= flag
;
189 WMSetSliderAction(WMSlider
*slider
, WMAction
*action
, void *data
)
191 CHECK_CLASS(slider
, WC_Slider
);
193 slider
->action
= action
;
194 slider
->clientData
= data
;
199 makeKnobPixmap(Slider
*sPtr
)
202 WMScreen
*scr
= sPtr
->view
->screen
;
205 if (sPtr
->flags
.vertical
) {
206 w
= sPtr
->view
->size
.width
-2;
210 h
= sPtr
->view
->size
.height
-2;
213 pix
= XCreatePixmap(scr
->display
, sPtr
->view
->window
, w
, h
, scr
->depth
);
214 XFillRectangle(scr
->display
, pix
, W_GC(scr
->gray
), 0, 0, w
, h
);
216 if (sPtr
->flags
.vertical
) {
217 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 0, 0, 0, h
-3);
218 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 1, 0, 1, h
-3);
219 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), w
-2, 1, w
-2, h
/2-2);
220 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), w
-2, h
/2, w
-2, h
-2);
222 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 0, 0, w
-2, 0);
223 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), 1, h
/2-2, w
-3, h
/2-2);
224 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 0, h
/2-1, w
-3, h
/2-1);
225 XDrawLine(scr
->display
, pix
, W_GC(scr
->black
), w
-1, 0, w
-1, h
-2);
227 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), 0, h
-3, w
-2, h
-3);
228 XDrawLine(scr
->display
, pix
, W_GC(scr
->black
), 0, h
-2, w
-1, h
-2);
229 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), 0, h
-1, w
-1,h
-1);
231 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 0, 0, w
-3, 0);
233 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 0, 0, 0, h
-2);
234 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), 1, 0, 1, h
-3);
235 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), w
/2-2, 1, w
/2-2, h
-3);
236 XDrawLine(scr
->display
, pix
, W_GC(scr
->white
), w
/2-1, 0, w
/2-1, h
-3);
237 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), w
-3, 0, w
-3, h
-2);
238 XDrawLine(scr
->display
, pix
, W_GC(scr
->black
), w
-2, 0, w
-2, h
-2);
239 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), w
-1, 0, w
-1, h
-1);
241 XDrawLine(scr
->display
, pix
, W_GC(scr
->black
), 1, h
-1, w
/2+1, h
-1);
242 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), 1, h
-2, w
/2-2, h
-2);
243 XDrawLine(scr
->display
, pix
, W_GC(scr
->darkGray
), w
/2, h
-2, w
-3,h
-2);
244 XDrawLine(scr
->display
, pix
, W_GC(scr
->black
), 0, h
-1, w
-2, h
-1);
247 if (sPtr
->knobPixmap
)
248 XFreePixmap(scr
->display
, sPtr
->knobPixmap
);
249 sPtr
->knobPixmap
= pix
;
254 realizeSlider(Slider
*sPtr
)
256 W_RealizeView(sPtr
->view
);
258 makeKnobPixmap(sPtr
);
263 resizeSlider(Slider
*sPtr
, unsigned int width
, unsigned int height
)
268 W_ResizeView(sPtr
->view
, width
, height
);
270 if (width
> height
) {
271 if (sPtr
->flags
.vertical
) {
272 sPtr
->flags
.vertical
= 0;
273 if (sPtr
->view
->flags
.realized
)
274 makeKnobPixmap(sPtr
);
277 if (!sPtr
->flags
.vertical
) {
278 sPtr
->flags
.vertical
= 1;
279 if (sPtr
->view
->flags
.realized
)
280 makeKnobPixmap(sPtr
);
288 paintSlider(Slider
*sPtr
)
290 W_Screen
*scr
= sPtr
->view
->screen
;
294 WMSize size
= sPtr
->view
->size
;
298 #define MINV sPtr->minValue
299 #define MAXV sPtr->maxValue
300 #define POSV sPtr->value
302 bgc
= W_GC(scr
->black
);
303 wgc
= W_GC(scr
->white
);
304 lgc
= W_GC(scr
->gray
);
306 buffer
= XCreatePixmap(scr
->display
, sPtr
->view
->window
,
307 size
.width
, size
.height
, scr
->depth
);
308 XFillRectangle(scr
->display
, buffer
, lgc
, 0, 0, size
.width
, size
.height
);
309 XFillRectangle(scr
->display
, buffer
, scr
->stippleGC
, 0, 0, size
.width
,
312 if (sPtr
->flags
.vertical
) {
313 pos
= (size
.height
-2-SLIDER_LENGTH
)*(POSV
-MINV
)/(MAXV
-MINV
)+1;
315 XCopyArea(scr
->display
, sPtr
->knobPixmap
, buffer
,
316 scr
->copyGC
, 0, 0, size
.width
-2, SLIDER_LENGTH
, 1, pos
);
318 pos
= (size
.width
-2-SLIDER_LENGTH
)*(POSV
-MINV
)/(MAXV
-MINV
)+1;
320 XCopyArea(scr
->display
, sPtr
->knobPixmap
, buffer
,
321 scr
->copyGC
, 0, 0, SLIDER_LENGTH
, size
.height
, pos
, 1);
324 XDrawLine(scr
->display
, buffer
, bgc
, 0, 0, 0, size
.height
-1);
325 XDrawLine(scr
->display
, buffer
, bgc
, 0, 0, size
.width
, 0);
327 XDrawLine(scr
->display
, buffer
, wgc
, size
.width
-1, 0,
328 size
.width
-1, size
.height
-1);
329 XDrawLine(scr
->display
, buffer
, wgc
, 0, size
.height
-1,
330 size
.width
-1, size
.height
-1);
332 XCopyArea(scr
->display
, buffer
, sPtr
->view
->window
, scr
->copyGC
, 0, 0,
333 size
.width
, size
.height
, 0, 0);
334 XFreePixmap(scr
->display
, buffer
);
340 handleEvents(XEvent
*event
, void *data
)
342 Slider
*sPtr
= (Slider
*)data
;
344 CHECK_CLASS(data
, WC_Slider
);
347 switch (event
->type
) {
349 if (event
->xexpose
.count
!=0)
367 getSliderPart(Slider
*sPtr
, int x
, int y
)
371 WMSize size
= sPtr
->view
->size
;
374 if (sPtr
->flags
.vertical
) {
376 pos
= (size
.height
-2-SLIDER_LENGTH
)*(POSV
-MINV
)/(MAXV
-MINV
);
379 if (p
> pos
+ SLIDER_LENGTH
)
384 pos
= (size
.width
-2-SLIDER_LENGTH
)*(POSV
-MINV
)/(MAXV
-MINV
);
387 if (p
> pos
+ SLIDER_LENGTH
)
395 valueForMousePoint(Slider
*sPtr
, int x
, int y
)
397 WMSize size
= sPtr
->view
->size
;
400 if (sPtr
->flags
.vertical
) {
401 f
= (y
-SLIDER_LENGTH
/2)*(MAXV
-MINV
)/((int)size
.height
-2-SLIDER_LENGTH
);
403 f
= (x
-SLIDER_LENGTH
/2)*(MAXV
-MINV
)/((int)size
.width
-2-SLIDER_LENGTH
);
407 if (f
< sPtr
->minValue
)
409 else if (f
> sPtr
->maxValue
)
416 handleActionEvents(XEvent
*event
, void *data
)
418 WMSlider
*sPtr
= (Slider
*)data
;
420 CHECK_CLASS(data
, WC_Slider
);
423 switch (event
->type
) {
425 if (getSliderPart(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
)==KNOB_PART
)
426 sPtr
->flags
.dragging
= 1;
428 #ifdef STRICT_NEXT_BEHAVIOUR
429 sPtr
->flags
.dragging
= 1;
431 sPtr
->value
= valueForMousePoint(sPtr
, event
->xmotion
.x
,
437 tmp
= valueForMousePoint(sPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
438 if (tmp
< sPtr
->value
)
442 WMSetSliderValue(sPtr
, tmp
);
445 if (sPtr
->flags
.continuous
&& sPtr
->action
) {
446 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
452 if (!sPtr
->flags
.continuous
&& sPtr
->flags
.dragging
&& sPtr
->action
) {
453 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
455 sPtr
->flags
.dragging
= 0;
459 if (sPtr
->flags
.dragging
) {
460 sPtr
->value
= valueForMousePoint(sPtr
, event
->xmotion
.x
,
464 if (sPtr
->flags
.continuous
&& sPtr
->action
) {
465 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
475 destroySlider(Slider
*sPtr
)
477 if (sPtr
->knobPixmap
)
478 XFreePixmap(sPtr
->view
->screen
->display
, sPtr
->knobPixmap
);