/** \file * \brief GLExpander 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_attrib.h" #include "iup_str.h" #include "iup_register.h" #include "iup_glcontrols.h" #include "iup_glfont.h" #include "iup_gldraw.h" #include "iup_glimage.h" #include "iup_glsubcanvas.h" #define IEXPAND_BUTTON_SIZE 16 #define IEXPAND_HANDLE_SIZE 20 #define IEXPAND_SPACING 3 #define IEXPAND_BACK_MARGIN 2 /* used only when TOP && (title||image||extra_buttons) */ enum { IEXPANDER_LEFT, IEXPANDER_RIGHT, IEXPANDER_TOP, IEXPANDER_BOTTOM }; enum { IEXPANDER_CLOSE, IEXPANDER_OPEN }; struct _IcontrolData { /* attributes */ int position; int state; int barSize; int extra_buttons, extra_buttons_state[4]; int moving; }; static void iGLExpanderOpenCloseChild(Ihandle* ih, int refresh, int callcb, int state) { Ihandle* gl_parent = (Ihandle*)iupAttribGet(ih, "_IUP_GLCANVAS_PARENT"); Ihandle *child = ih->firstchild; if (callcb) { IFni cb = (IFni)IupGetCallback(ih, "OPENCLOSE_CB"); if (cb) { int ret = cb(ih, state); if (ret == IUP_IGNORE) return; } } ih->data->state = state; if (child) { if (ih->data->state == IEXPANDER_CLOSE) IupSetAttribute(child, "VISIBLE", "NO"); else IupSetAttribute(child, "VISIBLE", "YES"); if (refresh) IupRefreshChildren(gl_parent); /* this will recompute the layout of the glcanvasbox only */ } IupSetAttribute(gl_parent, "REDRAW", NULL); /* redraw the whole box */ if (callcb) { IFn cb = IupGetCallback(ih, "ACTION"); if (cb) cb(ih); } } static int iGLExpanderGetBarSize(Ihandle* ih) { int bar_size; if (ih->data->barSize == -1) { iupGLFontGetCharSize(ih, NULL, &bar_size); /* define a minimum size only when estimating one from charsize */ if (bar_size < IEXPAND_HANDLE_SIZE) bar_size = IEXPAND_HANDLE_SIZE; if (ih->data->position == IEXPANDER_TOP) { char* title = iupAttribGetStr(ih, "TITLE"); char* image = iupAttribGetStr(ih, "IMAGE"); if (image) { int image_h = 0; iupGLImageGetInfo(image, NULL, &image_h, NULL); bar_size = iupMAX(bar_size, image_h); } if (title || image || ih->data->extra_buttons != 0) bar_size += 2 * IEXPAND_BACK_MARGIN; } } else bar_size = ih->data->barSize; return bar_size; } static int iGLExpanderIsInsideHandler(Ihandle* ih, int x, int y, int bar_size) { char *image = iupAttribGet(ih, "IMAGE"); char* title = iupAttribGet(ih, "TITLE"); if (ih->data->position == IEXPANDER_TOP && (title || image || ih->data->extra_buttons != 0)) { /* always left aligned */ if (y >= IEXPAND_SPACING + IEXPAND_BACK_MARGIN && y <= bar_size - IEXPAND_SPACING - IEXPAND_BACK_MARGIN) { int icon_width = IEXPAND_HANDLE_SIZE; if (image) { int width; iupGLImageGetInfo(image, &width, NULL, NULL); icon_width = iupMAX(icon_width, width); } if (title) { int width; iupGLFontGetMultiLineStringSize(ih, title, &width, NULL); icon_width += width; } if (x >= IEXPAND_BACK_MARGIN && x < IEXPAND_BACK_MARGIN + icon_width) return 1; } } else { /* always centered */ if (ih->data->position == IEXPANDER_TOP || ih->data->position == IEXPANDER_BOTTOM) { if (y >= IEXPAND_SPACING && y <= bar_size - IEXPAND_SPACING) { int half = ih->currentwidth / 2; if (x >= half - IEXPAND_HANDLE_SIZE / 2 && x <= half + IEXPAND_HANDLE_SIZE/2) return 1; } } else /* IEXPANDER_LEFT or IEXPANDER_RIGHT */ { if (x >= IEXPAND_SPACING && x <= bar_size - IEXPAND_SPACING) { int half = ih->currentheight / 2; if (y >= half - IEXPAND_HANDLE_SIZE / 2 && y <= half + IEXPAND_HANDLE_SIZE / 2) return 1; } } } return 0; } static int iGLExpanderMOTION_CB(Ihandle* ih, int x, int y, char* status) { int redraw = 0; int bar_size = iGLExpanderGetBarSize(ih); /* shift to bar position */ if (ih->data->position == IEXPANDER_RIGHT) x -= ih->currentwidth - 1 - bar_size; else if (ih->data->position == IEXPANDER_BOTTOM) y -= ih->currentheight - 1 - bar_size; /* special highlight processing for handler area */ if (iGLExpanderIsInsideHandler(ih, x, y, bar_size)) { if (!iupAttribGet(ih, "HIGHLIGHT")) { redraw = 1; iupAttribSet(ih, "HIGHLIGHT", "1"); } } else { if (iupAttribGet(ih, "HIGHLIGHT")) { redraw = 1; iupAttribSet(ih, "HIGHLIGHT", NULL); } } if (ih->data->position == IEXPANDER_TOP && !ih->data->moving) { if (y >= IEXPAND_SPACING + IEXPAND_BACK_MARGIN && y <= bar_size - IEXPAND_SPACING - IEXPAND_BACK_MARGIN) { int old_state[4]; old_state[1] = ih->data->extra_buttons_state[1]; old_state[2] = ih->data->extra_buttons_state[2]; old_state[3] = ih->data->extra_buttons_state[3]; if ((x >= ih->currentwidth - (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN) && (x < ih->currentwidth - IEXPAND_SPACING - IEXPAND_BACK_MARGIN)) { if (ih->data->extra_buttons_state[1] == 0) ih->data->extra_buttons_state[1] = -1; /* highlight if not pressed */ } else { if (ih->data->extra_buttons_state[1] != 0) ih->data->extra_buttons_state[1] = 0; } if (ih->data->extra_buttons > 1) { if ((x >= ih->currentwidth - 2 * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN) && (x < ih->currentwidth - (IEXPAND_BUTTON_SIZE + 2 * IEXPAND_SPACING) - IEXPAND_BACK_MARGIN)) { if (ih->data->extra_buttons_state[2] == 0) ih->data->extra_buttons_state[2] = -1; /* highlight if not pressed */ } else { if (ih->data->extra_buttons_state[2] != 0) ih->data->extra_buttons_state[2] = 0; } } if (ih->data->extra_buttons == 3) { if ((x >= ih->currentwidth - 3 * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN) && (x < ih->currentwidth - (2 * IEXPAND_BUTTON_SIZE + 3 * IEXPAND_SPACING) - IEXPAND_BACK_MARGIN)) { if (ih->data->extra_buttons_state[3] == 0) ih->data->extra_buttons_state[3] = -1; /* highlight if not pressed */ } else { if (ih->data->extra_buttons_state[3] != 0) ih->data->extra_buttons_state[3] = 0; } } if (old_state[1] != ih->data->extra_buttons_state[1] || old_state[2] != ih->data->extra_buttons_state[2] || old_state[3] != ih->data->extra_buttons_state[3]) { iupGLSubCanvasRedraw(ih); redraw = 0; } } } if (ih->data->moving) { if (iupGLSubCanvasMove(ih, x, y)) redraw = 0; } if (redraw) iupGLSubCanvasRedraw(ih); (void)status; return IUP_DEFAULT; } static int iGLExpanderCallExtraButtonCb(Ihandle* ih, int button, int pressed) { int old_state = ih->data->extra_buttons_state[button]; ih->data->extra_buttons_state[button] = pressed; /* redraw only if state changed */ if (old_state != ih->data->extra_buttons_state[button]) iupGLSubCanvasRedraw(ih); /* if pressed always call, if not pressed, call only if was pressed */ if (pressed || old_state == 1) { IFnii cb = (IFnii)IupGetCallback(ih, "EXTRABUTTON_CB"); if (cb) cb(ih, button, pressed); } return IUP_DEFAULT; } static int iGLExpanderBUTTON_CB(Ihandle* ih, int button, int pressed, int x, int y, char* status) { int bar_size = iGLExpanderGetBarSize(ih); ih->data->moving = 0; if (button != IUP_BUTTON1) return IUP_DEFAULT; /* shift to bar position */ if (ih->data->position == IEXPANDER_RIGHT) x -= ih->currentwidth-1 - bar_size; else if (ih->data->position == IEXPANDER_BOTTOM) y -= ih->currentheight-1 - bar_size; if (ih->data->position == IEXPANDER_TOP && ih->data->extra_buttons != 0) { if (y >= IEXPAND_SPACING + IEXPAND_BACK_MARGIN && y <= ih->currentheight - IEXPAND_SPACING - IEXPAND_BACK_MARGIN) { if ((x >= ih->currentwidth - (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN) && (x < ih->currentwidth - IEXPAND_SPACING - IEXPAND_BACK_MARGIN)) return iGLExpanderCallExtraButtonCb(ih, 1, pressed); if (ih->data->extra_buttons > 1) { if ((x >= ih->currentwidth - 2 * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN) && (x < ih->currentwidth - (IEXPAND_BUTTON_SIZE + 2 * IEXPAND_SPACING) - IEXPAND_BACK_MARGIN)) return iGLExpanderCallExtraButtonCb(ih, 2, pressed); } if (ih->data->extra_buttons == 3) { if ((x >= ih->currentwidth - 3 * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN) && (x < ih->currentwidth - (2 * IEXPAND_BUTTON_SIZE + 3 * IEXPAND_SPACING) - IEXPAND_BACK_MARGIN)) return iGLExpanderCallExtraButtonCb(ih, 3, pressed); } } } if (pressed) { if (!iGLExpanderIsInsideHandler(ih, x, y, bar_size)) { int moveable = iupAttribGetInt(ih, "MOVEABLE"); if (moveable) { iupGLSubCanvasStartMoving(ih, x, y); ih->data->moving = 1; } iupAttribSet(ih, "PRESSED", NULL); } else { /* Update the state: OPEN ==> collapsed, CLOSE ==> expanded */ iGLExpanderOpenCloseChild(ih, 1, 1, ih->data->state == IEXPANDER_OPEN ? IEXPANDER_CLOSE : IEXPANDER_OPEN); } } (void)status; return IUP_DEFAULT; } static void iGLExpanderDrawArrow(Ihandle *ih, int x, int y, const char* color, int active, int dir) { int size = IEXPAND_HANDLE_SIZE - 3 * IEXPAND_SPACING; x += (3 * IEXPAND_SPACING) / 2; y += (3 * IEXPAND_SPACING) / 2; iupGLDrawArrow(ih, x, y, size, color, active, dir); } static void iGLExpanderDrawSmallArrow(Ihandle *ih, const char* color, int active, int dir, int y_offset) { /* always left align */ int size = IEXPAND_HANDLE_SIZE - 3 * IEXPAND_SPACING - 2 * IEXPAND_BACK_MARGIN + 1; int x = IEXPAND_BACK_MARGIN + (3 * IEXPAND_SPACING) / 2; int y = IEXPAND_BACK_MARGIN + (3 * IEXPAND_SPACING) / 2 + y_offset + 1; iupGLDrawArrow(ih, x, y, size, color, active, dir); } static void iGLExpanderDrawExtraButton(Ihandle* ih, int button, int x, int y, int height, int active) { char* image = iupAttribGetId(ih, "IMAGEEXTRA", button); int img_height; if (!image) return; if (ih->data->extra_buttons_state[button] == 1) { char* impress = iupAttribGetId(ih, "IMAGEEXTRAPRESS", button); if (impress) image = impress; } else if (ih->data->extra_buttons_state[button] == -1) { char* imhighlight = iupAttribGetId(ih, "IMAGEEXTRAHIGHLIGHT", button); if (imhighlight) image = imhighlight; } iupGLImageGetInfo(image, NULL, &img_height, NULL); if (height > img_height) y += (height - img_height) / 2; iupGLDrawIconImage(ih, x, y, NULL, image, !active); } static int iGLExpanderACTION_CB(Ihandle* ih) { int x1, y1, x2, y2; char *image = iupAttribGet(ih, "IMAGE"); char* title = iupAttribGet(ih, "TITLE"); int active = iupAttribGetInt(ih, "ACTIVE"); char* fgcolor = iupAttribGetStr(ih, "FORECOLOR"); char* bgcolor = iupAttribGetStr(ih, "BACKCOLOR"); int highlight = iupAttribGetInt(ih, "HIGHLIGHT"); int pressed = iupAttribGetInt(ih, "PRESSED"); int bar_size = iGLExpanderGetBarSize(ih); char* bgimage = iupAttribGet(ih, "TITLEBACKIMAGE"); /* calc bar position */ if (ih->data->position == IEXPANDER_LEFT) { x1 = 0; x2 = bar_size; y1 = 0; y2 = ih->currentheight - 1; } else if (ih->data->position == IEXPANDER_RIGHT) { x1 = ih->currentwidth-1 - bar_size; x2 = ih->currentwidth-1; y1 = 0; y2 = ih->currentheight - 1; } else if (ih->data->position == IEXPANDER_BOTTOM) { x1 = 0; x2 = ih->currentwidth - 1; y1 = ih->currentheight-1 - bar_size; y2 = ih->currentheight-1; } else /* IEXPANDER_TOP */ { x1 = 0; x2 = ih->currentwidth - 1; y1 = 0; y2 = bar_size; } /* draw bar box */ if (bgimage) iupGLDrawIconImageZoom(ih, x1, x2, y1, y2, "TITLEBACKIMAGE", bgimage, active); else iupGLDrawBox(ih, x1, x2, y1, y2, bgcolor, 1); /* always active */ if (ih->data->position == IEXPANDER_TOP && (title || image || ih->data->extra_buttons != 0)) { /* left align image/handler+title */ int txt_offset = IEXPAND_HANDLE_SIZE; if (image) { int img_width = 0, img_height = 0; int y_offset = 0; if (ih->data->state != IEXPANDER_CLOSE) { char* imopen = iupAttribGetStr(ih, "IMAGEOPEN"); if (imopen) image = imopen; if (highlight) { char* imhighlight = iupAttribGetStr(ih, "IMAGEOPENHIGHLIGHT"); if (imhighlight) image = imhighlight; } } else if (highlight) { char* imhighlight = iupAttribGetStr(ih, "IMAGEHIGHLIGHT"); if (imhighlight) image = imhighlight; } iupGLImageGetInfo(image, &img_width, &img_height, NULL); if (bar_size > img_height) y_offset = (bar_size - img_height) / 2; iupGLDrawIconImage(ih, IEXPAND_BACK_MARGIN, y_offset, NULL, image, !active); txt_offset = iupMAX(txt_offset, img_width); } else { int y_offset = 0; if (bar_size > IEXPAND_HANDLE_SIZE + 2 * IEXPAND_BACK_MARGIN) y_offset = (bar_size - IEXPAND_HANDLE_SIZE - 2 * IEXPAND_BACK_MARGIN) / 2; if (pressed) { char* presscolor = iupAttribGetStr(ih, "PRESSCOLOR"); if (presscolor) fgcolor = presscolor; } else if (highlight) { char* hlcolor = iupAttribGetStr(ih, "HIGHCOLOR"); if (hlcolor) fgcolor = hlcolor; } if (ih->data->state == IEXPANDER_CLOSE) iGLExpanderDrawSmallArrow(ih, fgcolor, active, IEXPANDER_RIGHT, y_offset); else iGLExpanderDrawSmallArrow(ih, fgcolor, active, IEXPANDER_BOTTOM, y_offset); } if (title) { int height; iupGLFontGetMultiLineStringSize(ih, title, NULL, &height); iupGLDrawMultilineText(ih, txt_offset, (bar_size - height) / 2 - 1, title, fgcolor, active); } if (ih->data->extra_buttons != 0) { /* right align extra buttons */ int y = IEXPAND_SPACING + IEXPAND_BACK_MARGIN; int height = bar_size - 2 * (IEXPAND_SPACING + IEXPAND_BACK_MARGIN); iGLExpanderDrawExtraButton(ih, 1, ih->currentwidth - (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN, y, height, active); if (ih->data->extra_buttons > 1) iGLExpanderDrawExtraButton(ih, 2, ih->currentwidth - 2 * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN, y, height, active); if (ih->data->extra_buttons == 3) iGLExpanderDrawExtraButton(ih, 3, ih->currentwidth - 3 * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING) - IEXPAND_BACK_MARGIN, y, height, active); } } else { /* center align the handler */ int x = x1, y = y1, width = x2 - x1 + 1, height = y2 - y1 + 1; if (pressed) { char* presscolor = iupAttribGetStr(ih, "PRESSCOLOR"); if (presscolor) fgcolor = presscolor; } else if (highlight) { char* hlcolor = iupAttribGetStr(ih, "HIGHCOLOR"); if (hlcolor) fgcolor = hlcolor; } switch (ih->data->position) { case IEXPANDER_LEFT: x += 0; y += (height - IEXPAND_HANDLE_SIZE) / 2; if (ih->data->state == IEXPANDER_CLOSE) iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_RIGHT); else iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_LEFT); break; case IEXPANDER_RIGHT: x += 0; y += (height - IEXPAND_HANDLE_SIZE) / 2; if (ih->data->state == IEXPANDER_CLOSE) iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_LEFT); else iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_RIGHT); break; case IEXPANDER_TOP: x += (width - IEXPAND_HANDLE_SIZE) / 2; y += 0; if (ih->data->state == IEXPANDER_CLOSE) iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_BOTTOM); else iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_TOP); break; case IEXPANDER_BOTTOM: x += (width - IEXPAND_HANDLE_SIZE) / 2; y += 0; if (ih->data->state == IEXPANDER_CLOSE) iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_TOP); else iGLExpanderDrawArrow(ih, x, y, fgcolor, active, IEXPANDER_BOTTOM); break; } } return IUP_DEFAULT; } static int iGLExpanderENTERWINDOW_CB(Ihandle* ih, int x, int y) { int bar_size = iGLExpanderGetBarSize(ih); /* shift to bar position */ if (ih->data->position == IEXPANDER_RIGHT) x -= ih->currentwidth - 1 - bar_size; else if (ih->data->position == IEXPANDER_BOTTOM) y -= ih->currentheight - 1 - bar_size; /* special highlight processing for handler area */ if (iGLExpanderIsInsideHandler(ih, x, y, bar_size)) iupAttribSet(ih, "HIGHLIGHT", "1"); else iupAttribSet(ih, "HIGHLIGHT", NULL); return iupGLSubCanvasRedraw(ih); } /*****************************************************************************\ |* Attributes *| \*****************************************************************************/ static char* iGLExpanderGetClientSizeAttrib(Ihandle* ih) { int width = ih->currentwidth; int height = ih->currentheight; int bar_size = iGLExpanderGetBarSize(ih); if (ih->data->position == IEXPANDER_LEFT || ih->data->position == IEXPANDER_RIGHT) width -= bar_size; else height -= bar_size; if (width < 0) width = 0; if (height < 0) height = 0; return iupStrReturnIntInt(width, height, 'x'); } static char* iGLExpanderGetClipMinAttrib(Ihandle* ih) { int dx = 0, dy = 0; int bar_size = iGLExpanderGetBarSize(ih); if (ih->data->position == IEXPANDER_LEFT) dx += bar_size; else if (ih->data->position == IEXPANDER_TOP) dy += bar_size; return iupStrReturnIntInt(dx, dy, 'x'); } static int iGLExpanderSetPositionAttrib(Ihandle* ih, const char* value) { if (iupStrEqualNoCase(value, "LEFT")) ih->data->position = IEXPANDER_LEFT; else if (iupStrEqualNoCase(value, "RIGHT")) ih->data->position = IEXPANDER_RIGHT; else if (iupStrEqualNoCase(value, "BOTTOM")) ih->data->position = IEXPANDER_BOTTOM; else /* Default = TOP */ ih->data->position = IEXPANDER_TOP; return 0; /* do not store value in hash table */ } static int iGLExpanderSetBarSizeAttrib(Ihandle* ih, const char* value) { if (!value) ih->data->barSize = -1; else iupStrToInt(value, &ih->data->barSize); /* must manually update layout */ return 0; /* do not store value in hash table */ } static char* iGLExpanderGetBarSizeAttrib(Ihandle* ih) { int bar_size = iGLExpanderGetBarSize(ih); return iupStrReturnInt(bar_size); } static int iGLExpanderSetStateAttrib(Ihandle* ih, const char* value) { int state; if (iupStrEqualNoCase(value, "OPEN")) state = IEXPANDER_OPEN; else state = IEXPANDER_CLOSE; iGLExpanderOpenCloseChild(ih, 1, 0, state); return 0; /* do not store value in hash table */ } static char* iGLExpanderGetStateAttrib(Ihandle* ih) { if (ih->data->state) return "OPEN"; else return "CLOSE"; } static int iGLExpanderSetExtraButtonsAttrib(Ihandle* ih, const char* value) { if (!value) ih->data->extra_buttons = 0; else { iupStrToInt(value, &(ih->data->extra_buttons)); if (ih->data->extra_buttons < 0) ih->data->extra_buttons = 0; else if (ih->data->extra_buttons > 3) ih->data->extra_buttons = 3; } return 0; /* do not store value in hash table */ } static char* iGLExpanderGetExtraButtonsAttrib(Ihandle* ih) { return iupStrReturnInt(ih->data->extra_buttons); } static int iGLExpanderSetMoveableAttrib(Ihandle* ih, const char* value) { Ihandle* gl_parent = (Ihandle*)iupAttribGet(ih, "_IUP_GLCANVAS_PARENT"); /* only a direct child of the canvabox can be moved */ if (iupStrBoolean(value) && ih->parent == gl_parent) return 1; else { iupAttribSet(ih, "MOVEABLE", "NO"); return 0; } } /*****************************************************************************\ |* Methods *| \*****************************************************************************/ static void iGLExpanderComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *children_expand) { int child_expand = 0, natural_w, natural_h; Ihandle *child = ih->firstchild; int bar_size = iGLExpanderGetBarSize(ih); /* bar */ if (ih->data->position == IEXPANDER_LEFT || ih->data->position == IEXPANDER_RIGHT) { natural_w = bar_size; natural_h = IEXPAND_HANDLE_SIZE; /* just a minimum size */ } else { natural_w = IEXPAND_HANDLE_SIZE; /* just a minimum size */ natural_h = bar_size; if (ih->data->position == IEXPANDER_TOP) { char* title, *image; /* if IMAGE is defined assume that will cover all the canvas area */ image = iupAttribGetStr(ih, "IMAGE"); if (image) { int image_w = 0; iupGLImageGetInfo(image, &image_w, NULL, NULL); natural_w = iupMAX(natural_w, image_w); } /* if TITLE and IMAGE are both defined then IMAGE is only the handle */ title = iupAttribGetStr(ih, "TITLE"); if (title) { int title_size = 0; iupGLFontGetMultiLineStringSize(ih, title, &title_size, NULL); natural_w += title_size; } if (ih->data->extra_buttons != 0) natural_w += ih->data->extra_buttons * (IEXPAND_BUTTON_SIZE + IEXPAND_SPACING); if (image || title || ih->data->extra_buttons != 0) natural_w += 2 * IEXPAND_BACK_MARGIN; } } if (child) { /* update child natural bar_size first */ iupBaseComputeNaturalSize(child); if (ih->data->position == IEXPANDER_LEFT || ih->data->position == IEXPANDER_RIGHT) { if (ih->data->state == IEXPANDER_OPEN) /* only open, not float */ natural_w += child->naturalwidth; natural_h = iupMAX(natural_h, child->naturalheight); } else { natural_w = iupMAX(natural_w, child->naturalwidth); if (ih->data->state == IEXPANDER_OPEN) /* only open, not float */ natural_h += child->naturalheight; } if (ih->data->state == IEXPANDER_OPEN) child_expand = child->expand; else { if (ih->data->position == IEXPANDER_LEFT || ih->data->position == IEXPANDER_RIGHT) child_expand = child->expand & IUP_EXPAND_HEIGHT; /* only vertical allowed */ else child_expand = child->expand & IUP_EXPAND_WIDTH; /* only horizontal allowed */ } } *children_expand = child_expand; *w = natural_w; *h = natural_h; } static void iGLExpanderSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink) { Ihandle *child = ih->firstchild; int width = ih->currentwidth; int height = ih->currentheight; int bar_size = iGLExpanderGetBarSize(ih); if (ih->data->position == IEXPANDER_LEFT || ih->data->position == IEXPANDER_RIGHT) { if (ih->currentwidth < bar_size) ih->currentwidth = bar_size; width = ih->currentwidth - bar_size; } else /* IEXPANDER_TOP OR IEXPANDER_BOTTOM */ { if (ih->currentheight < bar_size) ih->currentheight = bar_size; height = ih->currentheight - bar_size; } if (child) { if (ih->data->state == IEXPANDER_OPEN) iupBaseSetCurrentSize(child, width, height, shrink); } } static void iGLExpanderSetChildrenPositionMethod(Ihandle* ih, int x, int y) { Ihandle *child = ih->firstchild; if (child) { int bar_size = iGLExpanderGetBarSize(ih); if (ih->data->position == IEXPANDER_LEFT) x += bar_size; else if (ih->data->position == IEXPANDER_TOP) y += bar_size; if (ih->data->state == IEXPANDER_OPEN) iupBaseSetPosition(child, x, y); } } static void iGLExpanderChildAddedMethod(Ihandle* ih, Ihandle* child) { iGLExpanderOpenCloseChild(ih, 0, 0, ih->data->state); (void)child; } static int iGLExpanderCreateMethod(Ihandle* ih, void** params) { ih->data = iupALLOCCTRLDATA(); ih->data->position = IEXPANDER_TOP; ih->data->state = IEXPANDER_OPEN; ih->data->barSize = -1; /* Setting callbacks */ IupSetCallback(ih, "GL_ACTION", (Icallback)iGLExpanderACTION_CB); IupSetCallback(ih, "GL_BUTTON_CB", (Icallback)iGLExpanderBUTTON_CB); IupSetCallback(ih, "GL_MOTION_CB", (Icallback)iGLExpanderMOTION_CB); IupSetCallback(ih, "GL_LEAVEWINDOW_CB", iupGLSubCanvasRedraw); IupSetCallback(ih, "GL_ENTERWINDOW_CB", (Icallback)iGLExpanderENTERWINDOW_CB); if (params) { Ihandle** iparams = (Ihandle**)params; if (*iparams) IupAppend(ih, *iparams); } return IUP_NOERROR; } Iclass* iupGLExpanderNewClass(void) { Iclass* ic = iupClassNew(iupRegisterFindClass("glsubcanvas")); ic->name = "glexpander"; ic->cons = "GLExpander"; ic->format = "h"; /* one Ihandle* */ ic->nativetype = IUP_TYPEVOID; ic->childtype = IUP_CHILDMANY+1; /* 1 child */ ic->is_interactive = 0; /* Class functions */ ic->New = iupGLExpanderNewClass; ic->Create = iGLExpanderCreateMethod; ic->Map = iupBaseTypeVoidMapMethod; ic->ChildAdded = iGLExpanderChildAddedMethod; ic->ComputeNaturalSize = iGLExpanderComputeNaturalSizeMethod; ic->SetChildrenCurrentSize = iGLExpanderSetChildrenCurrentSizeMethod; ic->SetChildrenPosition = iGLExpanderSetChildrenPositionMethod; /* Callbacks */ iupClassRegisterCallback(ic, "ACTION", ""); iupClassRegisterCallback(ic, "OPENCLOSE_CB", "i"); iupClassRegisterCallback(ic, "EXTRABUTTON_CB", "ii"); iupClassRegisterCallback(ic, "MOVE_CB", "ii"); /* Base Container */ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CLIENTSIZE", iGLExpanderGetClientSizeAttrib, 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 */ /* NOTICE: avoid defining inheritable attributes for containers */ iupClassRegisterAttribute(ic, "CLIP_MIN", iGLExpanderGetClipMinAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_READONLY | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BARPOSITION", NULL, iGLExpanderSetPositionAttrib, IUPAF_SAMEASSYSTEM, "TOP", IUPAF_NOT_MAPPED | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BARSIZE", iGLExpanderGetBarSizeAttrib, iGLExpanderSetBarSizeAttrib, IUPAF_SAMEASSYSTEM, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "STATE", iGLExpanderGetStateAttrib, iGLExpanderSetStateAttrib, IUPAF_SAMEASSYSTEM, "OPEN", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "EXTRABUTTONS", iGLExpanderGetExtraButtonsAttrib, iGLExpanderSetExtraButtonsAttrib, IUPAF_SAMEASSYSTEM, NULL, IUPAF_NOT_MAPPED | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "MOVEABLE", NULL, iGLExpanderSetMoveableAttrib, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "MOVETOTOP", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "FORECOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "255 255 255", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BACKCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "50 100 150", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "HIGHCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "200 225 245", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "PRESSCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "150 200 235", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "TITLE", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "TITLEBACKIMAGE", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "TITLEBACKIMAGEINACTIVE", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGE", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEHIGHLIGHT", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEOPEN", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEOPENHIGHLIGHT", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRA1", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRAPRESS1", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRAHIGHLIGHT1", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRA2", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRAPRESS2", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRAHIGHLIGHT2", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRA3", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRAPRESS3", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEEXTRAHIGHLIGHT3", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); return ic; } Ihandle* IupGLExpander(Ihandle* child) { void *children[2]; children[0] = (void*)child; children[1] = NULL; return IupCreatev("glexpander", children); }