/* * Copyright (c) 2008 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "slider.h" #include "window.h" #include "primitive.h" #include "gui_math.h" #define TOTSIZE(sl) (((sl)->type==AG_SLIDER_VERT) ? HEIGHT(sl) : WIDTH(sl)) AG_Slider * AG_SliderNew(void *parent, enum ag_slider_type type, Uint flags) { AG_Slider *sl; sl = Malloc(sizeof(AG_Slider)); AG_ObjectInit(sl, &agSliderClass); sl->type = type; sl->flags |= flags; if (flags & AG_SLIDER_HFILL) { AG_ExpandHoriz(sl); } if (flags & AG_SLIDER_VFILL) { AG_ExpandVert(sl); } AG_ObjectAttach(parent, sl); return (sl); } AG_Slider * AG_SliderNewInt(void *parent, enum ag_slider_type type, Uint flags, int *val, int *min, int *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindInt(sl, "value", val); } if (min != NULL) { AG_BindInt(sl, "min", min); } if (max != NULL) { AG_BindInt(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewIntR(void *parent, enum ag_slider_type type, Uint flags, int *val, int min, int max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindInt(sl, "value", val); } AG_SetInt(sl, "min", min); AG_SetInt(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewUint(void *parent, enum ag_slider_type type, Uint flags, Uint *val, Uint *min, Uint *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint(sl, "value", val); } if (min != NULL) { AG_BindUint(sl, "min", min); } if (max != NULL) { AG_BindUint(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewUintR(void *parent, enum ag_slider_type type, Uint flags, Uint *val, Uint min, Uint max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint(sl, "value", val); } AG_SetUint(sl, "min", min); AG_SetUint(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewUint8(void *parent, enum ag_slider_type type, Uint flags, Uint8 *val, Uint8 *min, Uint8 *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint8(sl, "value", val); } if (min != NULL) { AG_BindUint8(sl, "min", min); } if (max != NULL) { AG_BindUint8(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewUint8R(void *parent, enum ag_slider_type type, Uint flags, Uint8 *val, Uint8 min, Uint8 max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint8(sl, "value", val); } AG_SetUint8(sl, "min", min); AG_SetUint8(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewSint8(void *parent, enum ag_slider_type type, Uint flags, Sint8 *val, Sint8 *min, Sint8 *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindSint8(sl, "value", val); } if (min != NULL) { AG_BindSint8(sl, "min", min); } if (max != NULL) { AG_BindSint8(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewSint8R(void *parent, enum ag_slider_type type, Uint flags, Sint8 *val, Sint8 min, Sint8 max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindSint8(sl, "value", val); } AG_SetSint8(sl, "min", min); AG_SetSint8(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewUint16(void *parent, enum ag_slider_type type, Uint flags, Uint16 *val, Uint16 *min, Uint16 *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint16(sl, "value", val); } if (min != NULL) { AG_BindUint16(sl, "min", min); } if (max != NULL) { AG_BindUint16(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewUint16R(void *parent, enum ag_slider_type type, Uint flags, Uint16 *val, Uint16 min, Uint16 max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint16(sl, "value", val); } AG_SetUint16(sl, "min", min); AG_SetUint16(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewSint16(void *parent, enum ag_slider_type type, Uint flags, Sint16 *val, Sint16 *min, Sint16 *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindSint16(sl, "value", val); } if (min != NULL) { AG_BindSint16(sl, "min", min); } if (max != NULL) { AG_BindSint16(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewSint16R(void *parent, enum ag_slider_type type, Uint flags, Sint16 *val, Sint16 min, Sint16 max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindSint16(sl, "value", val); } AG_SetSint16(sl, "min", min); AG_SetSint16(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewUint32(void *parent, enum ag_slider_type type, Uint flags, Uint32 *val, Uint32 *min, Uint32 *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint32(sl, "value", val); } if (min != NULL) { AG_BindUint32(sl, "min", min); } if (max != NULL) { AG_BindUint32(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewUint32R(void *parent, enum ag_slider_type type, Uint flags, Uint32 *val, Uint32 min, Uint32 max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindUint32(sl, "value", val); } AG_SetUint32(sl, "min", min); AG_SetUint32(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewSint32(void *parent, enum ag_slider_type type, Uint flags, Sint32 *val, Sint32 *min, Sint32 *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindSint32(sl, "value", val); } if (min != NULL) { AG_BindSint32(sl, "min", min); } if (max != NULL) { AG_BindSint32(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewSint32R(void *parent, enum ag_slider_type type, Uint flags, Sint32 *val, Sint32 min, Sint32 max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindSint32(sl, "value", val); } AG_SetSint32(sl, "min", min); AG_SetSint32(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewFlt(void *parent, enum ag_slider_type type, Uint flags, float *val, float *min, float *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindFloat(sl, "value", val); } if (min != NULL) { AG_BindFloat(sl, "min", min); } if (max != NULL) { AG_BindFloat(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewFltR(void *parent, enum ag_slider_type type, Uint flags, float *val, float min, float max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindFloat(sl, "value", val); } AG_SetFloat(sl, "min", min); AG_SetFloat(sl, "max", max); return (sl); } AG_Slider * AG_SliderNewDbl(void *parent, enum ag_slider_type type, Uint flags, double *val, double *min, double *max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindDouble(sl, "value", val); } if (min != NULL) { AG_BindDouble(sl, "min", min); } if (max != NULL) { AG_BindDouble(sl, "max", max); } return (sl); } AG_Slider * AG_SliderNewDblR(void *parent, enum ag_slider_type type, Uint flags, double *val, double min, double max) { AG_Slider *sl = AG_SliderNew(parent, type, flags); if (val != NULL) { AG_BindDouble(sl, "value", val); } AG_SetDouble(sl, "min", min); AG_SetDouble(sl, "max", max); return (sl); } /* Set the size of the control in pixels. */ void AG_SliderSetControlSize(AG_Slider *sl, int size) { AG_ObjectLock(sl); sl->wControlPref = size; switch (sl->type) { case AG_SLIDER_HORIZ: sl->wControl = MIN(size, HEIGHT(sl)); break; case AG_SLIDER_VERT: sl->wControl = MIN(size, WIDTH(sl)); break; } AG_ObjectUnlock(sl); } /* Set the base increment for integer bindings. */ void AG_SliderSetIntIncrement(AG_Slider *sl, int inc) { AG_ObjectLock(sl); sl->iInc = inc; AG_ObjectUnlock(sl); } /* Set the base increment for real bindings. */ void AG_SliderSetRealIncrement(AG_Slider *sl, double inc) { AG_ObjectLock(sl); sl->rInc = inc; AG_ObjectUnlock(sl); } /* * Return the current position of the slider, in terms of the position of the * Left (or Top) edge in pixels. Returns 0 on success and -1 if the range * is currently <= 0. */ #define GET_POSITION(type) \ if (*(type *)pMin >= (*(type *)pMax)) { \ goto fail; \ } \ *x = (int)(((*(type *)pVal - *(type *)pMin) * sl->extent) / \ (*(type *)pMax - *(type *)pMin)) static __inline__ int GetPosition(AG_Slider *sl, int *x) { AG_Variable *bMin, *bMax, *bVal; void *pMin, *pMax, *pVal; bVal = AG_GetVariable(sl, "value", &pVal); bMin = AG_GetVariable(sl, "min", &pMin); bMax = AG_GetVariable(sl, "max", &pMax); switch (AG_VARIABLE_TYPE(bVal)) { case AG_VARIABLE_INT: GET_POSITION(int); break; case AG_VARIABLE_UINT: GET_POSITION(Uint); break; case AG_VARIABLE_FLOAT: GET_POSITION(float); break; case AG_VARIABLE_DOUBLE: GET_POSITION(double); break; case AG_VARIABLE_UINT8: GET_POSITION(Uint8); break; case AG_VARIABLE_SINT8: GET_POSITION(Sint8); break; case AG_VARIABLE_UINT16: GET_POSITION(Uint16); break; case AG_VARIABLE_SINT16: GET_POSITION(Sint16); break; case AG_VARIABLE_UINT32: GET_POSITION(Uint32); break; case AG_VARIABLE_SINT32: GET_POSITION(Sint32); break; default: *x = 0; break; } AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); return (0); fail: AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); return (-1); } #undef GET_POSITION /* * Set the value from a specified position in pixels. */ #define SEEK_TO_POSITION(type) \ if (x <= 0) { \ *(type *)pVal = *(type *)pMin; \ } else if (x >= sl->extent) { \ *(type *)pVal = *(type *)pMax; \ } else { \ *(type *)pVal = x * \ (*(type *)pMax - *(type *)pMin) / sl->extent; \ *(type *)pVal += *(type *)pMin; \ } static __inline__ void SeekToPosition(AG_Slider *sl, int x) { AG_Variable *bMin, *bMax, *bVal; void *pMin, *pMax, *pVal; bVal = AG_GetVariable(sl, "value", &pVal); bMin = AG_GetVariable(sl, "min", &pMin); bMax = AG_GetVariable(sl, "max", &pMax); switch (AG_VARIABLE_TYPE(bVal)) { case AG_VARIABLE_INT: SEEK_TO_POSITION(int); break; case AG_VARIABLE_UINT: SEEK_TO_POSITION(Uint); break; case AG_VARIABLE_FLOAT: SEEK_TO_POSITION(float); break; case AG_VARIABLE_DOUBLE: SEEK_TO_POSITION(double); break; case AG_VARIABLE_UINT8: SEEK_TO_POSITION(Uint8); break; case AG_VARIABLE_SINT8: SEEK_TO_POSITION(Sint8); break; case AG_VARIABLE_UINT16: SEEK_TO_POSITION(Uint16); break; case AG_VARIABLE_SINT16: SEEK_TO_POSITION(Sint16); break; case AG_VARIABLE_UINT32: SEEK_TO_POSITION(Uint32); break; case AG_VARIABLE_SINT32: SEEK_TO_POSITION(Sint32); break; default: break; } AG_PostEvent(NULL, sl, "slider-changed", NULL); AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); } #undef SEEK_TO_POSITION /* * Decrement the value by the specified amount multiplied by iInc/rInc. */ #define DECREMENT_INT(type) \ if ((*(type *)pVal - ((type)sl->iInc)*v) < *(type *)pMin) \ *(type *)pVal = *(type *)pMin; \ else \ *(type *)pVal -= ((type)sl->iInc)*v #define DECREMENT_REAL(type) \ if ((*(type *)pVal - ((type)v)*sl->rInc) < *(type *)pMin) \ *(type *)pVal = *(type *)pMin; \ else \ *(type *)pVal -= ((type)v)*sl->rInc static void Decrement(AG_Slider *sl, int v) { AG_Variable *bMin, *bMax, *bVal; void *pMin, *pMax, *pVal; bVal = AG_GetVariable(sl, "value", &pVal); bMin = AG_GetVariable(sl, "min", &pMin); bMax = AG_GetVariable(sl, "max", &pMax); switch (AG_VARIABLE_TYPE(bVal)) { case AG_VARIABLE_INT: DECREMENT_INT(int); break; case AG_VARIABLE_UINT: DECREMENT_INT(Uint); break; case AG_VARIABLE_FLOAT: DECREMENT_REAL(float); break; case AG_VARIABLE_DOUBLE: DECREMENT_REAL(double); break; case AG_VARIABLE_UINT8: DECREMENT_INT(Uint8); break; case AG_VARIABLE_SINT8: DECREMENT_INT(Sint8); break; case AG_VARIABLE_UINT16: DECREMENT_INT(Uint16); break; case AG_VARIABLE_SINT16: DECREMENT_INT(Sint16); break; case AG_VARIABLE_UINT32: DECREMENT_INT(Uint32); break; case AG_VARIABLE_SINT32: DECREMENT_INT(Sint32); break; default: break; } AG_PostEvent(NULL, sl, "slider-changed", NULL); AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); } #undef DECREMENT_INT #undef DECREMENT_REAL /* * Increment the value by the specified amount multiplied by iInc/rInc. */ #define INCREMENT_INT(type) \ if ((*(type *)pVal + ((type)sl->iInc)*v) > *(type *)pMax) \ *(type *)pVal = *(type *)pMax; \ else \ *(type *)pVal += ((type)sl->iInc)*v #define INCREMENT_REAL(type) \ if ((*(type *)pVal + ((type)v)*sl->rInc) > *(type *)pMax) \ *(type *)pVal = *(type *)pMax; \ else \ *(type *)pVal += ((type)v)*sl->rInc static void Increment(AG_Slider *sl, int v) { AG_Variable *bMin, *bMax, *bVal; void *pMin, *pMax, *pVal; bVal = AG_GetVariable(sl, "value", &pVal); bMin = AG_GetVariable(sl, "min", &pMin); bMax = AG_GetVariable(sl, "max", &pMax); switch (AG_VARIABLE_TYPE(bVal)) { case AG_VARIABLE_INT: INCREMENT_INT(int); break; case AG_VARIABLE_UINT: INCREMENT_INT(Uint); break; case AG_VARIABLE_FLOAT: INCREMENT_REAL(float); break; case AG_VARIABLE_DOUBLE: INCREMENT_REAL(double); break; case AG_VARIABLE_UINT8: INCREMENT_INT(Uint8); break; case AG_VARIABLE_SINT8: INCREMENT_INT(Sint8); break; case AG_VARIABLE_UINT16: INCREMENT_INT(Uint16); break; case AG_VARIABLE_SINT16: INCREMENT_INT(Sint16); break; case AG_VARIABLE_UINT32: INCREMENT_INT(Uint32); break; case AG_VARIABLE_SINT32: INCREMENT_INT(Sint32); break; default: break; } AG_PostEvent(NULL, sl, "slider-changed", NULL); AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); } #undef INCREMENT_INT #undef INCREMENT_REAL static void MouseButtonUp(AG_Event *event) { AG_Slider *sl = AG_SELF(); if (sl->ctlPressed) { sl->ctlPressed = 0; sl->xOffs = 0; AG_PostEvent(NULL, sl, "slider-drag-end", NULL); } } static void MouseButtonDown(AG_Event *event) { AG_Slider *sl = AG_SELF(); int button = AG_INT(1); int x = ((sl->type == AG_SLIDER_HORIZ) ? AG_INT(2) : AG_INT(3)); int pos; if (button != SDL_BUTTON_LEFT) { return; } if (GetPosition(sl, &pos) == -1) return; AG_WidgetFocus(sl); if (x >= pos && x <= (pos + sl->wControl)) { /* * Click on the slider itself. We don't do anything except * saving the cursor position which we will use in future * mousemotion events. */ sl->ctlPressed = 1; sl->xOffs = x - pos; AG_PostEvent(NULL, sl, "slider-drag-begin", NULL); } else { /* * Click outside of control. We seek to the absolute position * described by the cursor. */ sl->ctlPressed = 1; sl->xOffs = sl->wControl/2; SeekToPosition(sl, x - sl->xOffs); AG_PostEvent(NULL, sl, "slider-drag-begin", NULL); } } static void MouseMotion(AG_Event *event) { AG_Slider *sl = AG_SELF(); if (!sl->ctlPressed) { return; } SeekToPosition(sl, ((sl->type == AG_SLIDER_HORIZ) ? AG_INT(1):AG_INT(2)) - sl->xOffs); } static void KeyDown(AG_Event *event) { AG_Slider *sl = AG_SELF(); int keysym = AG_INT(1); switch (keysym) { case SDLK_UP: case SDLK_LEFT: Decrement(sl, 1); AG_DelTimeout(sl, &sl->incTo); AG_ScheduleTimeout(sl, &sl->decTo, agKbdDelay); break; case SDLK_DOWN: case SDLK_RIGHT: Increment(sl, 1); AG_DelTimeout(sl, &sl->decTo); AG_ScheduleTimeout(sl, &sl->incTo, agKbdDelay); break; } } static void KeyUp(AG_Event *event) { AG_Slider *sl = AG_SELF(); int keysym = AG_INT(1); switch (keysym) { case SDLK_UP: case SDLK_LEFT: AG_DelTimeout(sl, &sl->decTo); break; case SDLK_DOWN: case SDLK_RIGHT: AG_DelTimeout(sl, &sl->incTo); break; } } static Uint32 IncrementTimeout(void *obj, Uint32 ival, void *arg) { AG_Slider *sl = obj; Increment(sl, 1); return (agKbdRepeat); } static Uint32 DecrementTimeout(void *obj, Uint32 ival, void *arg) { AG_Slider *sl = obj; Decrement(sl, 1); return (agKbdRepeat); } static void LostFocus(AG_Event *event) { AG_Slider *sl = AG_SELF(); AG_DelTimeout(sl, &sl->incTo); AG_DelTimeout(sl, &sl->decTo); } static void BoundValue(AG_Event *event) { AG_Slider *sl = AG_SELF(); AG_Variable *bNew = AG_PTR(1); AG_Variable *bValue; void *pValue; /* * Require that "min" and "max" be of the same binding type as * "value" to avoid derelict hell. Mixing of types could always be * implemented if some application really requires it. */ if (!strcmp(bNew->name, "min") || !strcmp(bNew->name, "max")) { bValue = AG_GetVariable(sl, "value", &pValue); if (bValue->type != bNew->type) { AG_FatalError("Slider \"%s\" binding type disagree " "with \"value\" binding", bNew->name); } AG_UnlockVariable(bValue); } } static void Init(void *obj) { AG_Slider *sl = obj; WIDGET(sl)->flags |= AG_WIDGET_UNFOCUSED_BUTTONUP| AG_WIDGET_UNFOCUSED_MOTION| AG_WIDGET_FOCUSABLE; AG_BindInt(sl, "value", &sl->value); AG_BindInt(sl, "min", &sl->min); AG_BindInt(sl, "max", &sl->max); sl->type = AG_SLIDER_HORIZ; sl->ctlPressed = 0; sl->flags = 0; sl->value = 0; sl->min = 0; sl->max = 0; sl->wControlPref = 16; sl->wControl = sl->wControlPref; sl->xOffs = 0; sl->rInc = 1.0; sl->iInc = 1; AG_SetEvent(sl, "window-mousebuttondown", MouseButtonDown, NULL); AG_SetEvent(sl, "window-mousebuttonup", MouseButtonUp, NULL); AG_SetEvent(sl, "window-mousemotion", MouseMotion, NULL); AG_SetEvent(sl, "window-keydown", KeyDown, NULL); AG_SetEvent(sl, "window-keyup", KeyUp, NULL); AG_SetEvent(sl, "widget-lostfocus", LostFocus, NULL); AG_SetEvent(sl, "widget-hidden", LostFocus, NULL); AG_SetEvent(sl, "bound", BoundValue, NULL); AG_SetTimeout(&sl->incTo, IncrementTimeout, NULL, 0); AG_SetTimeout(&sl->decTo, DecrementTimeout, NULL, 0); } static void SizeRequest(void *obj, AG_SizeReq *r) { AG_Slider *sl = obj; r->w = sl->wControlPref*2 + 10; r->h = sl->wControlPref; } static int SizeAllocate(void *obj, const AG_SizeAlloc *a) { AG_Slider *sl = obj; if (a->w < 4 || a->h < 4) { return (-1); } switch (sl->type) { case AG_SLIDER_VERT: sl->wControl = MIN(sl->wControlPref, a->h); sl->extent = a->h; break; case AG_SLIDER_HORIZ: sl->wControl = MIN(sl->wControlPref, a->w); sl->extent = a->w; break; } sl->extent -= sl->wControl; return (0); } static void Draw(void *obj) { AG_Slider *sl = obj; int x; if (GetPosition(sl, &x) == -1) { return; } switch (sl->type) { case AG_SLIDER_VERT: STYLE(sl)->SliderBackgroundVert(sl); STYLE(sl)->SliderControlVert(sl, x, sl->wControl); break; case AG_SLIDER_HORIZ: STYLE(sl)->SliderBackgroundHoriz(sl); STYLE(sl)->SliderControlHoriz(sl, x, sl->wControl); break; } } AG_WidgetClass agSliderClass = { { "Agar(Widget:Slider)", sizeof(AG_Slider), { 0,0 }, Init, NULL, /* free */ NULL, /* destroy */ NULL, /* load */ NULL, /* save */ NULL /* edit */ }, Draw, SizeRequest, SizeAllocate };