summaryrefslogtreecommitdiff
path: root/iup/src/iup_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'iup/src/iup_list.c')
-rwxr-xr-xiup/src/iup_list.c711
1 files changed, 711 insertions, 0 deletions
diff --git a/iup/src/iup_list.c b/iup/src/iup_list.c
new file mode 100755
index 0000000..5965665
--- /dev/null
+++ b/iup/src/iup_list.c
@@ -0,0 +1,711 @@
+/** \file
+ * \brief List Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_assert.h"
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_layout.h"
+#include "iup_mask.h"
+#include "iup_list.h"
+
+
+void iupListSingleCallDblClickCallback(Ihandle* ih, IFnis cb, int pos)
+{
+ char *text;
+ char str[30];
+
+ if (pos<=0)
+ return;
+
+ sprintf(str, "%d", pos);
+ text = IupGetAttribute(ih, str);
+
+ if (cb(ih, pos, text) == IUP_CLOSE)
+ IupExitLoop();
+}
+
+static void iListCallActionCallback(Ihandle* ih, IFnsii cb, int pos, int state)
+{
+ char *text;
+ char str[30];
+
+ if (pos<=0)
+ return;
+
+ sprintf(str, "%d", pos);
+ text = IupGetAttribute(ih, str);
+
+ if (cb(ih, text, pos, state) == IUP_CLOSE)
+ IupExitLoop();
+}
+
+void iupListSingleCallActionCallback(Ihandle* ih, IFnsii cb, int pos)
+{
+ char* old_str = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
+ if (old_str)
+ {
+ int oldpos = atoi(old_str);
+ if (oldpos != pos)
+ {
+ iListCallActionCallback(ih, cb, oldpos, 0);
+ iListCallActionCallback(ih, cb, pos, 1);
+ }
+ }
+ else
+ iListCallActionCallback(ih, cb, pos, 1);
+ iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", pos);
+}
+
+void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, int* pos, int sel_count)
+{
+ int i, count = iupdrvListGetCount(ih);
+
+ char* old_str = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
+ int old_count = old_str? strlen(old_str): 0;
+
+ char* str = iupStrGetMemory(count+1);
+ memset(str, '-', count);
+ str[count]=0;
+ for (i=0; i<sel_count; i++)
+ str[pos[i]] = '+';
+
+ if (old_count != count)
+ {
+ old_count = 0;
+ old_str = NULL;
+ }
+
+ if (multi_cb)
+ {
+ int unchanged = 1;
+ for (i=0; i<count && old_str; i++)
+ {
+ if (str[i] == old_str[i])
+ str[i] = 'x'; /* mark unchanged values */
+ else
+ unchanged = 0;
+ }
+
+ if (old_str && unchanged)
+ return;
+
+ if (multi_cb(ih, str) == IUP_CLOSE)
+ IupExitLoop();
+
+ for (i=0; i<count && old_str; i++)
+ {
+ if (str[i] == 'x')
+ str[i] = old_str[i]; /* restore unchanged values */
+ }
+ }
+ else
+ {
+ /* must simulate the click on each item */
+ for (i=0; i<count; i++)
+ {
+ if (i >= old_count) /* new items, if selected then call the callback */
+ {
+ if (str[i] == '+')
+ iListCallActionCallback(ih, cb, i+1, 1);
+ }
+ else if (str[i] != old_str[i])
+ {
+ if (str[i] == '+')
+ iListCallActionCallback(ih, cb, i+1, 1);
+ else
+ iListCallActionCallback(ih, cb, i+1, 0);
+ }
+ }
+ }
+
+ iupAttribStoreStr(ih, "_IUPLIST_OLDVALUE", str);
+}
+
+int iupListGetPos(Ihandle* ih, const char* name_id)
+{
+ int pos;
+ if (iupStrToInt(name_id, &pos))
+ {
+ int count = iupdrvListGetCount(ih);
+
+ pos--; /* IUP items start at 1 */
+
+ if (pos < 0) return -1;
+ if (pos > count-1) return -1;
+
+ return pos;
+ }
+ return -1;
+}
+
+void iupListSetInitialItems(Ihandle* ih)
+{
+ char str[20], *value;
+ int i = 1;
+ sprintf(str, "%d", i);
+ while ((value = iupAttribGet(ih, str))!=NULL)
+ {
+ iupdrvListAppendItem(ih, value);
+ iupAttribSetStr(ih, str, NULL);
+
+ i++;
+ sprintf(str, "%d", i);
+ }
+}
+
+char* iupListGetSpacingAttrib(Ihandle* ih)
+{
+ if (!ih->data->is_dropdown)
+ {
+ char *str = iupStrGetMemory(50);
+ sprintf(str, "%d", ih->data->spacing);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+char* iupListGetPaddingAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ char *str = iupStrGetMemory(50);
+ sprintf(str, "%dx%d", ih->data->horiz_padding, ih->data->vert_padding);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+char* iupListGetNCAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ char* str = iupStrGetMemory(100);
+ sprintf(str, "%d", ih->data->nc);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+int iupListSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int pos;
+ if (iupStrToInt(name_id, &pos))
+ {
+ int count = iupdrvListGetCount(ih);
+
+ pos--; /* IUP starts at 1 */
+
+ if (!value)
+ {
+ if (pos >= 0 && pos <= count-1)
+ {
+ if (pos == 0)
+ iupdrvListRemoveAllItems(ih);
+ else
+ {
+ int i = pos;
+ while (i < count)
+ {
+ iupdrvListRemoveItem(ih, pos);
+ i++;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (pos >= 0 && pos <= count-1)
+ {
+ iupdrvListRemoveItem(ih, pos);
+ iupdrvListInsertItem(ih, pos, value);
+ }
+ else if (pos == count)
+ iupdrvListAppendItem(ih, value);
+ }
+ }
+ return 1;
+}
+
+static int iListSetAppendItemAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ if (value)
+ iupdrvListAppendItem(ih, value);
+ return 0;
+}
+
+static int iListSetInsertItemAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ if (value)
+ {
+ int pos = iupListGetPos(ih, name_id);
+ if (pos!=-1)
+ iupdrvListInsertItem(ih, pos, value);
+ }
+ return 0;
+}
+
+static int iListSetRemoveItemAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ if (!value)
+ iupdrvListRemoveAllItems(ih);
+ else
+ {
+ int pos = iupListGetPos(ih, value);
+ if (pos!=-1)
+ iupdrvListRemoveItem(ih, pos);
+ }
+ return 0;
+}
+
+static int iListGetCount(Ihandle* ih)
+{
+ int count;
+ if (ih->handle)
+ count = iupdrvListGetCount(ih);
+ else
+ {
+ char str[20];
+ count = 0;
+ sprintf(str, "%d", count+1);
+ while (iupAttribGet(ih, str))
+ {
+ count++;
+ sprintf(str, "%d", count+1);
+ }
+ }
+ return count;
+}
+
+static char* iListGetCountAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(50);
+ sprintf(str, "%d", iListGetCount(ih));
+ return str;
+}
+
+static int iListSetDropdownAttrib(Ihandle* ih, const char* value)
+{
+ /* valid only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrBoolean(value))
+ {
+ ih->data->is_dropdown = 1;
+ ih->data->is_multiple = 0;
+ }
+ else
+ ih->data->is_dropdown = 0;
+
+ return 0;
+}
+
+static char* iListGetDropdownAttrib(Ihandle* ih)
+{
+ if (ih->data->is_dropdown)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iListSetMultipleAttrib(Ihandle* ih, const char* value)
+{
+ /* valid only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrBoolean(value))
+ {
+ ih->data->is_multiple = 1;
+ ih->data->is_dropdown = 0;
+ ih->data->has_editbox = 0;
+ }
+ else
+ ih->data->is_multiple = 0;
+
+ return 0;
+}
+
+static char* iListGetMultipleAttrib(Ihandle* ih)
+{
+ if (ih->data->is_multiple)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iListSetEditboxAttrib(Ihandle* ih, const char* value)
+{
+ /* valid only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrBoolean(value))
+ {
+ ih->data->has_editbox = 1;
+ ih->data->is_multiple = 0;
+ }
+ else
+ ih->data->has_editbox = 0;
+
+ return 0;
+}
+
+static char* iListGetEditboxAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iListSetScrollbarAttrib(Ihandle* ih, const char* value)
+{
+ /* valid only before map */
+ if (ih->handle)
+ return 0;
+
+ else if (iupStrBoolean(value))
+ ih->data->sb = 1;
+ else
+ ih->data->sb = 0;
+
+ return 0;
+}
+
+static char* iListGetScrollbarAttrib(Ihandle* ih)
+{
+ if (ih->data->sb)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iListGetMaskDataAttrib(Ihandle* ih)
+{
+ if (!ih->data->has_editbox)
+ return NULL;
+
+ /* Used only by the OLD iupmask API */
+ return (char*)ih->data->mask;
+}
+
+static int iListSetMaskAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ {
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+ }
+ else
+ {
+ int casei = iupAttribGetInt(ih, "MASKCASEI");
+ Imask* mask = iupMaskCreate(value,casei);
+ if (mask)
+ {
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+
+ ih->data->mask = mask;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int iListSetMaskIntAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ {
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+
+ iupAttribSetStr(ih, "MASK", NULL);
+ }
+ else
+ {
+ Imask* mask;
+ int min, max;
+
+ if (iupStrToIntInt(value, &min, &max, ':')!=2)
+ return 0;
+
+ mask = iupMaskCreateInt(min,max);
+
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+
+ ih->data->mask = mask;
+
+ if (min < 0)
+ iupAttribSetStr(ih, "MASK", IUP_MASK_INT);
+ else
+ iupAttribSetStr(ih, "MASK", IUP_MASK_UINT);
+ }
+
+ return 0;
+}
+
+static int iListSetMaskFloatAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ {
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+
+ iupAttribSetStr(ih, "MASK", NULL);
+ }
+ else
+ {
+ Imask* mask;
+ float min, max;
+
+ if (iupStrToFloatFloat(value, &min, &max, ':')!=2)
+ return 0;
+
+ mask = iupMaskCreateFloat(min,max);
+
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+
+ ih->data->mask = mask;
+
+ if (min < 0)
+ iupAttribSetStr(ih, "MASK", IUP_MASK_FLOAT);
+ else
+ iupAttribSetStr(ih, "MASK", IUP_MASK_UFLOAT);
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************************/
+
+
+static int iListCreateMethod(Ihandle* ih, void** params)
+{
+ if (params && params[0])
+ iupAttribStoreStr(ih, "ACTION", (char*)(params[0]));
+
+ ih->data = iupALLOCCTRLDATA();
+ ih->data->sb = 1;
+
+ return IUP_NOERROR;
+}
+
+static void iListGetNaturalItemsSize(Ihandle *ih, int *w, int *h)
+{
+ char *value;
+ int visiblecolumns,
+ count = iListGetCount(ih);
+
+ *w = 0;
+ *h = 0;
+
+ iupdrvFontGetCharSize(ih, w, h); /* one line height, and one character width */
+
+ visiblecolumns = iupAttribGetInt(ih, "VISIBLECOLUMNS");
+ if (visiblecolumns)
+ {
+ *w = iupdrvFontGetStringWidth(ih, "WWWWWWWWWW");
+ *w = (visiblecolumns*(*w))/10;
+ }
+ else
+ {
+ int item_w, i;
+ char str[20];
+
+ for (i=1; i<=count; i++)
+ {
+ sprintf(str, "%d", i);
+ value = IupGetAttribute(ih, str); /* must use IupGetAttribute to check the native system */
+ if (value)
+ {
+ item_w = iupdrvFontGetStringWidth(ih, value);
+ if (item_w > *w)
+ *w = item_w;
+ }
+ }
+
+ if (*w == 0) /* default is 5 characters in 1 item */
+ *w = iupdrvFontGetStringWidth(ih, "WWWWW");
+ }
+
+ /* compute height for multiple lines, drodown is just 1 line */
+ if (!ih->data->is_dropdown)
+ {
+ int visiblelines, num_lines, line_size = *h;
+
+ iupdrvListAddItemSpace(ih, h); /* this independs from spacing */
+
+ *h += 2*ih->data->spacing; /* this will be multiplied by the number of lines */
+ *w += 2*ih->data->spacing; /* include also horizontal spacing */
+
+ num_lines = count;
+ if (num_lines == 0) num_lines = 1;
+
+ visiblelines = iupAttribGetInt(ih, "VISIBLELINES");
+ if (visiblelines)
+ num_lines = visiblelines;
+
+ *h = *h * num_lines;
+
+ if (ih->data->has_editbox)
+ *h += line_size;
+ }
+}
+
+static void iListComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+{
+ int natural_w, natural_h;
+ int sb_size = iupdrvGetScrollbarSize();
+ (void)expand; /* unset if not a container */
+
+ iListGetNaturalItemsSize(ih, &natural_w, &natural_h);
+
+ /* compute the borders space */
+ iupdrvListAddBorders(ih, &natural_w, &natural_h);
+
+ if (ih->data->is_dropdown)
+ {
+ /* add room for dropdown box */
+ natural_w += sb_size;
+
+ if (natural_h < sb_size)
+ natural_h = sb_size;
+ }
+ else
+ {
+ /* add room for scrollbar */
+ if (ih->data->sb)
+ {
+ natural_h += sb_size;
+ natural_w += sb_size;
+ }
+ }
+
+ if (ih->data->has_editbox)
+ {
+ natural_w += 2*ih->data->horiz_padding;
+ natural_h += 2*ih->data->vert_padding;
+ }
+
+ *w = natural_w;
+ *h = natural_h;
+}
+
+static void iListDestroyMethod(Ihandle* ih)
+{
+ if (ih->data->mask)
+ iupMaskDestroy(ih->data->mask);
+}
+
+
+/******************************************************************************/
+
+
+Ihandle* IupList(const char* action)
+{
+ void *params[2];
+ params[0] = (void*)action;
+ params[1] = NULL;
+ return IupCreatev("list", params);
+}
+
+Iclass* iupListGetClass(void)
+{
+ Iclass* ic = iupClassNew(NULL);
+
+ ic->name = "list";
+ ic->format = "A"; /* one optional callback name */
+ ic->nativetype = IUP_TYPECONTROL;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+ ic->has_attrib_id = 1;
+
+ /* Class functions */
+ ic->Create = iListCreateMethod;
+ ic->Destroy = iListDestroyMethod;
+ ic->ComputeNaturalSize = iListComputeNaturalSizeMethod;
+
+ ic->LayoutUpdate = iupdrvBaseLayoutUpdateMethod;
+ ic->UnMap = iupdrvBaseUnMapMethod;
+
+ /* Callbacks */
+ iupClassRegisterCallback(ic, "ACTION", "sii");
+ iupClassRegisterCallback(ic, "MULTISELECT_CB", "s");
+ iupClassRegisterCallback(ic, "DROPFILES_CB", "siii");
+ iupClassRegisterCallback(ic, "DROPDOWN_CB", "i");
+ iupClassRegisterCallback(ic, "DBLCLICK_CB", "is");
+ iupClassRegisterCallback(ic, "VALUECHANGED_CB", "");
+
+ iupClassRegisterCallback(ic, "EDIT_CB", "is");
+ iupClassRegisterCallback(ic, "CARET_CB", "iii");
+
+ /* Common Callbacks */
+ iupBaseRegisterCommonCallbacks(ic);
+
+ /* Common */
+ iupBaseRegisterCommonAttrib(ic);
+
+ /* Visual */
+ iupBaseRegisterVisualAttrib(ic);
+
+ /* IupList only */
+ iupClassRegisterAttribute(ic, "SCROLLBAR", iListGetScrollbarAttrib, iListSetScrollbarAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MULTIPLE", iListGetMultipleAttrib, iListSetMultipleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DROPDOWN", iListGetDropdownAttrib, iListSetDropdownAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EDITBOX", iListGetEditboxAttrib, iListSetEditboxAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "COUNT", iListGetCountAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "INSERTITEM", NULL, iListSetInsertItemAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "APPENDITEM", NULL, iListSetAppendItemAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "REMOVEITEM", NULL, iListSetRemoveItemAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AUTOHIDE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "MASKCASEI", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MASK", NULL, iListSetMaskAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MASKINT", NULL, iListSetMaskIntAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MASKFLOAT", NULL, iListSetMaskFloatAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "OLD_MASK_DATA", iListGetMaskDataAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "VISIBLECOLUMNS", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VISIBLELINES", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupdrvListInitClass(ic);
+
+ return ic;
+}