/** \file * \brief List Control * * See Copyright Notice in "iup.h" */ #include #include #include #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= 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; }