/** \file * \brief GLScrollBox control * * See Copyright Notice in "iup.h" */ #include #include #include #include #include "iup.h" #include "iupcbs.h" #include "iupglcontrols.h" #include "iup_object.h" #include "iup_register.h" #include "iup_attrib.h" #include "iup_str.h" #include "iup_layout.h" #include "iup_glcontrols.h" #include "iup_glscrollbars.h" #include "iup_glsubcanvas.h" static int iGLScrollBoxBUTTON_CB(Ihandle *ih, int button, int pressed, int x, int y, char* status) { if (button != IUP_BUTTON1) return IUP_DEFAULT; if (iupGLScrollbarsButton(ih, pressed, x, y)) iupGLSubCanvasRedraw(ih); (void)status; return IUP_DEFAULT; } static int iGLScrollBoxMOTION_CB(Ihandle *ih, int x, int y, char* status) { if (iupGLScrollbarsMotion(ih, x, y)) iupGLSubCanvasRedraw(ih); (void)status; return IUP_DEFAULT; } static int iGLScrollBoxENTERWINDOW_CB(Ihandle* ih, int x, int y) { iupGLScrollbarsEnterWindow(ih, x, y); return iupGLSubCanvasRedraw(ih); } static int iGLScrollBoxLEAVEWINDOW_CB(Ihandle* ih) { iupGLScrollbarsLeaveWindow(ih); return iupGLSubCanvasRedraw(ih); } static int iGLScrollBoxACTION_CB(Ihandle* ih) { int active = iupAttribGetInt(ih, "ACTIVE"); iupGLScrollbarsDraw(ih, active); return IUP_DEFAULT; } static char* iGLScrollBoxGetClientSizeAttrib(Ihandle* ih) { int dx = iupAttribGetInt(ih, "DX"); int dy = iupAttribGetInt(ih, "DY"); return iupStrReturnIntInt(dx, dy, 'x'); } /*****************************************************************************\ |* Methods *| \*****************************************************************************/ static void iGLScrollBoxComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *children_expand) { if (ih->firstchild) { /* update child natural size first */ iupBaseComputeNaturalSize(ih->firstchild); } /* ScrollBox size does not depends on the child size, its natural size must be 0 to be free of restrictions. */ (void)w; (void)h; /* Also set expand to its own expand so it will not depend on children */ *children_expand = ih->expand; } static void iGLScrollBoxUpdateVisibleScrollArea(Ihandle* ih, int view_width, int view_height) { /* this is available drawing size not considering the scrollbars (there is no border here) */ int canvas_width = ih->currentwidth, canvas_height = ih->currentheight; int sb_size = iupGLScrollbarsGetSize(ih); /* if child is greater than scrollbox in one direction, then it has scrollbars but this affects the opposite direction */ if (view_width > ih->currentwidth) /* check for horizontal scrollbar */ canvas_height -= sb_size; /* affect vertical size */ if (view_height > ih->currentheight) canvas_width -= sb_size; if (view_width <= ih->currentwidth && view_width > canvas_width) canvas_height -= sb_size; if (view_height <= ih->currentheight && view_height > canvas_height) canvas_width -= sb_size; if (canvas_width < 0) canvas_width = 0; if (canvas_height < 0) canvas_height = 0; iupAttribSetInt(ih, "DX", canvas_width); iupAttribSetInt(ih, "DY", canvas_height); iupGLScrollbarsCheckPosX(ih); iupGLScrollbarsCheckPosY(ih); } static void iGLScrollBoxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink) { Ihandle* child = ih->firstchild; if (child) { int w, h, has_sb_horiz=0, has_sb_vert=0; int sb_size = iupGLScrollbarsGetSize(ih); /* If child is greater than scrollbox area, use child natural size, else use current scrollbox size; So this will let the child be greater than the scrollbox, or let the child expand to the scrollbox. */ if (child->naturalwidth > ih->currentwidth) { w = child->naturalwidth; has_sb_horiz = 1; } else w = ih->currentwidth; /* expand space */ if (child->naturalheight > ih->currentheight) { h = child->naturalheight; has_sb_vert = 1; } else h = ih->currentheight; /* expand space */ if (!has_sb_horiz && has_sb_vert) w -= sb_size; /* reduce expand space */ if (has_sb_horiz && !has_sb_vert) h -= sb_size; /* reduce expand space */ /* Now w and h is a possible child size */ iupBaseSetCurrentSize(child, w, h, shrink); /* Now we use the actual child size as the virtual area */ iupAttribSetInt(ih, "XMAX", child->currentwidth); iupAttribSetInt(ih, "YMAX", child->currentheight); /* Finally update the visible area */ iGLScrollBoxUpdateVisibleScrollArea(ih, child->currentwidth, child->currentheight); } else { iupAttribSet(ih, "XMAX", "0"); iupAttribSet(ih, "YMAX", "0"); iupAttribSet(ih, "DX", "0"); iupAttribSet(ih, "DY", "0"); iupAttribSet(ih, "POSX", "0"); iupAttribSet(ih, "POSY", "0"); } } static void iGLScrollBoxSetChildrenPositionMethod(Ihandle* ih, int x, int y) { if (ih->firstchild) { iupBaseSetPosition(ih->firstchild, x - iupAttribGetInt(ih, "POSX"), y - iupAttribGetInt(ih, "POSY")); } } static int iGLScrollBoxCreateMethod(Ihandle* ih, void** params) { IupSetCallback(ih, "GL_ACTION", (Icallback)iGLScrollBoxACTION_CB); IupSetCallback(ih, "GL_BUTTON_CB", (Icallback)iGLScrollBoxBUTTON_CB); IupSetCallback(ih, "GL_MOTION_CB", (Icallback)iGLScrollBoxMOTION_CB); IupSetCallback(ih, "GL_LEAVEWINDOW_CB", (Icallback)iGLScrollBoxLEAVEWINDOW_CB); IupSetCallback(ih, "GL_ENTERWINDOW_CB", (Icallback)iGLScrollBoxENTERWINDOW_CB); if (params) { Ihandle** iparams = (Ihandle**)params; if (iparams[0]) IupAppend(ih, iparams[0]); } return IUP_NOERROR; } Iclass* iupGLScrollBoxNewClass(void) { Iclass* ic = iupClassNew(iupRegisterFindClass("glsubcanvas")); ic->name = "glscrollbox"; ic->cons = "GLScrollBox"; ic->format = "h"; /* one Ihandle* */ ic->nativetype = IUP_TYPEVOID; ic->childtype = IUP_CHILDMANY+1; /* 1 child */ ic->is_interactive = 0; /* Class functions */ ic->New = iupGLScrollBoxNewClass; ic->Create = iGLScrollBoxCreateMethod; ic->ComputeNaturalSize = iGLScrollBoxComputeNaturalSizeMethod; ic->SetChildrenCurrentSize = iGLScrollBoxSetChildrenCurrentSizeMethod; ic->SetChildrenPosition = iGLScrollBoxSetChildrenPositionMethod; /* Base Container */ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CLIENTSIZE", iGLScrollBoxGetClientSizeAttrib, 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); iupGLScrollbarsRegisterAttrib(ic); return ic; } Ihandle* IupGLScrollBox(Ihandle* child) { void *children[2]; children[0] = (void*)child; children[1] = NULL; return IupCreatev("glscrollbox", children); }