984 lines
29 KiB
C
Executable File
984 lines
29 KiB
C
Executable File
/** \file
|
|
* \brief GLExpander control
|
|
*
|
|
* See Copyright Notice in "iup.h"
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#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);
|
|
}
|