diff options
Diffstat (limited to 'iup/src/iup_spin.c')
-rwxr-xr-x | iup/src/iup_spin.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/iup/src/iup_spin.c b/iup/src/iup_spin.c new file mode 100755 index 0000000..6fadab4 --- /dev/null +++ b/iup/src/iup_spin.c @@ -0,0 +1,301 @@ +/** \file + * \brief Spin control + * + * See Copyright Notice in "iup.h" +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "iup.h" +#include "iupcbs.h" +#include "iupkey.h" + +#include "iup_object.h" +#include "iup_attrib.h" +#include "iup_str.h" +#include "iup_stdcontrols.h" +#include "iup_childtree.h" + + +static Ihandle* spin_timer = NULL; + + +static int iSpinCallCB(Ihandle* ih, int dub, int ten, int sign) +{ + IFni cb; + + /* get the callback on the spin or on the spinbox */ + Ihandle* spinbox = (Ihandle*)iupAttribGet(ih->parent, "_IUPSPIN_BOX"); + if (spinbox) + ih = spinbox; + else + ih = ih->parent; + + cb = (IFni) IupGetCallback(ih, "SPIN_CB"); + if (cb) + { + return cb(ih, sign*(dub && ten ? 100 : + ten ? 10 : + dub ? 2 : 1)); + } + + return IUP_DEFAULT; +} + +static int iSpinTimerCB(Ihandle* ih) +{ + Ihandle* spin_button = (Ihandle*)iupAttribGet(ih, "_IUPSPIN_BUTTON"); + char* status = iupAttribGet(ih, "_IUPSPIN_STATUS"); + int spin_dir = iupAttribGetInt(ih, "_IUPSPIN_DIR"); + int count = iupAttribGetInt(ih, "_IUPSPIN_COUNT"); + char* reconfig = NULL; + + if(count == 0) /* first time */ + reconfig = "50"; + else if(count == 14) /* 300 + 14*50 = 1000 (1 second) */ + reconfig = "25"; + else if(count == 34) /* 300 + 14*50 + 20*50 = 2000 (2 seconds) */ + reconfig = "10"; + + if (reconfig) + { + IupSetAttribute(ih, "RUN", "NO"); + IupSetAttribute(ih, "TIME", reconfig); + IupSetAttribute(ih, "RUN", "YES"); + } + + iupAttribSetInt(ih, "_IUPSPIN_COUNT", count + 1); + + return iSpinCallCB(spin_button, iup_isshift(status), iup_iscontrol(status), spin_dir); +} + +static void iSpinPrepareTimer(Ihandle* ih, char* status, char* dir) +{ + (void)ih; + + iupAttribSetStr(spin_timer, "_IUPSPIN_BUTTON", (char*)ih); + + iupAttribStoreStr(spin_timer, "_IUPSPIN_STATUS", status); + + iupAttribSetStr(spin_timer, "_IUPSPIN_DIR", dir); + iupAttribSetStr(spin_timer, "_IUPSPIN_COUNT", "0"); + + IupSetAttribute(spin_timer, "TIME", "400"); + IupSetAttribute(spin_timer, "RUN", "YES"); +} + +static int iSpinK_SP(Ihandle* ih) +{ + int dir = iupAttribGetInt(ih, "_IUPSPIN_DIR"); + + return iSpinCallCB(ih, 0, 0, dir); +} + +static int iSpinK_sSP(Ihandle* ih) +{ + int dir = iupAttribGetInt(ih, "_IUPSPIN_DIR"); + + return iSpinCallCB(ih, 1, 0, dir); +} + +static int iSpinK_cSP(Ihandle* ih) +{ + int dir = iupAttribGetInt(ih, "_IUPSPIN_DIR"); + + return iSpinCallCB(ih, 0, 1, dir); +} + +static int iSpinButtonCB(Ihandle* ih, int but, int pressed, int x, int y, char* status) +{ + (void)x; + (void)y; + + if (pressed && but == IUP_BUTTON1) + { + int dir = iupAttribGetInt(ih, "_IUPSPIN_DIR"); + + iSpinPrepareTimer(ih, status, iupAttribGet(ih, "_IUPSPIN_DIR")); + + return iSpinCallCB(ih, iup_isshift(status), iup_iscontrol(status), dir); + } + else if (!pressed && but == IUP_BUTTON1) + { + IupSetAttribute(spin_timer, "RUN", "NO"); + } + + return IUP_DEFAULT; +} + +static int iSpinCreateMethod(Ihandle* ih, void** params) +{ + Ihandle* bt_up; + Ihandle* bt_down; + (void)params; + + /* Button UP */ + bt_up = IupButton(NULL, NULL); + + IupSetAttribute(bt_up, "EXPAND", "NO"); + IupSetAttribute(bt_up, "IMAGE", "IupSpinUpImage"); + IupSetAttribute(bt_up, "_IUPSPIN_DIR", "1"); + IupSetAttribute(bt_up, "CANFOCUS", "NO"); + + IupSetCallback(bt_up, "BUTTON_CB", (Icallback) iSpinButtonCB); + IupSetCallback(bt_up, "K_SP", (Icallback) iSpinK_SP); + IupSetCallback(bt_up, "K_sSP", (Icallback) iSpinK_sSP); + IupSetCallback(bt_up, "K_cSP", (Icallback) iSpinK_cSP); + + /* Button DOWN */ + bt_down = IupButton(NULL, NULL); + + IupSetAttribute(bt_down, "EXPAND", "NO"); + IupSetAttribute(bt_down, "IMAGE", "IupSpinDownImage"); + IupSetAttribute(bt_down, "_IUPSPIN_DIR", "-1"); + IupSetAttribute(bt_down, "CANFOCUS", "NO"); + + IupSetCallback(bt_down, "BUTTON_CB", (Icallback) iSpinButtonCB); + IupSetCallback(bt_down, "K_SP", (Icallback) iSpinK_SP); + IupSetCallback(bt_down, "K_sSP", (Icallback) iSpinK_sSP); + IupSetCallback(bt_down, "K_cSP", (Icallback) iSpinK_cSP); + + /* manually add the buttons as a children */ + ih->firstchild = bt_up; + bt_up->parent = ih; + bt_up->brother = bt_down; + bt_down->parent = ih; + + IupSetAttribute(ih, "GAP", "0"); + IupSetAttribute(ih, "MARGIN", "0x0"); + + return IUP_NOERROR; +} + +static int iSpinboxCreateMethod(Ihandle* ih, void** params) +{ + Ihandle *spin, *ctrl; + + if (!params || !(params[0])) + return IUP_ERROR; + + IupSetAttribute(ih, "GAP", "0"); + IupSetAttribute(ih, "MARGIN", "0x0"); + IupSetAttribute(ih, "ALIGNMENT", "ACENTER"); + + ctrl = (Ihandle*)(params[0]); + iupChildTreeAppend(ih, ctrl); + + spin = IupSpin(); + iupChildTreeAppend(ih, spin); + + iupAttribSetStr(spin, "_IUPSPIN_BOX", (char*)ih); + + return IUP_NOERROR; +} + +static void iSpinLoadImages(void) +{ + Ihandle* img; + + /* Spin UP image */ + unsigned char iupspin_up_img[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + /* Spin DOWN image */ + unsigned char iupspin_down_img[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + img = IupImage(9, 6, iupspin_up_img); + IupSetAttribute(img, "0", "0 0 0"); + IupSetAttribute(img, "1", "BGCOLOR"); + IupSetHandle("IupSpinUpImage", img); + + img = IupImage(9, 6, iupspin_down_img); + IupSetAttribute(img, "0", "0 0 0"); + IupSetAttribute(img, "1", "BGCOLOR"); + IupSetHandle("IupSpinDownImage", img); +} + +static void iSpinReleaseMethod(Iclass* ic) +{ + (void)ic; + + if (spin_timer) + { + /* no need to destroy the images, they will be destroyed by IupClose automatically */ + IupDestroy(spin_timer); + spin_timer = NULL; + } +} + +Iclass* iupSpinboxGetClass(void) +{ + Iclass* ic = iupClassNew(iupHboxGetClass()); + + ic->name = "spinbox"; + ic->format = "h"; /* one Ihandle */ + ic->nativetype = IUP_TYPEVOID; + ic->childtype = IUP_CHILDNONE; + ic->is_interactive = 0; + + iupClassRegisterCallback(ic, "SPIN_CB", "i"); + + /* Class functions */ + ic->Create = iSpinboxCreateMethod; + + return ic; +} + +Iclass* iupSpinGetClass(void) +{ + Iclass* ic = iupClassNew(iupVboxGetClass()); + + ic->name = "spin"; + ic->format = NULL; /* no parameters */ + ic->nativetype = IUP_TYPEVOID; + ic->childtype = IUP_CHILDNONE; + ic->is_interactive = 0; + + /* Class functions */ + ic->Create = iSpinCreateMethod; + ic->Release = iSpinReleaseMethod; + + iupClassRegisterCallback(ic, "SPIN_CB", "i"); + + if (!spin_timer) + { + iSpinLoadImages(); + + spin_timer = IupTimer(); + IupSetCallback(spin_timer, "ACTION_CB", (Icallback) iSpinTimerCB); + } + + return ic; +} + +Ihandle* IupSpin(void) +{ + return IupCreate("spin"); +} + +Ihandle* IupSpinbox(Ihandle* ctrl) +{ + void *params[2]; + params[0] = (void*)ctrl; + params[1] = NULL; /* must add NULL because spinbox inherit from Hbox */ + return IupCreatev("spinbox", params); +} |