/** \file * \brief Zbox Control. * * See Copyright Notice in "iup.h" */ #include #include #include "iup.h" #include "iupcbs.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_varg.h" enum{IZBOX_ALIGN_NORTH, IZBOX_ALIGN_SOUTH, IZBOX_ALIGN_WEST, IZBOX_ALIGN_EAST, IZBOX_ALIGN_NE, IZBOX_ALIGN_SE, IZBOX_ALIGN_NW, IZBOX_ALIGN_SW, IZBOX_ALIGN_ACENTER}; struct _IcontrolData { int alignment; Ihandle* value_handle; }; static int iZboxCreateMethod(Ihandle* ih, void** params) { ih->data = iupALLOCCTRLDATA(); ih->data->alignment = IZBOX_ALIGN_NW; if (params) { Ihandle** iparams = (Ihandle**)params; while (*iparams) { IupAppend(ih, *iparams); iparams++; } } return IUP_NOERROR; } static void iZboxChildAddedMethod(Ihandle* ih, Ihandle* child) { /* make sure it has at least one name */ if (!iupAttribGetHandleName(child)) iupAttribSetHandleName(child); if (!ih->data->value_handle) { IupSetAttribute(child, "VISIBLE", IupGetAttribute(ih, "VISIBLE")); ih->data->value_handle = child; } else IupSetAttribute(child, "VISIBLE", "NO"); } static void iZboxChildRemovedMethod(Ihandle* ih, Ihandle* child, int pos) { (void)pos; if (child == ih->data->value_handle) { /* reset to the first child, even if it is NULL */ if (ih->firstchild) IupSetAttribute(ih->firstchild, "VISIBLE", IupGetAttribute(ih, "VISIBLE")); ih->data->value_handle = ih->firstchild; if (!iupAttribGetBoolean(ih, "CHILDSIZEALL")) IupRefresh(ih); } } static int iZboxSetAlignmentAttrib(Ihandle* ih, const char* value) { if (iupStrEqualNoCase(value, "NORTH") || iupStrEqualNoCase(value, "ATOP")) ih->data->alignment = IZBOX_ALIGN_NORTH; else if (iupStrEqualNoCase(value, "SOUTH") || iupStrEqualNoCase(value, "ABOTTOM")) ih->data->alignment = IZBOX_ALIGN_SOUTH; else if (iupStrEqualNoCase(value, "WEST") || iupStrEqualNoCase(value, "ALEFT")) ih->data->alignment = IZBOX_ALIGN_WEST; else if (iupStrEqualNoCase(value, "EAST") || iupStrEqualNoCase(value, "ARIGHT")) ih->data->alignment = IZBOX_ALIGN_EAST; else if (iupStrEqualNoCase(value, "NE")) ih->data->alignment = IZBOX_ALIGN_NE; else if (iupStrEqualNoCase(value, "SE")) ih->data->alignment = IZBOX_ALIGN_SE; else if (iupStrEqualNoCase(value, "NW")) ih->data->alignment = IZBOX_ALIGN_NW; else if (iupStrEqualNoCase(value, "SW")) ih->data->alignment = IZBOX_ALIGN_SW; else if (iupStrEqualNoCase(value, "ACENTER")) ih->data->alignment = IZBOX_ALIGN_ACENTER; return 0; } static char* iZboxGetAlignmentAttrib(Ihandle* ih) { static char* align2str[9] = {"NORTH", "SOUTH", "WEST", "EAST", "NE", "SE", "NW", "SW", "ACENTER"}; return align2str[ih->data->alignment]; } static int iZboxSetValueHandleAttrib(Ihandle* ih, const char* value) { int visible; Ihandle* old_handle, *new_handle, *child; new_handle = (Ihandle*)value; if (!iupObjectCheck(new_handle)) return 0; old_handle = ih->data->value_handle; if (!iupObjectCheck(old_handle)) old_handle = NULL; if (old_handle == new_handle) return 0; visible = IupGetInt(ih, "VISIBLE"); for (child = ih->firstchild; child; child = child->brother) { if (child == new_handle) /* found child */ { if (old_handle && old_handle != new_handle) IupSetAttribute(old_handle, "VISIBLE", "NO"); IupSetAttribute(new_handle, "VISIBLE", visible? "YES": "NO"); ih->data->value_handle = new_handle; if (!iupAttribGetBoolean(ih, "CHILDSIZEALL")) IupRefresh(ih); return 0; } } return 0; } static char* iZboxGetValueHandleAttrib(Ihandle* ih) { return (char*)(ih->data->value_handle); } static int iZboxSetValuePosAttrib(Ihandle* ih, const char* value) { Ihandle* child; int pos, i; if (!iupStrToInt(value, &pos)) return 0; for (i=0, child=ih->firstchild; child; child = child->brother, i++) { if (i == pos) /* found child */ { iZboxSetValueHandleAttrib(ih, (char*)child); return 0; } } return 0; } static char* iZboxGetValuePosAttrib(Ihandle* ih) { Ihandle* child; int pos; if (!iupObjectCheck(ih->data->value_handle)) return NULL; for (pos=0, child = ih->firstchild; child; child = child->brother, pos++) { if (child == ih->data->value_handle) /* found child */ return iupStrReturnInt(pos); } return NULL; } static int iZboxSetValueAttrib(Ihandle* ih, const char* value) { Ihandle *new_handle; if (!value) return 0; new_handle = IupGetHandle(value); if (!new_handle) return 0; iZboxSetValueHandleAttrib(ih, (char*)new_handle); return 0; } static char* iZboxGetValueAttrib(Ihandle* ih) { Ihandle* child; int pos; if (!iupObjectCheck(ih->data->value_handle)) return NULL; for (pos=0, child = ih->firstchild; child; child = child->brother, pos++) { if (child == ih->data->value_handle) /* found child, just checking */ return IupGetName(ih->data->value_handle); /* Name is guarantied at AddedMethod */ } return NULL; } static int iZboxSetVisibleAttrib(Ihandle* ih, const char* value) { if (iupObjectCheck(ih->data->value_handle)) IupSetAttribute(ih->data->value_handle, "VISIBLE", (char*)value); return 1; /* must be 1 to mark when set at the element */ } static void iZboxComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *children_expand) { Ihandle* child; int children_naturalwidth, children_naturalheight; int childSizeAll = iupAttribGetBoolean(ih, "CHILDSIZEALL"); /* calculate total children natural size (even for hidden children) */ children_naturalwidth = 0; children_naturalheight = 0; for (child = ih->firstchild; child; child = child->brother) { /* update child natural size first */ if (!(child->flags & IUP_FLOATING_IGNORE)) iupBaseComputeNaturalSize(child); if (!childSizeAll && child != ih->data->value_handle) continue; if (!(child->flags & IUP_FLOATING)) { *children_expand |= child->expand; children_naturalwidth = iupMAX(children_naturalwidth, child->naturalwidth); children_naturalheight = iupMAX(children_naturalheight, child->naturalheight); } } *w = children_naturalwidth; *h = children_naturalheight; } static void iZboxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink) { Ihandle* child; for (child = ih->firstchild; child; child = child->brother) { if (!(child->flags & IUP_FLOATING)) iupBaseSetCurrentSize(child, ih->currentwidth, ih->currentheight, shrink); } } static void iZboxSetChildrenPositionMethod(Ihandle* ih, int x, int y) { int dx = 0, dy = 0; Ihandle* child; for (child = ih->firstchild; child; child = child->brother) { if (!(child->flags & IUP_FLOATING)) { switch (ih->data->alignment) { case IZBOX_ALIGN_ACENTER: dx=(ih->currentwidth-child->currentwidth)/2; dy=(ih->currentheight-child->currentheight)/2; break; case IZBOX_ALIGN_NORTH: dx=(ih->currentwidth-child->currentwidth)/2; dy=0; break; case IZBOX_ALIGN_SOUTH: dx=(ih->currentwidth-child->currentwidth)/2; dy=ih->currentheight-child->currentheight; break; case IZBOX_ALIGN_WEST: dx=0; dy=(ih->currentheight-child->currentheight)/2; break; case IZBOX_ALIGN_EAST: dx=ih->currentwidth-child->currentwidth; dy=(ih->currentheight-child->currentheight)/2; break; case IZBOX_ALIGN_NE: dx=ih->currentwidth-child->currentwidth; dy=0; break; case IZBOX_ALIGN_SE: dx=ih->currentwidth-child->currentwidth; dy=ih->currentheight-child->currentheight; break; case IZBOX_ALIGN_SW: dx=0; dy=ih->currentheight-child->currentheight; break; case IZBOX_ALIGN_NW: default: dx=0; dy=0; break; } if (dx<0) dx = 0; if (dy<0) dy = 0; /* update child */ iupBaseSetPosition(child, x+dx, y+dy); } } } /******************************************************************************/ IUP_API Ihandle* IupZboxv(Ihandle **children) { return IupCreatev("zbox", (void**)children); } IUP_API Ihandle* IupZboxV(Ihandle* child, va_list arglist) { return IupCreateV("zbox", child, arglist); } IUP_API Ihandle* IupZbox(Ihandle* child, ...) { Ihandle *ih; va_list arglist; va_start(arglist, child); ih = IupCreateV("zbox", child, arglist); va_end(arglist); return ih; } Iclass* iupZboxNewClass(void) { Iclass* ic = iupClassNew(NULL); ic->name = "zbox"; ic->format = "g"; /* array of Ihandle */ ic->nativetype = IUP_TYPEVOID; ic->childtype = IUP_CHILDMANY; /* can have children */ ic->is_interactive = 0; /* Class functions */ ic->New = iupZboxNewClass; ic->Create = iZboxCreateMethod; ic->Map = iupBaseTypeVoidMapMethod; ic->ChildAdded = iZboxChildAddedMethod; ic->ChildRemoved = iZboxChildRemovedMethod; ic->ComputeNaturalSize = iZboxComputeNaturalSizeMethod; ic->SetChildrenCurrentSize = iZboxSetChildrenCurrentSizeMethod; ic->SetChildrenPosition = iZboxSetChildrenPositionMethod; /* Base Callbacks */ iupBaseRegisterBaseCallbacks(ic); /* Common */ iupBaseRegisterCommonAttrib(ic); /* Base Container */ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CLIENTSIZE", iupBaseGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CLIENTOFFSET", iupBaseGetClientOffsetAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* Zbox only */ iupClassRegisterAttribute(ic, "ALIGNMENT", iZboxGetAlignmentAttrib, iZboxSetAlignmentAttrib, IUPAF_SAMEASSYSTEM, "NW", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "VALUE", iZboxGetValueAttrib, iZboxSetValueAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "VALUEPOS", iZboxGetValuePosAttrib, iZboxSetValuePosAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "VALUE_HANDLE", iZboxGetValueHandleAttrib, iZboxSetValueHandleAttrib, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_NO_INHERIT | IUPAF_IHANDLE | IUPAF_NO_STRING); iupClassRegisterAttribute(ic, "CHILDSIZEALL", NULL, NULL, IUPAF_SAMEASSYSTEM, "Yes", IUPAF_NO_INHERIT); /* Intercept VISIBLE since ZBOX works by showing and hiding its children */ iupClassRegisterAttribute(ic, "VISIBLE", NULL, iZboxSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_SAVE|IUPAF_NOT_MAPPED); return ic; }