1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 12:28:22 +01:00
Files
wmaker/WINGs/wslider.c
Christophe CURIS 708bc27e3f WINGs: Added explicit parameter list to function prototypes (Simple cases)
It is dangerous to let the compiler know about a function without
letting him know the arguments because he won't be able to report
invalid calls.

This patch concern the cases where adding the arguments did not
need other code change.
2013-05-12 01:01:20 +01:00

488 lines
12 KiB
C

#include "WINGsP.h"
#undef STRICT_NEXT_BEHAVIOUR
typedef struct W_Slider {
W_Class widgetClass;
WMView *view;
int minValue;
int maxValue;
int value;
Pixmap knobPixmap;
WMPixmap *backPixmap;
WMAction *action;
void *clientData;
int knobThickness;
struct {
unsigned int continuous:1;
unsigned int vertical:1;
unsigned int dragging:1;
} flags;
} Slider;
static void didResizeSlider(W_ViewDelegate * self, WMView * view);
W_ViewDelegate _SliderViewDelegate = {
NULL,
NULL,
didResizeSlider,
NULL,
NULL
};
static void destroySlider(Slider * sPtr);
static void paintSlider(Slider * sPtr);
static void handleEvents(XEvent * event, void *data);
static void handleActionEvents(XEvent * event, void *data);
static void makeKnobPixmap(Slider * sPtr);
static void realizeObserver(void *self, WMNotification * not)
{
makeKnobPixmap(self);
}
WMSlider *WMCreateSlider(WMWidget * parent)
{
Slider *sPtr;
sPtr = wmalloc(sizeof(Slider));
sPtr->widgetClass = WC_Slider;
sPtr->view = W_CreateView(W_VIEW(parent));
if (!sPtr->view) {
wfree(sPtr);
return NULL;
}
sPtr->view->self = sPtr;
sPtr->view->delegate = &_SliderViewDelegate;
WMCreateEventHandler(sPtr->view, ExposureMask | StructureNotifyMask, handleEvents, sPtr);
WMCreateEventHandler(sPtr->view, ButtonPressMask | ButtonReleaseMask
| EnterWindowMask | LeaveWindowMask | ButtonMotionMask, handleActionEvents, sPtr);
W_ResizeView(sPtr->view, 100, 16);
sPtr->flags.vertical = 0;
sPtr->minValue = 0;
sPtr->maxValue = 100;
sPtr->value = 50;
sPtr->knobThickness = 20;
sPtr->flags.continuous = 1;
WMAddNotificationObserver(realizeObserver, sPtr, WMViewRealizedNotification, sPtr->view);
return sPtr;
}
void WMSetSliderImage(WMSlider * sPtr, WMPixmap * pixmap)
{
if (sPtr->backPixmap)
WMReleasePixmap(sPtr->backPixmap);
sPtr->backPixmap = WMRetainPixmap(pixmap);
if (sPtr->view->flags.mapped) {
paintSlider(sPtr);
}
}
void WMSetSliderKnobThickness(WMSlider * sPtr, int thickness)
{
assert(thickness > 0);
sPtr->knobThickness = thickness;
if (sPtr->knobPixmap) {
makeKnobPixmap(sPtr);
}
if (sPtr->view->flags.mapped) {
paintSlider(sPtr);
}
}
int WMGetSliderMinValue(WMSlider * slider)
{
CHECK_CLASS(slider, WC_Slider);
return slider->minValue;
}
int WMGetSliderMaxValue(WMSlider * slider)
{
CHECK_CLASS(slider, WC_Slider);
return slider->maxValue;
}
int WMGetSliderValue(WMSlider * slider)
{
CHECK_CLASS(slider, WC_Slider);
return slider->value;
}
void WMSetSliderMinValue(WMSlider * slider, int value)
{
CHECK_CLASS(slider, WC_Slider);
slider->minValue = value;
if (slider->value < value) {
slider->value = value;
if (slider->view->flags.mapped)
paintSlider(slider);
}
}
void WMSetSliderMaxValue(WMSlider * slider, int value)
{
CHECK_CLASS(slider, WC_Slider);
slider->maxValue = value;
if (slider->value > value) {
slider->value = value;
if (slider->view->flags.mapped)
paintSlider(slider);
}
}
void WMSetSliderValue(WMSlider * slider, int value)
{
CHECK_CLASS(slider, WC_Slider);
if (value < slider->minValue)
slider->value = slider->minValue;
else if (value > slider->maxValue)
slider->value = slider->maxValue;
else
slider->value = value;
if (slider->view->flags.mapped)
paintSlider(slider);
}
void WMSetSliderContinuous(WMSlider * slider, Bool flag)
{
CHECK_CLASS(slider, WC_Slider);
slider->flags.continuous = ((flag == 0) ? 0 : 1);
}
void WMSetSliderAction(WMSlider * slider, WMAction * action, void *data)
{
CHECK_CLASS(slider, WC_Slider);
slider->action = action;
slider->clientData = data;
}
static void makeKnobPixmap(Slider * sPtr)
{
Pixmap pix;
WMScreen *scr = sPtr->view->screen;
int w, h;
if (sPtr->flags.vertical) {
w = sPtr->view->size.width - 2;
h = sPtr->knobThickness;
} else {
w = sPtr->knobThickness;
h = sPtr->view->size.height - 2;
}
pix = XCreatePixmap(scr->display, sPtr->view->window, w, h, scr->depth);
XFillRectangle(scr->display, pix, WMColorGC(scr->gray), 0, 0, w, h);
if (sPtr->knobThickness < 10) {
W_DrawRelief(scr, pix, 0, 0, w, h, WRRaised);
} else if (sPtr->flags.vertical) {
XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, 0, h - 3);
XDrawLine(scr->display, pix, WMColorGC(scr->white), 1, 0, 1, h - 3);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 2, 1, w - 2, h / 2 - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 2, h / 2, w - 2, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, w - 2, 0);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 1, h / 2 - 2, w - 3, h / 2 - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, h / 2 - 1, w - 3, h / 2 - 1);
XDrawLine(scr->display, pix, WMColorGC(scr->black), w - 1, 0, w - 1, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 0, h - 3, w - 2, h - 3);
XDrawLine(scr->display, pix, WMColorGC(scr->black), 0, h - 2, w - 1, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 0, h - 1, w - 1, h - 1);
} else {
XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, w - 3, 0);
XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, 0, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->white), 1, 0, 1, h - 3);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w / 2 - 2, 1, w / 2 - 2, h - 3);
XDrawLine(scr->display, pix, WMColorGC(scr->white), w / 2 - 1, 0, w / 2 - 1, h - 3);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 3, 0, w - 3, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->black), w - 2, 0, w - 2, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 1, 0, w - 1, h - 1);
XDrawLine(scr->display, pix, WMColorGC(scr->black), 1, h - 1, w / 2 + 1, h - 1);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 1, h - 2, w / 2 - 2, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w / 2, h - 2, w - 3, h - 2);
XDrawLine(scr->display, pix, WMColorGC(scr->black), 0, h - 1, w - 2, h - 1);
}
if (sPtr->knobPixmap)
XFreePixmap(scr->display, sPtr->knobPixmap);
sPtr->knobPixmap = pix;
}
static void didResizeSlider(W_ViewDelegate * self, WMView * view)
{
Slider *sPtr = (Slider *) view->self;
int width = sPtr->view->size.width;
int height = sPtr->view->size.height;
assert(width > 0);
assert(height > 0);
if (width > height) {
if (sPtr->flags.vertical) {
sPtr->flags.vertical = 0;
if (sPtr->view->flags.realized)
makeKnobPixmap(sPtr);
}
} else {
if (!sPtr->flags.vertical) {
sPtr->flags.vertical = 1;
if (sPtr->view->flags.realized)
makeKnobPixmap(sPtr);
}
}
}
static void paintSlider(Slider * sPtr)
{
W_Screen *scr = sPtr->view->screen;
GC bgc;
GC wgc;
GC lgc;
WMSize size = sPtr->view->size;
int pos;
Pixmap buffer;
#define MINV sPtr->minValue
#define MAXV sPtr->maxValue
#define POSV sPtr->value
bgc = WMColorGC(scr->black);
wgc = WMColorGC(scr->white);
lgc = WMColorGC(scr->gray);
buffer = XCreatePixmap(scr->display, sPtr->view->window, size.width, size.height, scr->depth);
if (sPtr->backPixmap) {
WMSize size = WMGetPixmapSize(sPtr->backPixmap);
XCopyArea(scr->display, WMGetPixmapXID(sPtr->backPixmap),
buffer, scr->copyGC, 0, 0, size.width, size.height, 1, 1);
} else {
XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width, size.height);
XFillRectangle(scr->display, buffer, scr->stippleGC, 0, 0, size.width, size.height);
}
if (sPtr->flags.vertical) {
pos = (size.height - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV) + 1;
/* draw knob */
XCopyArea(scr->display, sPtr->knobPixmap, buffer,
scr->copyGC, 0, 0, size.width - 2, sPtr->knobThickness, 1, pos);
} else {
pos = (size.width - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV) + 1;
/* draw knob */
XCopyArea(scr->display, sPtr->knobPixmap, buffer,
scr->copyGC, 0, 0, sPtr->knobThickness, size.height, pos, 1);
}
XDrawLine(scr->display, buffer, bgc, 0, 0, 0, size.height - 1);
XDrawLine(scr->display, buffer, bgc, 0, 0, size.width, 0);
XDrawLine(scr->display, buffer, wgc, size.width - 1, 0, size.width - 1, size.height - 1);
XDrawLine(scr->display, buffer, wgc, 0, size.height - 1, size.width - 1, size.height - 1);
XCopyArea(scr->display, buffer, sPtr->view->window, scr->copyGC, 0, 0, size.width, size.height, 0, 0);
XFreePixmap(scr->display, buffer);
}
static void handleEvents(XEvent * event, void *data)
{
Slider *sPtr = (Slider *) data;
CHECK_CLASS(data, WC_Slider);
switch (event->type) {
case Expose:
if (event->xexpose.count != 0)
break;
paintSlider(sPtr);
break;
case DestroyNotify:
destroySlider(sPtr);
break;
}
}
#define DECR_PART 1
#define KNOB_PART 2
#define INCR_PART 3
static int getSliderPart(Slider * sPtr, int x, int y)
{
int p;
int pos;
WMSize size = sPtr->view->size;
if (sPtr->flags.vertical) {
p = y;
pos = (size.height - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV);
if (p < pos)
return INCR_PART;
if (p > pos + sPtr->knobThickness)
return DECR_PART;
return KNOB_PART;
} else {
p = x;
pos = (size.width - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV);
if (p < pos)
return DECR_PART;
if (p > pos + sPtr->knobThickness)
return INCR_PART;
return KNOB_PART;
}
}
static int valueForMousePoint(Slider * sPtr, int x, int y)
{
WMSize size = sPtr->view->size;
int f;
if (sPtr->flags.vertical) {
f = (y - sPtr->knobThickness / 2) * (MAXV - MINV)
/ ((int)size.height - 2 - sPtr->knobThickness);
} else {
f = (x - sPtr->knobThickness / 2) * (MAXV - MINV)
/ ((int)size.width - 2 - sPtr->knobThickness);
}
f += sPtr->minValue;
if (f < sPtr->minValue)
f = sPtr->minValue;
else if (f > sPtr->maxValue)
f = sPtr->maxValue;
return f;
}
static void handleActionEvents(XEvent * event, void *data)
{
WMSlider *sPtr = (Slider *) data;
CHECK_CLASS(data, WC_Slider);
switch (event->type) {
case ButtonPress:
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp && !sPtr->flags.dragging) {
/* Wheel up */
if (sPtr->value + 1 <= sPtr->maxValue) {
WMSetSliderValue(sPtr, sPtr->value + 1);
if (sPtr->flags.continuous && sPtr->action) {
(*sPtr->action) (sPtr, sPtr->clientData);
}
}
} else if (event->xbutton.button == WINGsConfiguration.mouseWheelDown && !sPtr->flags.dragging) {
/* Wheel down */
if (sPtr->value - 1 >= sPtr->minValue) {
WMSetSliderValue(sPtr, sPtr->value - 1);
if (sPtr->flags.continuous && sPtr->action) {
(*sPtr->action) (sPtr, sPtr->clientData);
}
}
} else if (getSliderPart(sPtr, event->xbutton.x, event->xbutton.y)
== KNOB_PART)
sPtr->flags.dragging = 1;
else {
#ifdef STRICT_NEXT_BEHAVIOUR
sPtr->flags.dragging = 1;
sPtr->value = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
paintSlider(sPtr);
#else
int tmp;
if (event->xbutton.button == Button2) {
sPtr->flags.dragging = 1;
sPtr->value = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
paintSlider(sPtr);
} else {
tmp = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
if (tmp < sPtr->value)
tmp = sPtr->value - 1;
else
tmp = sPtr->value + 1;
WMSetSliderValue(sPtr, tmp);
}
#endif
if (sPtr->flags.continuous && sPtr->action) {
(*sPtr->action) (sPtr, sPtr->clientData);
}
}
break;
case ButtonRelease:
if (!sPtr->flags.continuous && sPtr->action) {
(*sPtr->action) (sPtr, sPtr->clientData);
}
sPtr->flags.dragging = 0;
break;
case MotionNotify:
if (sPtr->flags.dragging) {
sPtr->value = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
paintSlider(sPtr);
if (sPtr->flags.continuous && sPtr->action) {
(*sPtr->action) (sPtr, sPtr->clientData);
}
}
break;
}
}
static void destroySlider(Slider * sPtr)
{
if (sPtr->knobPixmap)
XFreePixmap(sPtr->view->screen->display, sPtr->knobPixmap);
if (sPtr->backPixmap)
WMReleasePixmap(sPtr->backPixmap);
WMRemoveNotificationObserver(sPtr);
wfree(sPtr);
}