/** \file * \brief iupsbox control * * See Copyright Notice in "iup.h" */ #include #include #include #include #include "iup.h" #include "iupglcontrols.h" #include "iup_object.h" #include "iup_attrib.h" #include "iup_str.h" #include "iup_register.h" #include "iup_layout.h" #include "iup_glcontrols.h" #include "iup_gldraw.h" #include "iup_glsubcanvas.h" #define ISBOX_THICK 4 enum { ISBOX_VERTICAL=1, ISBOX_HORIZONTAL=2, ISBOX_BOTH=3 }; struct _IcontrolData { int isholding, hold_resizer; int start_x, start_y; int start_w, start_h; int resizers; }; static int iGLSizeBoxGetYborder(Ihandle* ih) { if (ih->data->resizers & ISBOX_VERTICAL) return ISBOX_THICK; else return 0; } static int iGLSizeBoxGetXborder(Ihandle* ih) { if (ih->data->resizers & ISBOX_HORIZONTAL) return ISBOX_THICK; else return 0; } static int iGLSizeBoxSetCursor(Ihandle* ih, int x, int y) { int resizer = 0; if (ih->data->resizers & ISBOX_HORIZONTAL) { if (x >= ih->currentwidth - 1 - ISBOX_THICK) resizer = ISBOX_HORIZONTAL; } if (ih->data->resizers & ISBOX_VERTICAL) { if (y >= ih->currentheight - 1 - ISBOX_THICK) { if (resizer != 0) resizer = ISBOX_BOTH; else resizer = ISBOX_VERTICAL; } } if (resizer == ISBOX_HORIZONTAL) iupAttribSet(ih, "CURSOR", "RESIZE_WE"); else if (resizer == ISBOX_VERTICAL) iupAttribSet(ih, "CURSOR", "RESIZE_NS"); else if (resizer == ISBOX_BOTH) iupAttribSet(ih, "CURSOR", "RESIZE_NW"); else iupAttribSet(ih, "CURSOR", NULL); return resizer; } static void iGLSizeBoxResizeChild(Ihandle* ih, int resizer, int w, int h) { Ihandle* gl_parent = (Ihandle*)iupAttribGet(ih, "_IUP_GLCANVAS_PARENT"); Ihandle* child = ih->firstchild; int redraw = 0; iupLayoutApplyMinMaxSize(child, &w, &h); if (resizer & ISBOX_HORIZONTAL) { if (w != child->currentwidth) { child->userwidth = w; redraw = 1; } } if (resizer & ISBOX_VERTICAL) { if (h != child->currentheight) { child->userheight = h; redraw = 1; } } if (redraw) { IupRefreshChildren(gl_parent); /* this will recompute the layout of the glcanvasbox only */ IupSetAttribute(gl_parent, "REDRAW", NULL); /* redraw the whole box */ } } /*****************************************************************************\ |* Callbacks of canvas bar *| \*****************************************************************************/ static int iGLSizeBoxBUTTON_CB(Ihandle* ih, int button, int pressed, int x, int y, char* status) { Ihandle* child = ih->firstchild; ih->data->isholding = 0; if (button != IUP_BUTTON1 || !child) return IUP_DEFAULT; if (pressed) { ih->data->hold_resizer = iGLSizeBoxSetCursor(ih, x, y); if (ih->data->hold_resizer) { ih->data->isholding = 1; /* Save the cursor position */ ih->data->start_x = ih->x + x; ih->data->start_y = ih->y + y; /* Save the initial size */ ih->data->start_w = child->currentwidth; ih->data->start_h = child->currentheight; } } (void)status; return IUP_DEFAULT; } static int iGLSizeBoxMOTION_CB(Ihandle* ih, int x, int y, char* status) { iGLSizeBoxSetCursor(ih, x, y); if (!iup_isbutton1(status)) ih->data->isholding = 0; if (ih->data->isholding) { int final_x = ih->x + x; int final_y = ih->y + y; int diff_x = final_x - ih->data->start_x; int diff_y = final_y - ih->data->start_y; int w = diff_x + ih->data->start_w; int h = diff_y + ih->data->start_h; iGLSizeBoxResizeChild(ih, ih->data->hold_resizer, w, h); } return IUP_DEFAULT; } static int iGLSizeBoxACTION_CB(Ihandle* ih) { int active = iupAttribGetInt(ih, "ACTIVE"); char* fgcolor = iupAttribGetStr(ih, "FORECOLOR"); int xmin, xmax, ymin, ymax; if (ih->data->resizers & ISBOX_HORIZONTAL) { xmin = ih->currentwidth - ISBOX_THICK; xmax = ih->currentwidth - 1; ymin = 0; ymax = ih->currentheight - 1; iupGLDrawBox(ih, xmin, xmax, ymin, ymax, fgcolor, active); } if (ih->data->resizers & ISBOX_VERTICAL) { xmin = 0; xmax = ih->currentwidth - 1; ymin = ih->currentheight - ISBOX_THICK; ymax = ih->currentheight - 1; iupGLDrawBox(ih, xmin, xmax, ymin, ymax, fgcolor, active); } return IUP_DEFAULT; } static int iGLSizeBoxENTERWINDOW_CB(Ihandle* ih, int x, int y) { iGLSizeBoxSetCursor(ih, x, y); return iupGLSubCanvasRedraw(ih); } static int iGLSizeBoxLEAVEWINDOW_CB(Ihandle* ih) { iupAttribSet(ih, "CURSOR", NULL); return iupGLSubCanvasRedraw(ih); } /*****************************************************************************\ |* Attributes *| \*****************************************************************************/ static char* iGLSizeBoxGetClientSizeAttrib(Ihandle* ih) { int width = ih->currentwidth - iGLSizeBoxGetXborder(ih); int height = ih->currentheight - iGLSizeBoxGetYborder(ih); if (width < 0) width = 0; if (height < 0) height = 0; return iupStrReturnIntInt(width, height, 'x'); } static int iGLSizeBoxSetResizersAttrib(Ihandle* ih, const char* value) { if (iupStrEqualNoCase(value, "VERTICAL")) ih->data->resizers = ISBOX_VERTICAL; else if(iupStrEqualNoCase(value, "HORIZONTAL")) ih->data->resizers = ISBOX_HORIZONTAL; else /* Default = BOTH */ ih->data->resizers = ISBOX_BOTH; return 0; /* do not store value in hash table */ } static char* iGLSizeBoxGetResizersAttrib(Ihandle* ih) { if (ih->data->resizers == ISBOX_HORIZONTAL) return "HORIZONTAL"; else if (ih->data->resizers == ISBOX_VERTICAL) return "VERTICAL"; else return "BOTH"; } /*****************************************************************************\ |* Methods *| \*****************************************************************************/ static void iGLSizeBoxComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *children_expand) { int natural_w = iGLSizeBoxGetXborder(ih); int natural_h = iGLSizeBoxGetYborder(ih); Ihandle* child = ih->firstchild; if (child) { /* update child natural size first */ iupBaseComputeNaturalSize(child); natural_w += child->naturalwidth; natural_h += child->naturalheight; *children_expand = child->expand; } *w = natural_w; *h = natural_h; } static void iGLSizeBoxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink) { if (ih->firstchild) { int width = ih->currentwidth - iGLSizeBoxGetXborder(ih); int height = ih->currentheight - iGLSizeBoxGetYborder(ih); if (width < 0) width = 0; if (height < 0) height = 0; iupBaseSetCurrentSize(ih->firstchild, width, height, shrink); } } static void iGLSizeBoxSetChildrenPositionMethod(Ihandle* ih, int x, int y) { if (ih->firstchild) iupBaseSetPosition(ih->firstchild, x, y); } static int iGLSizeBoxCreateMethod(Ihandle* ih, void** params) { ih->data = iupALLOCCTRLDATA(); ih->data->resizers = ISBOX_BOTH; /* Setting callbacks */ IupSetCallback(ih, "GL_ACTION", (Icallback)iGLSizeBoxACTION_CB); IupSetCallback(ih, "GL_BUTTON_CB", (Icallback)iGLSizeBoxBUTTON_CB); IupSetCallback(ih, "GL_MOTION_CB", (Icallback)iGLSizeBoxMOTION_CB); IupSetCallback(ih, "GL_LEAVEWINDOW_CB", iGLSizeBoxLEAVEWINDOW_CB); IupSetCallback(ih, "GL_ENTERWINDOW_CB", (Icallback)iGLSizeBoxENTERWINDOW_CB); if (params) { Ihandle** iparams = (Ihandle**)params; if (*iparams) IupAppend(ih, *iparams); } return IUP_NOERROR; } Iclass* iupGLSizeBoxNewClass(void) { Iclass* ic = iupClassNew(iupRegisterFindClass("glsubcanvas")); ic->name = "glsizebox"; ic->cons = "GLSizeBox"; ic->format = "h"; /* one Ihandle* */ ic->nativetype = IUP_TYPEVOID; ic->childtype = IUP_CHILDMANY+1; /* 1 child */ ic->is_interactive = 0; /* Class functions */ ic->New = iupGLSizeBoxNewClass; ic->Create = iGLSizeBoxCreateMethod; ic->Map = iupBaseTypeVoidMapMethod; ic->ComputeNaturalSize = iGLSizeBoxComputeNaturalSizeMethod; ic->SetChildrenCurrentSize = iGLSizeBoxSetChildrenCurrentSizeMethod; ic->SetChildrenPosition = iGLSizeBoxSetChildrenPositionMethod; /* Base Container */ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CLIENTSIZE", iGLSizeBoxGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_READONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CLIENTOFFSET", iupBaseGetClientOffsetAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_READONLY | IUPAF_NO_INHERIT); /* Visual */ iupClassRegisterAttribute(ic, "FORECOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "90 190 255", IUPAF_NO_INHERIT); /* IupSizeBox only */ iupClassRegisterAttribute(ic, "RESIZERS", iGLSizeBoxGetResizersAttrib, iGLSizeBoxSetResizersAttrib, IUPAF_SAMEASSYSTEM, "BOTH", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); return ic; } Ihandle* IupGLSizeBox(Ihandle* child) { void *children[2]; children[0] = (void*)child; children[1] = NULL; return IupCreatev("glsizebox", children); }