summaryrefslogtreecommitdiff
path: root/iup/src/iup_sbox.c
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-04 11:56:41 -0800
committerPixel <pixel@nobis-crew.org>2009-11-04 11:59:33 -0800
commitd577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch)
tree590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /iup/src/iup_sbox.c
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'iup/src/iup_sbox.c')
-rwxr-xr-xiup/src/iup_sbox.c413
1 files changed, 413 insertions, 0 deletions
diff --git a/iup/src/iup_sbox.c b/iup/src/iup_sbox.c
new file mode 100755
index 0000000..5a71d33
--- /dev/null
+++ b/iup/src/iup_sbox.c
@@ -0,0 +1,413 @@
+/** \file
+ * \brief iupsbox 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 "iupkey.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_layout.h"
+#include "iup_childtree.h"
+
+
+#define ISBOX_THICK 5
+
+enum { ISBOX_NORTH, ISBOX_SOUTH, ISBOX_WEST, ISBOX_EAST };
+
+struct _IcontrolData
+{
+ int w, h;
+ int isholding;
+ int start_x, start_y;
+ int start_w, start_h;
+
+ int direction; /* one of the types: ISBOX_NORTH, ISBOX_SOUTH, ISBOX_WEST, ISBOX_EAST */
+};
+
+
+static int iSboxGetYborder(Ihandle* ih)
+{
+ if (ih->data->direction == ISBOX_NORTH || ih->data->direction == ISBOX_SOUTH)
+ return ISBOX_THICK;
+ else
+ return 0;
+}
+
+static int iSboxGetXborder(Ihandle* ih)
+{
+ if (ih->data->direction == ISBOX_EAST || ih->data->direction == ISBOX_WEST)
+ return ISBOX_THICK;
+ else
+ return 0;
+}
+
+static void iSboxSaveDimension(Ihandle* ih, int w, int h)
+{
+ ih->data->w = w;
+ ih->data->h = h;
+}
+
+static void iSboxAddDecorOffset(Ihandle* ih, int *x, int *y)
+{
+ /* skip north thumb if there is one */
+ if (ih->data->direction == ISBOX_NORTH)
+ *y += ISBOX_THICK;
+
+ /* skip west thumb if there is one */
+ if (ih->data->direction == ISBOX_WEST)
+ *x += ISBOX_THICK;
+}
+
+static void iSboxGetFinalSize(Ihandle* ih, int direction, int *w, int *h)
+{
+ int final_x, final_y;
+ int diff_x, diff_y;
+
+ iupStrToIntInt(IupGetGlobal("CURSORPOS"), &final_x, &final_y, 'x');
+
+ diff_x = final_x - ih->data->start_x;
+ diff_y = final_y - ih->data->start_y;
+
+ if(direction == ISBOX_WEST)
+ diff_x = -diff_x;
+
+ if(direction == ISBOX_NORTH)
+ diff_y = -diff_y;
+
+ *w = diff_x + ih->data->start_w;
+ *h = diff_y + ih->data->start_h;
+}
+
+static void iSboxShakeControls(Ihandle* ih)
+{
+ int new_w, new_h;
+
+ iSboxGetFinalSize(ih, ih->data->direction, &new_w, &new_h);
+
+ if (ih->data->direction == ISBOX_WEST || ih->data->direction == ISBOX_EAST)
+ {
+ if (new_w != ih->data->w)
+ {
+ if (new_w > ih->naturalwidth)
+ iSboxSaveDimension(ih, new_w, ih->data->h);
+ else
+ iSboxSaveDimension(ih, new_w, ih->naturalwidth);
+ }
+ }
+ else if (ih->data->direction == ISBOX_SOUTH || ih->data->direction == ISBOX_NORTH)
+ {
+ if(new_h != ih->data->h)
+ {
+ if (new_h > ih->naturalheight)
+ iSboxSaveDimension(ih, ih->data->w, new_h);
+ else
+ iSboxSaveDimension(ih, ih->naturalheight, new_h);
+ }
+ }
+
+ IupRefresh(ih); /* may affect all the elements in the dialog */
+}
+
+
+/*****************************************************************************\
+|* Callbacks of canvas bar *|
+\*****************************************************************************/
+
+
+static int iSboxMotion_CB(Ihandle* bar, int x, int y, char *r)
+{
+ Ihandle* ih = bar->parent;
+
+ if (ih->data->isholding)
+ iSboxShakeControls(ih);
+
+ (void)x;
+ (void)y;
+ (void)r;
+ return IUP_DEFAULT;
+}
+
+static int iSboxButton_CB(Ihandle* bar, int button, int pressed, int x, int y, char* status)
+{
+ Ihandle* ih = bar->parent;
+
+ if (button!=IUP_BUTTON1)
+ return IUP_DEFAULT;
+
+ if (!ih->data->isholding && pressed)
+ {
+ ih->data->isholding = 1;
+
+ /* Save the cursor position */
+ iupStrToIntInt(IupGetGlobal("CURSORPOS"), &ih->data->start_x, &ih->data->start_y, 'x');
+
+ /* Save the initial size */
+ ih->data->start_w = ih->data->w;
+ ih->data->start_h = ih->data->h;
+ }
+ else if (ih->data->isholding && !pressed)
+ ih->data->isholding = 0;
+
+ (void)x;
+ (void)y;
+ (void)status;
+ return IUP_DEFAULT;
+}
+
+static int iSboxFocus_CB(Ihandle* bar, int focus)
+{
+ Ihandle* ih = bar->parent;
+
+ if (!ih || focus) /* use only kill focus */
+ return IUP_DEFAULT;
+
+ if (ih->data->isholding)
+ ih->data->isholding = 0;
+
+ return IUP_DEFAULT;
+}
+
+
+/*****************************************************************************\
+|* Attributes *|
+\*****************************************************************************/
+
+
+static char* iSboxGetClientSizeAttrib(Ihandle* ih)
+{
+ int width, height;
+ char* str = iupStrGetMemory(20);
+ width = ih->currentwidth;
+ height = ih->currentheight;
+ width -= iSboxGetXborder(ih);
+ height -= iSboxGetYborder(ih);
+ if (width < 0) width = 0;
+ if (height < 0) height = 0;
+ sprintf(str, "%dx%d", width, height);
+ return str;
+}
+
+static int iSboxSetColorAttrib(Ihandle* ih, const char* value)
+{
+ IupSetAttribute(ih->firstchild, "BGCOLOR", value);
+ return 0; /* do not store value in hash table */
+}
+
+static int iSboxSetDirectionAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->handle) /* only before map */
+ return 0;
+
+ if (iupStrEqual(value, "NORTH"))
+ ih->data->direction = ISBOX_NORTH;
+ else if(iupStrEqual(value, "SOUTH"))
+ ih->data->direction = ISBOX_SOUTH;
+ else if(iupStrEqual(value, "WEST"))
+ ih->data->direction = ISBOX_WEST;
+ else /* Default = EAST */
+ ih->data->direction = ISBOX_EAST;
+
+ if (ih->data->direction == ISBOX_EAST || ih->data->direction == ISBOX_WEST)
+ IupSetAttribute(ih->firstchild, "CURSOR", "RESIZE_WE");
+ else
+ IupSetAttribute(ih->firstchild, "CURSOR", "RESIZE_NS");
+
+ return 0; /* do not store value in hash table */
+}
+
+
+/*****************************************************************************\
+|* Methods *|
+\*****************************************************************************/
+
+
+static void iSboxComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+{
+ int natural_w = ih->naturalwidth,
+ natural_h = ih->naturalheight;
+
+ /* only allow expand in the oposite direction, complement iupBaseContainerUpdateExpand */
+ if (ih->data->direction == ISBOX_EAST || ih->data->direction == ISBOX_WEST)
+ ih->expand &= ~IUP_EXPAND_WIDTH;
+ else
+ ih->expand &= ~IUP_EXPAND_HEIGHT;
+
+ /* always has at least one child, the bar */
+
+ /* This is an unusual element, the iupBaseComputeNaturalSize logic is done twice, one here and one back there. */
+
+ if (ih->firstchild->brother)
+ {
+ Ihandle* child = ih->firstchild->brother;
+
+ /* update child natural size first */
+ iupBaseComputeNaturalSize(child);
+
+ *expand = child->expand;
+
+ /* calculate as in iupBaseComputeNaturalSize */
+ natural_w = iupMAX(natural_w, child->naturalwidth + iSboxGetXborder(ih));
+ natural_h = iupMAX(natural_h, child->naturalheight + iSboxGetYborder(ih));
+ }
+
+ /* update control to fit its children according to direction */
+
+ /* bar */
+ if (ih->data->direction == ISBOX_EAST || ih->data->direction == ISBOX_WEST)
+ {
+ ih->data->w = iupMAX(natural_w, ih->data->w);
+ ih->data->h = natural_h;
+ }
+ else /* ISBOX_NORTH || ISBOX_SOUTH */
+ {
+ ih->data->w = natural_w;
+ ih->data->h = iupMAX(natural_h, ih->data->h);
+ }
+
+ /* child */
+ if (ih->firstchild->brother)
+ {
+ Ihandle* child = ih->firstchild->brother;
+ child->naturalwidth = ih->data->w - iSboxGetXborder(ih);
+ child->naturalheight = ih->data->h - iSboxGetYborder(ih);
+ }
+
+ *w = ih->data->w;
+ *h = ih->data->h;
+}
+
+static void iSboxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
+{
+ /* bar */
+ if ((ih->data->direction == ISBOX_NORTH || ih->data->direction == ISBOX_SOUTH))
+ {
+ ih->firstchild->currentwidth = ih->currentwidth;
+ ih->firstchild->currentheight = ISBOX_THICK;
+ }
+ else
+ {
+ ih->firstchild->currentwidth = ISBOX_THICK;
+ ih->firstchild->currentheight = ih->currentheight;
+ }
+
+ /* child */
+ if (ih->firstchild->brother)
+ {
+ int width = ih->currentwidth-iSboxGetXborder(ih);
+ int height = ih->currentheight-iSboxGetYborder(ih);
+ if (width < 0) width = 0;
+ if (height < 0) height = 0;
+
+ iupBaseSetCurrentSize(ih->firstchild->brother, width, height, shrink);
+ }
+}
+
+static void iSboxSetChildrenPositionMethod(Ihandle* ih, int x, int y)
+{
+ int posx = 0, posy = 0;
+
+ /* bar */
+ if (ih->data->direction == ISBOX_EAST)
+ {
+ posx = ih->data->w - ISBOX_THICK;
+ if (posx<0) posx = 0;
+ }
+ if (ih->data->direction == ISBOX_SOUTH)
+ {
+ posy = ih->data->h - ISBOX_THICK;
+ if (posy<0) posy = 0;
+ }
+
+ iupBaseSetPosition(ih->firstchild, x+posx, y+posy);
+
+ /* child */
+ if (ih->firstchild->brother)
+ {
+ iSboxAddDecorOffset(ih, &x, &y);
+ iupBaseSetPosition(ih->firstchild->brother, x, y);
+ }
+}
+
+static int iSboxCreateMethod(Ihandle* ih, void** params)
+{
+ Ihandle* bar;
+
+ ih->data = iupALLOCCTRLDATA();
+
+ ih->data->direction = ISBOX_EAST;
+ ih->data->h = -1;
+ ih->data->w = -1;
+
+ bar = IupCanvas(NULL);
+ iupChildTreeAppend(ih, bar); /* bar will always be the firstchild */
+
+ IupSetAttribute(bar, "BORDER", "YES");
+ IupSetAttribute(bar, "EXPAND", "NO");
+ IupSetAttribute(bar, "BGCOLOR", "192 192 192");
+
+ /* Setting callbacks */
+ IupSetCallback(bar, "BUTTON_CB", (Icallback) iSboxButton_CB);
+ IupSetCallback(bar, "FOCUS_CB", (Icallback) iSboxFocus_CB);
+ IupSetCallback(bar, "MOTION_CB", (Icallback) iSboxMotion_CB);
+
+ if (params)
+ {
+ Ihandle** iparams = (Ihandle**)params;
+ if (*iparams)
+ IupAppend(ih, *iparams);
+ }
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupSboxGetClass(void)
+{
+ Iclass* ic = iupClassNew(NULL);
+
+ ic->name = "sbox";
+ ic->format = "H"; /* one optional ihandle */
+ ic->nativetype = IUP_TYPEVOID;
+ ic->childtype = IUP_CHILDMANY; /* should be IUP_CHILDONE but has the bar (a IupCanvas) as firstchild */
+ ic->is_interactive = 0;
+
+ /* Class functions */
+ ic->Create = iSboxCreateMethod;
+ ic->Map = iupBaseTypeVoidMapMethod;
+
+ ic->ComputeNaturalSize = iSboxComputeNaturalSizeMethod;
+ ic->SetChildrenCurrentSize = iSboxSetChildrenCurrentSizeMethod;
+ ic->SetChildrenPosition = iSboxSetChildrenPositionMethod;
+
+ /* Common */
+ iupBaseRegisterCommonAttrib(ic);
+
+ /* Base Container */
+ iupClassRegisterAttribute(ic, "CLIENTSIZE", iSboxGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupSbox only */
+ iupClassRegisterAttribute(ic, "COLOR", NULL, iSboxSetColorAttrib, IUPAF_SAMEASSYSTEM, "192 192 192", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DIRECTION", NULL, iSboxSetDirectionAttrib, IUPAF_SAMEASSYSTEM, "EAST", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ return ic;
+}
+
+Ihandle* IupSbox(Ihandle* child)
+{
+ void *params[2];
+ params[0] = (void*)child;
+ params[1] = NULL;
+ return IupCreatev("sbox", params);
+}