diff options
Diffstat (limited to 'iup/src/iup_getparam.c')
-rwxr-xr-x | iup/src/iup_getparam.c | 1254 |
1 files changed, 1254 insertions, 0 deletions
diff --git a/iup/src/iup_getparam.c b/iup/src/iup_getparam.c new file mode 100755 index 0000000..1418aa5 --- /dev/null +++ b/iup/src/iup_getparam.c @@ -0,0 +1,1254 @@ +/** \file + * \brief IupGetParam + * + * See Copyright Notice in "iup.h" + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <assert.h> + +#include "iup.h" + +#include "iup_attrib.h" +#include "iup_str.h" +#include "iup_strmessage.h" +#include "iup_drvfont.h" + + +#define RAD2DEG 57.296f /* radians to degrees */ + + +/******************************************************************************************* + Internal Callbacks +*******************************************************************************************/ + +static int iParamButtonOK_CB(Ihandle* self) +{ + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + iupAttribSetStr(dlg, "STATUS", "1"); + if (cb && !cb(dlg, -1, (void*)iupAttribGet(dlg, "USER_DATA"))) + return IUP_DEFAULT; + else + return IUP_CLOSE; +} + +static int iParamButtonCancel_CB(Ihandle* self) +{ + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + iupAttribSetStr(dlg, "STATUS", "0"); + if (cb) cb(dlg, -3, (void*)iupAttribGet(dlg, "USER_DATA")); + return IUP_CLOSE; +} + +static int iParamToggleAction_CB(Ihandle *self, int v) +{ + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + int old_v = iupAttribGetInt(param, "VALUE"); + + if (v == 1) + iupAttribSetStr(param, "VALUE", "1"); + else + iupAttribSetStr(param, "VALUE", "0"); + + if (cb && !cb(dlg, iupAttribGetInt(param, "INDEX"), (void*)iupAttribGet(dlg, "USER_DATA"))) + { + /* Undo */ + if (old_v == 1) + { + iupAttribSetStr(param, "VALUE", "1"); + IupSetAttribute(self, "VALUE", "1"); + } + else + { + iupAttribSetStr(param, "VALUE", "0"); + IupSetAttribute(self, "VALUE", "0"); + } + + /* there is no IUP_IGNORE for IupToggle */ + return IUP_DEFAULT; + } + + /* update the interface */ + if (v == 1) + IupStoreAttribute(self, "TITLE", iupAttribGet(param, "_IUPGP_TRUE")); + else + IupStoreAttribute(self, "TITLE", iupAttribGet(param, "_IUPGP_FALSE")); + + return IUP_DEFAULT; +} + +static int iParamTextAction_CB(Ihandle *self, int c, char *after) +{ + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + Ihandle* aux = (Ihandle*)iupAttribGet(param, "AUXCONTROL"); + (void)c; + + iupAttribStoreStr(param, "VALUE", after); + + if (cb && !cb(dlg, iupAttribGetInt(param, "INDEX"), (void*)iupAttribGet(dlg, "USER_DATA"))) + { + /* Undo */ + iupAttribStoreStr(param, "VALUE", IupGetAttribute(self, "VALUE")); + return IUP_IGNORE; + } + + if (aux) + { + if (iupStrEqual(iupAttribGet(param, "TYPE"), "COLOR")) + IupStoreAttribute(aux, "BGCOLOR", after); + else + IupStoreAttribute(aux, "VALUE", after); + } + + if (IupGetInt(self, "SPIN")) + { + if (iupAttribGet(self, "_IUPGP_SPINREAL")) + { + float min = iupAttribGetFloat(param, "MIN"); + float step = iupAttribGetFloat(self, "_IUPGP_INCSTEP"); + float val; + if (iupStrToFloat(after, &val)) + IupSetfAttribute(self, "SPINVALUE", "%d", (int)((val-min)/step + 0.5)); + } + else + { + int val; + if (iupStrToInt(after, &val)) + IupSetfAttribute(self, "SPINVALUE", "%d", val); + } + } + + return IUP_DEFAULT; +} + +static int iParamValAction_CB(Ihandle *self) +{ + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* text = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_TEXT"); + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + float old_value = iupAttribGetFloat(param, "VALUE"); + float val = IupGetFloat(self, "VALUE"); + + char* type = iupAttribGet(param, "TYPE"); + if (iupStrEqual(type, "INTEGER")) + { + iupAttribSetStrf(param, "VALUE", "%d", (int)val); + } + else + { + if (iupAttribGetInt(param, "ANGLE")) + { + float old_angle; + + if (val == 0) + { + old_angle = iupAttribGetFloat(param, "VALUE"); + iupAttribSetStrf(param, "_IUPGP_OLD_ANGLE", "%g", old_angle); + } + else + old_angle = iupAttribGetFloat(param, "_IUPGP_OLD_ANGLE"); + + val = old_angle + val*RAD2DEG; + + if (iupAttribGetInt(param, "INTERVAL")) + { + float min = iupAttribGetFloat(param, "MIN"); + float max = iupAttribGetFloat(param, "MAX"); + if (val < min) + val = min; + if (val > max) + val = max; + } + else if (iupAttribGetInt(param, "PARTIAL")) + { + float min = iupAttribGetFloat(param, "MIN"); + if (val < min) + val = min; + } + } + + iupAttribSetStrf(param, "VALUE", "%g", val); + } + + if (cb && !cb(dlg, iupAttribGetInt(param, "INDEX"), (void*)iupAttribGet(dlg, "USER_DATA"))) + { + /* Undo */ + iupAttribSetStrf(param, "VALUE", "%g", old_value); + + if (!iupAttribGetInt(param, "ANGLE")) + IupSetfAttribute(self, "VALUE", "%g", old_value); + + /* there is no IUP_IGNORE for IupVal */ + return IUP_DEFAULT; + } + + type = iupAttribGet(param, "TYPE"); + if (iupStrEqual(type, "INTEGER")) + IupSetfAttribute(text, "VALUE", "%d", (int)val); + else + IupSetfAttribute(text, "VALUE", "%g", val); + + if (IupGetInt(text, "SPIN")) + { + if (iupAttribGet(text, "_IUPGP_SPINREAL")) + { + float min = iupAttribGetFloat(param, "MIN"); + float step = iupAttribGetFloat(text, "_IUPGP_INCSTEP"); + float val = IupGetFloat(text, "VALUE"); + IupSetfAttribute(text, "SPINVALUE", "%d", (int)((val-min)/step + 0.5)); + } + else + { + int val = IupGetInt(text, "VALUE"); + IupSetfAttribute(text, "SPINVALUE", "%d", val); + } + } + + return IUP_DEFAULT; +} + +static int iParamListAction_CB(Ihandle *self, char *t, int i, int v) +{ + (void)t; + if (v == 1) + { + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + int old_i = iupAttribGetInt(param, "VALUE"); + + iupAttribSetStrf(param, "VALUE", "%d", i-1); + + if (cb && !cb(dlg, iupAttribGetInt(param, "INDEX"), (void*)iupAttribGet(dlg, "USER_DATA"))) + { + /* Undo */ + iupAttribSetStrf(param, "VALUE", "%d", old_i); + IupSetfAttribute(self, "VALUE", "%d", old_i+1); + + /* there is no IUP_IGNORE for IupList */ + return IUP_DEFAULT; + } + } + + return IUP_DEFAULT; +} + +static int iParamFileButton_CB(Ihandle *self) +{ + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* textbox = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_TEXT"); + + Ihandle* dlg = IupFileDlg(); + + IupSetAttributeHandle(dlg, "PARENTDIALOG", IupGetDialog(self)); + IupSetAttribute(dlg, "TITLE", iupAttribGet(param, "TITLE")); + IupSetAttribute(dlg, "VALUE", iupAttribGet(param, "VALUE")); + + IupSetAttribute(dlg, "DIALOGTYPE", iupAttribGet(param, "_IUPGP_DIALOGTYPE")); + IupSetAttribute(dlg, "FILTER", iupAttribGet(param, "_IUPGP_FILTER")); + IupSetAttribute(dlg, "DIRECTORY", iupAttribGet(param, "_IUPGP_DIRECTORY")); + IupSetAttribute(dlg, "NOCHANGEDIR", iupAttribGet(param, "_IUPGP_NOCHANGEDIR")); + IupSetAttribute(dlg, "NOOVERWRITEPROMPT", iupAttribGet(param, "_IUPGP_NOOVERWRITEPROMPT")); + + IupPopup(dlg, IUP_CENTER, IUP_CENTER); + + if (IupGetInt(dlg, "STATUS") != -1) + { + IupSetAttribute(textbox, "VALUE", iupAttribGet(dlg, "VALUE")); + iupAttribStoreStr(param, "VALUE", iupAttribGet(dlg, "VALUE")); + } + + IupDestroy(dlg); + + return IUP_DEFAULT; +} + +static int iParamColorButton_CB(Ihandle *self, int button, int pressed) +{ + if (button==IUP_BUTTON1 && pressed) + { + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* textbox = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_TEXT"); + + Ihandle* dlg = IupColorDlg(); + + IupSetAttributeHandle(dlg, "PARENTDIALOG", IupGetDialog(self)); + IupSetAttribute(dlg, "TITLE", iupAttribGet(param, "TITLE")); + IupSetAttribute(dlg, "VALUE", iupAttribGet(param, "VALUE")); + + IupPopup(dlg, IUP_CENTER, IUP_CENTER); + + if (IupGetInt(dlg, "STATUS") != -1) + { + char* value = IupGetAttribute(dlg, "VALUE"); + IupSetAttribute(textbox, "VALUE", value); + iupAttribStoreStr(param, "VALUE", value); + IupStoreAttribute(self, "BGCOLOR", value); + } + + IupDestroy(dlg); + } + + return IUP_DEFAULT; +} + +static int iParamSpinReal_CB(Ihandle *self, int pos) +{ + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + Ihandle* text = (Ihandle*)iupAttribGet(param, "CONTROL"); + float min = iupAttribGetFloat(param, "MIN"); + float max = iupAttribGetFloat(param, "MAX"); + float val, step = iupAttribGetFloat(text, "_IUPGP_INCSTEP"); + + /* here spin is always [0-spinmax] converted to [min-max] */ + val = (float)pos*step + min; + if (val < min) + val = min; + if (val > max) + val = max; + + iupAttribSetStrf(param, "VALUE", "%g", (double)val); + + if (cb) + { + int ret; + iupAttribSetStr(dlg, "SPINNING", "1"); + ret = cb(dlg, iupAttribGetInt(param, "INDEX"), (void*)iupAttribGet(dlg, "USER_DATA")); + iupAttribSetStr(dlg, "SPINNING", NULL); + if (!ret) + return IUP_IGNORE; + } + + IupSetfAttribute(text, "VALUE", "%g", (double)val); + + { + Ihandle* aux = (Ihandle*)iupAttribGet(param, "AUXCONTROL"); + if (aux) + IupSetfAttribute(aux, "VALUE", "%g", (double)val); + } + + return IUP_DEFAULT; +} + +static int iParamSpinInt_CB(Ihandle *self, int pos) +{ + Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM"); + Ihandle* dlg = IupGetDialog(self); + Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB"); + Ihandle* text = (Ihandle*)iupAttribGet(param, "CONTROL"); + + /* here spin is always [min-max] */ + + iupAttribSetInt(param, "VALUE", pos); + + if (cb) + { + int ret; + iupAttribSetStr(dlg, "SPINNING", "1"); + ret = cb(dlg, iupAttribGetInt(param, "INDEX"), (void*)iupAttribGet(dlg, "USER_DATA")); + iupAttribSetStr(dlg, "SPINNING", NULL); + if (!ret) + return IUP_IGNORE; + } + + IupSetfAttribute(text, "VALUE", "%g", (double)pos); + + { + Ihandle* aux = (Ihandle*)iupAttribGet(param, "AUXCONTROL"); + if (aux) + IupSetfAttribute(aux, "VALUE", "%g", (double)pos); + } + + return IUP_DEFAULT; +} + +/******************************************************************************************* + Creates One Parameter Box +*******************************************************************************************/ + +static Ihandle* iParamCreateBox(Ihandle* param) +{ + Ihandle *box, *ctrl = NULL, *label; + char *type; + + label = IupLabel(iupAttribGet(param, "TITLE")); + + type = iupAttribGet(param, "TYPE"); + if (iupStrEqual(type, "SEPARATOR")) + { + box = IupHbox(label, NULL); + IupSetAttribute(box,"ALIGNMENT","ACENTER"); + } + else + { + if (iupStrEqual(type, "STRING") && iupAttribGetInt(param, "MULTILINE")) + { + Ihandle* hbox1 = IupHbox(IupSetAttributes(IupFill(), "SIZE=5"), label, NULL); + IupSetAttribute(hbox1,"ALIGNMENT","ACENTER"); + + box = IupVbox(hbox1, NULL); + IupSetAttribute(box,"ALIGNMENT","ALEFT"); + } + else + { + box = IupHbox(IupSetAttributes(IupFill(), "SIZE=5"), label, NULL); + IupSetAttribute(box,"ALIGNMENT","ACENTER"); + } + } + + IupSetAttribute(box,"MARGIN","0x0"); + + type = iupAttribGet(param, "TYPE"); + if (iupStrEqual(type, "BOOLEAN")) + { + int value = iupAttribGetInt(param, "VALUE"); + if (value) + { + ctrl = IupToggle(iupAttribGet(param, "_IUPGP_TRUE"), NULL); + IupSetAttribute(ctrl, "VALUE", "ON"); + } + else + { + ctrl = IupToggle(iupAttribGet(param, "_IUPGP_FALSE"), NULL); + IupSetAttribute(ctrl, "VALUE", "OFF"); + } + IupSetCallback(ctrl, "ACTION", (Icallback)iParamToggleAction_CB); + + IupAppend(box, ctrl); + iupAttribSetStr(param, "DATA_TYPE", "1"); + } + else if (iupStrEqual(type, "SEPARATOR")) + { + ctrl = IupLabel(""); + IupSetAttribute(ctrl, "SEPARATOR", "HORIZONTAL"); + + IupAppend(box, ctrl); + iupAttribSetStr(param, "DATA_TYPE", "-1"); + } + else if (iupStrEqual(type, "LIST")) + { + char str[20] = "1"; + int i = 1; + ctrl = IupList(NULL); + IupSetCallback(ctrl, "ACTION", (Icallback)iParamListAction_CB); + IupSetAttribute(ctrl, "DROPDOWN", "YES"); + IupSetfAttribute(ctrl, "VALUE", "%d", iupAttribGetInt(param, "VALUE")+1); + + while (*iupAttribGet(param, str) != 0) + { + IupStoreAttribute(ctrl, str, iupAttribGet(param, str)); + i++; + sprintf(str, "%d", i); + } + IupStoreAttribute(ctrl, str, NULL); + + IupAppend(box, ctrl); + iupAttribSetStr(param, "DATA_TYPE", "1"); + } + else if (iupStrEqual(type, "STRING")) + { + if (iupAttribGetInt(param, "MULTILINE")) + { + Ihandle* hbox; + + ctrl = IupMultiLine(NULL); + IupSetAttribute(ctrl, "SIZE", "100x50"); + IupSetAttribute(ctrl, "EXPAND", "YES"); + + hbox = IupHbox(IupSetAttributes(IupFill(), "SIZE=5"), ctrl, NULL); + IupSetAttribute(hbox,"ALIGNMENT","ACENTER"); + + IupAppend(box, hbox); + } + else + { + ctrl = IupText(NULL); + IupSetAttribute(ctrl, "SIZE", "100x"); + IupSetAttribute(ctrl, "EXPAND", "HORIZONTAL"); + IupAppend(box, ctrl); + } + IupSetCallback(ctrl, "ACTION", (Icallback)iParamTextAction_CB); + IupStoreAttribute(ctrl, "VALUE", iupAttribGet(param, "VALUE")); + + { + char* mask = iupAttribGet(param, "MASK"); + if (mask) + IupStoreAttribute(ctrl, "MASK", mask); + } + + iupAttribSetStr(param, "DATA_TYPE", "0"); + iupAttribSetStr(param, "EXPAND", "1"); + } + else if (iupStrEqual(type, "FILE")) + { + Ihandle* aux; + + ctrl = IupText(NULL); + IupSetAttribute(ctrl, "SIZE", "100x"); + IupSetAttribute(ctrl, "EXPAND", "HORIZONTAL"); + IupAppend(box, ctrl); + + IupSetCallback(ctrl, "ACTION", (Icallback)iParamTextAction_CB); + IupStoreAttribute(ctrl, "VALUE", iupAttribGet(param, "VALUE")); + + iupAttribSetStr(param, "DATA_TYPE", "0"); + iupAttribSetStr(param, "EXPAND", "1"); + + + aux = IupButton("...", ""); + IupSetAttribute(aux, "EXPAND", "NO"); + + IupSetCallback(aux, "ACTION", (Icallback)iParamFileButton_CB); + iupAttribSetStr(aux, "_IUPGP_PARAM", (char*)param); + iupAttribSetStr(aux, "_IUPGP_TEXT", (char*)ctrl); + IupSetAttribute(aux, "EXPAND", "NO"); + + IupAppend(box, aux); + } + else if (iupStrEqual(type, "COLOR")) + { + Ihandle* aux; + + ctrl = IupText(NULL); + IupSetAttribute(ctrl, "SIZE", "100x"); + IupSetAttribute(ctrl, "EXPAND", "HORIZONTAL"); + IupAppend(box, ctrl); + + IupSetCallback(ctrl, "ACTION", (Icallback)iParamTextAction_CB); + IupSetAttribute(ctrl, "MASK", "(/d|/d/d|1/d/d|2(0|1|2|3|4)/d|25(0|1|2|3|4|5)) (/d|/d/d|1/d/d|2(0|1|2|3|4)/d|25(0|1|2|3|4|5)) (/d|/d/d|1/d/d|2(0|1|2|3|4)/d|25(0|1|2|3|4|5)) (/d|/d/d|1/d/d|2(0|1|2|3|4)/d|25(0|1|2|3|4|5))"); + IupStoreAttribute(ctrl, "VALUE", iupAttribGet(param, "VALUE")); + + iupAttribSetStr(param, "DATA_TYPE", "0"); + iupAttribSetStr(param, "EXPAND", "1"); + + + aux = IupCanvas(NULL); + IupSetAttribute(aux, "SIZE", "20x10"); + IupSetAttribute(aux, "EXPAND", "NO"); + IupStoreAttribute(aux, "BGCOLOR", iupAttribGet(param, "VALUE")); + + IupSetCallback(aux, "BUTTON_CB", (Icallback)iParamColorButton_CB); + iupAttribSetStr(param, "AUXCONTROL", (char*)aux); + iupAttribSetStr(aux, "_IUPGP_PARAM", (char*)param); + iupAttribSetStr(aux, "_IUPGP_TEXT", (char*)ctrl); + IupSetAttribute(aux, "EXPAND", "NO"); + + IupAppend(box, aux); + } + else /* INTEGER, REAL */ + { + ctrl = IupText(NULL); + IupSetCallback(ctrl, "ACTION", (Icallback)iParamTextAction_CB); + IupStoreAttribute(ctrl, "VALUE", iupAttribGet(param, "VALUE")); + + type = iupAttribGet(param, "TYPE"); + if (iupStrEqual(type, "REAL")) + { + if (iupAttribGetInt(param, "INTERVAL")) + { + float min = iupAttribGetFloat(param, "MIN"); + float max = iupAttribGetFloat(param, "MAX"); + float step = iupAttribGetFloat(param, "STEP"); + float val = iupAttribGetFloat(param, "VALUE"); + if (step == 0) step = (max-min)/20.0f; + IupSetfAttribute(ctrl, "MASKFLOAT", "%f:%f", (double)min, (double)max); + + /* here spin is always [0-spinmax] converted to [min-max] */ + + IupSetAttribute(ctrl, "SPIN", "YES"); /* spin only for intervals */ + IupSetAttribute(ctrl, "SPINAUTO", "NO"); + IupAppend(box, ctrl); + IupSetCallback(ctrl, "SPIN_CB", (Icallback)iParamSpinReal_CB); + /* SPINMIN=0 and SPININC=1 */ + IupSetfAttribute(ctrl, "SPINMAX", "%d", (int)((max-min)/step + 0.5)); + IupSetfAttribute(ctrl, "SPINVALUE", "%d", (int)((val-min)/step + 0.5)); + + iupAttribSetStrf(ctrl, "_IUPGP_INCSTEP", "%g", step); + iupAttribSetStr(ctrl, "_IUPGP_SPINREAL", "1"); + } + else if (iupAttribGetInt(param, "PARTIAL")) + { + float min = iupAttribGetFloat(param, "MIN"); + if (min == 0) + IupSetAttribute(ctrl, "MASK", IUP_MASK_UFLOAT); + else + IupSetfAttribute(ctrl, "MASKFLOAT", "%f:%f", (double)min, (double)1.0e10); + IupAppend(box, ctrl); + } + else + { + IupSetAttribute(ctrl, "MASK", IUP_MASK_FLOAT); + IupAppend(box, ctrl); + } + + iupAttribSetStr(param, "DATA_TYPE", "2"); + IupSetAttribute(ctrl, "SIZE", "50x"); + } + else /* INTEGER*/ + { + int val = iupAttribGetInt(param, "VALUE"); + IupSetAttribute(ctrl, "SPIN", "YES"); /* spin always */ + IupSetAttribute(ctrl, "SPINAUTO", "NO"); /* manually update spin so the callback can also updated it */ + IupAppend(box, ctrl); + IupSetCallback(ctrl, "SPIN_CB", (Icallback)iParamSpinInt_CB); + iupAttribSetStr(ctrl, "_IUPGP_INCSTEP", "1"); + IupSetfAttribute(ctrl, "SPINVALUE", "%d", val); + + /* here spin is always [min-max] */ + + if (iupAttribGetInt(param, "INTERVAL")) + { + int min = iupAttribGetInt(param, "MIN"); + int max = iupAttribGetInt(param, "MAX"); + int step = iupAttribGetInt(param, "STEP"); + if (step) + { + iupAttribSetStrf(ctrl, "_IUPGP_INCSTEP", "%d", step); + IupSetfAttribute(ctrl, "SPININC", "%d", step); + } + IupSetfAttribute(ctrl, "SPINMAX", "%d", max); + IupSetfAttribute(ctrl, "SPINMIN", "%d", min); + } + else if (iupAttribGetInt(param, "PARTIAL")) + { + int min = iupAttribGetInt(param, "MIN"); + if (min == 0) + IupSetAttribute(ctrl, "MASK", IUP_MASK_UINT); + else + IupSetfAttribute(ctrl, "MASKINT", "%d:2147483647", min); + IupSetfAttribute(ctrl, "SPINMIN", "%d", min); + IupSetAttribute(ctrl, "SPINMAX", "2147483647"); + } + else + { + IupSetAttribute(ctrl, "SPINMIN", "-2147483647"); + IupSetAttribute(ctrl, "SPINMAX", "2147483647"); + IupSetAttribute(ctrl, "MASK", IUP_MASK_INT); + } + + iupAttribSetStr(param, "DATA_TYPE", "1"); + IupSetAttribute(ctrl, "SIZE", "50x"); + } + + if (iupAttribGetInt(param, "INTERVAL") || iupAttribGetInt(param, "ANGLE")) + { + Ihandle* aux; + + if (iupAttribGetInt(param, "ANGLE")) + { + aux = IupCreatep("dial", "HORIZONTAL", NULL); + if (aux) + { + IupSetfAttribute(aux, "VALUE", "%g", (double)(iupAttribGetFloat(param, "VALUE")/RAD2DEG)); + IupSetAttribute(aux, "SIZE", "50x10"); + } + } + else + { + char* step; + aux = IupVal("HORIZONTAL"); + IupStoreAttribute(aux, "MIN", iupAttribGet(param, "MIN")); + IupStoreAttribute(aux, "MAX", iupAttribGet(param, "MAX")); + IupStoreAttribute(aux, "VALUE", iupAttribGet(param, "VALUE")); + IupSetAttribute(aux, "EXPAND", "HORIZONTAL"); + iupAttribSetStr(param, "AUXCONTROL", (char*)aux); + iupAttribSetStr(param, "EXPAND", "1"); + step = iupAttribGet(param, "STEP"); + if (step) + IupSetfAttribute(aux, "STEP", "%g", iupAttribGetFloat(param, "STEP")/(iupAttribGetFloat(param, "MAX")-iupAttribGetFloat(param, "MIN"))); + else if (iupStrEqual(type, "INTEGER")) + IupSetfAttribute(aux, "STEP", "%g", 1.0/(iupAttribGetFloat(param, "MAX")-iupAttribGetFloat(param, "MIN"))); + } + + if (aux) + { + IupSetCallback(aux, "VALUECHANGED_CB", (Icallback)iParamValAction_CB); + iupAttribSetStr(aux, "_IUPGP_PARAM", (char*)param); + iupAttribSetStr(aux, "_IUPGP_TEXT", (char*)ctrl); + + IupAppend(box, aux); + } + } + } + + if (ctrl) IupStoreAttribute(ctrl, "TIP", iupAttribGet(param, "TIP")); + iupAttribSetStr(box, "_IUPGP_PARAM", (char*)param); + iupAttribSetStr(param, "CONTROL", (char*)ctrl); + iupAttribSetStr(param, "LABEL", (char*)label); + return box; +} + +/******************************************************************************************* + Creates the Dialog and Normalize Sizes +*******************************************************************************************/ + +static Ihandle* IupParamDlgP(Ihandle** params) +{ + Ihandle *dlg, *button_ok, *button_cancel, + *dlg_box, *button_box, *param_box; + int i, lbl_width, p, expand; + + button_ok = IupButton("OK", NULL); + IupSetAttribute(button_ok, "PADDING", "20x0"); + IupSetCallback(button_ok, "ACTION", (Icallback)iParamButtonOK_CB); + + button_cancel = IupButton(iupStrMessageGet("IUP_CANCEL"), NULL); + IupSetAttribute(button_cancel, "PADDING", "20x0"); + IupSetCallback(button_cancel, "ACTION", (Icallback)iParamButtonCancel_CB); + + param_box = IupVbox(NULL); + + i = 0; expand = 0; + while (params[i] != NULL) + { + IupAppend(param_box, iParamCreateBox(params[i])); + + if (IupGetInt(params[i], "EXPAND")) + expand = 1; + + i++; + } + + button_box = IupHbox( + IupFill(), + button_ok, + button_cancel, + NULL); + IupSetAttribute(button_box,"MARGIN","0x0"); + IupSetAttribute(button_box, "NORMALIZESIZE", "HORIZONTAL"); + + dlg_box = IupVbox( + IupFrame(param_box), + button_box, + NULL); + IupSetAttribute(dlg_box, "MARGIN", "10x10"); + IupSetAttribute(dlg_box, "GAP", "5"); + + dlg = IupDialog(dlg_box); + + IupSetAttribute(dlg, "MINBOX", "NO"); + IupSetAttribute(dlg, "MAXBOX", "NO"); + if (!expand) + { + IupSetAttribute(dlg, "RESIZE", "NO"); + IupSetAttribute(dlg, "DIALOGFRAME", "YES"); + IupSetAttribute(dlg,"DIALOGHINT","YES"); + } + IupSetAttributeHandle(dlg, "DEFAULTENTER", button_ok); + IupSetAttributeHandle(dlg, "DEFAULTESC", button_cancel); + IupSetAttribute(dlg, "TITLE", "ParamDlg"); + IupSetAttribute(dlg, "PARENTDIALOG", IupGetGlobal("PARENTDIALOG")); + IupSetAttribute(dlg, "ICON", IupGetGlobal("ICON")); + iupAttribSetStr(dlg, "OK", (char*)button_ok); + iupAttribSetStr(dlg, "CANCEL", (char*)button_cancel); + + IupMap(dlg); + + /* get the largest label size and set INDEX */ + i = 0; lbl_width = 0, p = 0; + while (params[i] != NULL) + { + int w; + + char* type = iupAttribGet(params[i], "TYPE"); + if (!iupStrEqual(type, "SEPARATOR")) + { + char str[20]; + sprintf(str, "PARAM%d", p); + IupSetAttribute(dlg, str, (char*)params[i]); + iupAttribSetStrf(params[i], "INDEX", "%d", p); + p++; + } + + w = IupGetInt((Ihandle*)iupAttribGet(params[i], "LABEL"), "SIZE"); + if (w > lbl_width) + lbl_width = w; + + i++; + } + + i = 0; + while (params[i] != NULL) + { + char* type = iupAttribGet(params[i], "TYPE"); + if (!iupStrEqual(type, "SEPARATOR")) + { + if (iupStrEqual(type, "LIST")) + { + /* set a minimum size for lists */ + Ihandle* ctrl = (Ihandle*)iupAttribGet(params[i], "CONTROL"); + if (IupGetInt(ctrl, "SIZE") < 50) + IupSetAttribute(ctrl, "SIZE", "50x"); + } + else if (iupStrEqual(type, "BOOLEAN")) + { + /* reserve enough space for boolean strings */ + Ihandle* ctrl = (Ihandle*)iupAttribGet(params[i], "CONTROL"); + int wf = iupdrvFontGetStringWidth(ctrl, iupAttribGet(params[i], "_IUPGP_FALSE")); + int wt = iupdrvFontGetStringWidth(ctrl, iupAttribGet(params[i], "_IUPGP_TRUE")); + int w = IupGetInt(ctrl, "SIZE"); + int v = IupGetInt(ctrl, "VALUE"); + if (v) /* True */ + { + int box = w - wt; + wf += box; + if (wf > w) + IupSetfAttribute(ctrl, "SIZE", "%dx", wf+8); + } + else + { + int box = w - wf; + wt += box; + if (wt > w) + IupSetfAttribute(ctrl, "SIZE", "%dx", wt+8); + } + } + + IupSetfAttribute((Ihandle*)iupAttribGet(params[i], "LABEL"), "SIZE", "%dx", lbl_width); + } + + i++; + } + + IupSetAttribute(dlg, "SIZE", NULL); + + return dlg; +} + +/******************************************************************************************* + Parameter String Parsing +*******************************************************************************************/ + +static char* iParamGetNextStrItem(char* line, char sep, int *count) +{ + int i = 0; + + while (line[i] != '\n' && line[i] != 0) + { + if (line[i] == sep) + { + line[i] = 0; + *count = i+1; + return line; + } + + i++; + } + + /* last item may not have the separator */ + line[i] = 0; + *count = i; + return line; +} + +static void iParamSetBoolNames(char* extra, Ihandle* param) +{ + char *falsestr = NULL, *truestr = NULL; + int count; + + if (extra) + { + falsestr = iParamGetNextStrItem(extra, ',', &count); extra += count; + truestr = iParamGetNextStrItem(extra, ',', &count); + } + + if (falsestr && truestr) + { + iupAttribStoreStr(param, "_IUPGP_TRUE", truestr); + iupAttribStoreStr(param, "_IUPGP_FALSE", falsestr); + } + else + { +/* iupAttribStoreStr(param, "_IUPGP_TRUE", iupStrMessageGet("IUP_TRUE")); */ +/* iupAttribStoreStr(param, "_IUPGP_FALSE", iupStrMessageGet("IUP_FALSE")); */ + iupAttribStoreStr(param, "_IUPGP_TRUE", ""); + iupAttribStoreStr(param, "_IUPGP_FALSE", ""); + } +} + +static void iParamSetInterval(char* extra, Ihandle* param) +{ + char *min, *max, *step; + int count; + + if (!extra) + return; + + min = iParamGetNextStrItem(extra, ',', &count); extra += count; + max = iParamGetNextStrItem(extra, ',', &count); extra += count; + step = iParamGetNextStrItem(extra, ',', &count); + + if (max[0]) + { + iupAttribSetStr(param, "INTERVAL", "1"); + iupAttribStoreStr(param, "MIN", min); + iupAttribStoreStr(param, "MAX", max); + if (step[0]) + iupAttribStoreStr(param, "STEP", step); + } + else + { + iupAttribSetStr(param, "PARTIAL", "1"); + iupAttribStoreStr(param, "MIN", min); + } +} + +static void iParamSetFileOptions(char* extra, Ihandle* param) +{ + char *type, *filter, *directory, *nochangedir, *nooverwriteprompt; + int count; + + if (!extra) + return; + + type = iParamGetNextStrItem(extra, '|', &count); extra += count; + filter = iParamGetNextStrItem(extra, '|', &count); extra += count; + directory = iParamGetNextStrItem(extra, '|', &count); extra += count; + nochangedir = iParamGetNextStrItem(extra, '|', &count); extra += count; + nooverwriteprompt = iParamGetNextStrItem(extra, '|', &count); extra += count; + + iupAttribStoreStr(param, "_IUPGP_DIALOGTYPE", type); + iupAttribStoreStr(param, "_IUPGP_FILTER", filter); + iupAttribStoreStr(param, "_IUPGP_DIRECTORY", directory); + iupAttribStoreStr(param, "_IUPGP_NOCHANGEDIR", nochangedir); + iupAttribStoreStr(param, "_IUPGP_NOOVERWRITEPROMPT", nooverwriteprompt); +} + +static void iParamSetListItems(char* extra, Ihandle* param) +{ + int d = 1, count; + char str[20], *item; + + if (!extra) + return; + + item = iParamGetNextStrItem(extra, '|', &count); extra += count; + while (*item) + { + sprintf(str, "%d", d); + iupAttribStoreStr(param, str, item); + + item = iParamGetNextStrItem(extra, '|', &count); extra += count; + d++; + } + + sprintf(str, "%d", d); + iupAttribSetStr(param, str, ""); +} + +static char* iParamGetStrExtra(char* line, char start, char end, int *count) +{ + int i = 0, end_pos = -1; + + if (*line != start) + { + *count = 0; + return NULL; + } + line++; /* skip start */ + + while (line[i] != '\n' && line[i] != 0) + { + if (line[i] == end) + end_pos = i; + + i++; + } + + if (end_pos != -1) + { + line[end_pos] = 0; + *count = 1+end_pos+1; + return line; + } + else + { + *count = 0; + return NULL; + } +} + +static int iParamCopyStrLine(char* line, const char* format) +{ + int i = 0; + while (format[i] != '\n' && format[i] != 0) + { + line[i] = format[i]; + i++; + if (i > 4094) /* to avoid being bigger than the local array */ + break; + } + line[i] = '\n'; + line[i+1] = 0; + return i+1; +} + +char iupGetParamType(const char* format, int *line_size) +{ + char* type = strchr(format, '%'); + char* line_end = strchr(format, '\n'); + if (line_end) + *line_size = line_end-format+1; + if (type) + return *(type+1); + else + return 0; +} + +static Ihandle *IupParamf(const char* format, int *line_size) +{ + Ihandle* param; + char line[4096]; + char* line_ptr = &line[0], *title, type, *tip, *extra, *mask; + int count; + + *line_size = iParamCopyStrLine(line, format); + + title = iParamGetNextStrItem(line_ptr, '%', &count); line_ptr += count; + param = IupUser(); + iupAttribStoreStr(param, "TITLE", title); + + type = *line_ptr; + line_ptr++; + + switch(type) + { + case 'b': + iupAttribSetStr(param, "TYPE", "BOOLEAN"); + iupAttribSetStr(param, "DATA_TYPE", "1"); /* integer */ + extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count; + iParamSetBoolNames(extra, param); + break; + case 'l': + iupAttribSetStr(param, "TYPE", "LIST"); + iupAttribSetStr(param, "DATA_TYPE", "1"); /* integer */ + extra = iParamGetStrExtra(line_ptr, '|', '|', &count); line_ptr += count; + iParamSetListItems(extra, param); + break; + case 'a': + iupAttribSetStr(param, "TYPE", "REAL"); + iupAttribSetStr(param, "DATA_TYPE", "2"); /* real */ + iupAttribSetStr(param, "ANGLE", "1"); + extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count; + iParamSetInterval(extra, param); + break; + case 'm': + iupAttribSetStr(param, "MULTILINE", "1"); + /* continue */ + case 's': + iupAttribSetStr(param, "TYPE", "STRING"); + iupAttribSetStr(param, "DATA_TYPE", "0"); /* string */ + mask = iParamGetNextStrItem(line_ptr, '{', &count); + if (*mask) + iupAttribStoreStr(param, "MASK", mask); + line_ptr += count-1; /* ignore the fake separator */ + line_ptr[0] = '{'; /* restore possible separator */ + break; + case 'i': + iupAttribSetStr(param, "TYPE", "INTEGER"); + iupAttribSetStr(param, "DATA_TYPE", "1"); /* integer */ + extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count; + iParamSetInterval(extra, param); + break; + case 'r': + iupAttribSetStr(param, "TYPE", "REAL"); + iupAttribSetStr(param, "DATA_TYPE", "2"); /* real */ + extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count; + iParamSetInterval(extra, param); + break; + case 'f': + iupAttribSetStr(param, "TYPE", "FILE"); + iupAttribSetStr(param, "DATA_TYPE", "0"); /* string */ + extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count; + iParamSetFileOptions(extra, param); + break; + case 'c': + iupAttribSetStr(param, "TYPE", "COLOR"); + iupAttribSetStr(param, "DATA_TYPE", "0"); /* string */ + break; + case 't': + iupAttribSetStr(param, "TYPE", "SEPARATOR"); + iupAttribSetStr(param, "DATA_TYPE", "-1"); /* NONE */ + break; + default: + return NULL; + } + + tip = iParamGetStrExtra(line_ptr, '{', '}', &count); + if (tip) + iupAttribStoreStr(param, "TIP", tip); + + return param; +} + +/******************************************************************************************* + Exported Functions +*******************************************************************************************/ + +int iupGetParamCount(const char *format, int *param_extra) +{ + int param_count = 0, sep = 0; + const char* s = format; + + *param_extra = 0; + while(*s) + { + if (*s == '%' && *(s+1) == 't') /* do not count separator lines */ + { + sep = 1; + (*param_extra)++; + } + + if (*s == '\n') + { + if (sep) + sep = 0; + else + param_count++; + } + + s++; + } + + return param_count; +} + +static void iParamDestroyAll(Ihandle **params) +{ + int i = 0; + while (params[i] != NULL) + { + IupDestroy(params[i]); + i++; + } +} + +int IupGetParamv(const char* title, Iparamcb action, void* user_data, const char* format, int param_count, int param_extra, void** param_data) +{ + Ihandle *dlg, *params[50]; + int i, line_size, p; + + assert(title && format); + if (!title || !format) + return 0; + + for (i = 0, p = 0; i < param_count+param_extra; i++) + { + int data_type; + + params[i] = IupParamf(format, &line_size); + assert(params[i]); + if (!params[i]) + return 0; + + data_type = IupGetInt(params[i], "DATA_TYPE"); + if (data_type == 1) + { + int *data_int = (int*)(param_data[p]); + if (!data_int) return 0; + iupAttribSetStrf(params[i], "VALUE", "%d", *data_int); + p++; + } + else if (data_type == 2) + { + float *data_float = (float*)(param_data[p]); + if (!data_float) return 0; + iupAttribSetStrf(params[i], "VALUE", "%g", *data_float); + p++; + } + else if (data_type == 0) + { + char *data_str = (char*)(param_data[p]); + if (!data_str) return 0; + iupAttribStoreStr(params[i], "VALUE", data_str); + p++; + } + + format += line_size; + } + params[i] = NULL; + + dlg = IupParamDlgP(params); + IupSetAttribute(dlg, "TITLE", (char*)title); + IupSetCallback(dlg, "PARAM_CB", (Icallback)action); + iupAttribSetStr(dlg, "USER_DATA", (char*)user_data); + + if (action) + action(dlg, -2, user_data); + + IupPopup(dlg, IUP_CENTERPARENT, IUP_CENTERPARENT); + + if (!IupGetInt(dlg, "STATUS")) + { + iParamDestroyAll(params); + IupDestroy(dlg); + return 0; + } + else + { + for (i = 0, p = 0; i < param_count; i++) + { + Ihandle* param; + int data_type; + char str[20]; + + sprintf(str, "PARAM%d", i); + param = (Ihandle*)iupAttribGet(dlg, str); + + data_type = iupAttribGetInt(param, "DATA_TYPE"); + if (data_type == 1) + { + int *data_int = (int*)(param_data[i]); + *data_int = iupAttribGetInt(param, "VALUE"); + p++; + } + else if (data_type == 2) + { + float *data_float = (float*)(param_data[i]); + *data_float = iupAttribGetFloat(param, "VALUE"); + p++; + } + else + { + char *data_str = (char*)(param_data[i]); + strcpy(data_str, iupAttribGet(param, "VALUE")); + p++; + } + } + + iParamDestroyAll(params); + IupDestroy(dlg); + return 1; + } +} + +int IupGetParam(const char* title, Iparamcb action, void* user_data, const char* format,...) +{ + int param_count, param_extra, i; + void* param_data[50]; + va_list arg; + + param_count = iupGetParamCount(format, ¶m_extra); + + va_start(arg, format); + for (i = 0; i < param_count; i++) + { + param_data[i] = (void*)(va_arg(arg, void*)); + } + va_end(arg); + + return IupGetParamv(title, action, user_data, format, param_count, param_extra, param_data); +} + |