/** \file * \brief GLVal 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" typedef struct _iGLVal { double value; /* min<=valuecurrentheight / 2; *width = handler_size; *height = ih->currentheight; } else { if (handler_size == 0) handler_size = ih->currentwidth / 2; *width = ih->currentwidth; *height = handler_size; } } } static int iGLValACTION_CB(Ihandle* ih) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); float bwidth = iupAttribGetFloat(ih, "BORDERWIDTH"); char* bordercolor = iupAttribGetStr(ih, "BORDERCOLOR"); int active = iupAttribGetInt(ih, "ACTIVE"); char* bgcolor = iupAttribGetStr(ih, "BGCOLOR"); int slider_size = iupAttribGetInt(ih, "SLIDERSIZE"); int border_width = (int)ceil(bwidth); int is_horizontal = iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "HORIZONTAL"); int handler_width, handler_height; char *image = iupAttribGet(ih, "IMAGE"); char* bgimage = iupAttribGet(ih, "BACKIMAGE"); double percent = (val->value - val->vmin) / (val->vmax - val->vmin); int x1, y1, x2, y2; iGLValGetHandlerSize(ih, is_horizontal, &handler_width, &handler_height); if (is_horizontal) { x1 = handler_width / 2; x2 = ih->currentwidth - 1 - handler_width / 2; y1 = (ih->currentheight - slider_size) / 2; y2 = y1 + slider_size; } else { y1 = handler_height / 2; y2 = ih->currentheight - 1 - handler_height / 2; x1 = (ih->currentwidth - slider_size) / 2; x2 = x1 + slider_size; } /* draw slider background */ if (bgimage) iupGLDrawIconImageZoom(ih, border_width, border_width, border_width, border_width, "BACKIMAGE", bgimage, active); else { iupGLDrawBox(ih, x1 + border_width, x2 - border_width, y1 + border_width, y2 - border_width, bgcolor, 1); /* always active */ /* draw slider border - can be disabled setting bwidth=0 */ iupGLDrawRect(ih, x1, x2, y1, y2, bwidth, bordercolor, active, 0); } if (is_horizontal) { int xmid = x1 + iupRound((x2 - x1) * percent); x1 = xmid - handler_width / 2; if (x1 < 0) x1 = 0; x2 = xmid + handler_width / 2; if (x2 > ih->currentwidth - 1) x2 = ih->currentwidth - 1; y1 = 0; y2 = ih->currentheight - 1; } else { int ymid = y1 + iupRound((y2 - y1) * (1.0 - percent)); y1 = ymid - handler_height / 2; if (y1 < 0) y1 = 0; y2 = ymid + handler_height / 2; if (y2 > ih->currentheight - 1) y2 = ih->currentheight - 1; x1 = 0; x2 = ih->currentwidth - 1; } if (image) { int x, y, width, height; iupGLImageGetInfo(image, &width, &height, NULL); /* always center the image */ x = (x2 - x1 + 1 - width) / 2; y = (y2 - y1 + 1 - height) / 2; if (x1 + x < 0) x = 0; if (y1 + y < 0) y = 0; if (x1 + x + width > ih->currentwidth - 1) x = ih->currentwidth - 1 - width - x1; if (y1 + y + height > ih->currentheight - 1) y = ih->currentheight - 1 - height - y1; iupGLDrawIconImage(ih, x1 + x, y1 + y, "IMAGE", image, active); } else { int pressed = iupAttribGetInt(ih, "PRESSED"); int highlight = iupAttribGetInt(ih, "HIGHLIGHT"); char* fgcolor = iupAttribGetStr(ih, "FGCOLOR"); if (pressed) { char* presscolor = iupAttribGetStr(ih, "PSCOLOR"); if (presscolor) fgcolor = presscolor; } else if (highlight) { char* hlcolor = iupAttribGetStr(ih, "HLCOLOR"); if (hlcolor) fgcolor = hlcolor; } /* draw handler foreground */ iupGLDrawBox(ih, x1 + border_width, x2 - border_width, y1 + border_width, y2 - border_width, fgcolor, active); /* draw handler border - can still be disabled setting bwidth=0 after the background because of the round rect */ iupGLDrawRect(ih, x1, x2, y1, y2, bwidth, bordercolor, active, 1); } return IUP_DEFAULT; } static void iGLValCropValue(iGLVal* val) { if (val->value>val->vmax) val->value = val->vmax; else if (val->valuevmin) val->value = val->vmin; } static int iGLValGetSliderInfo(Ihandle* ih, int dx, int dy, int is_horizontal, int *p, int *p1, int *p2, int *handler_op_size) { int handler_width, handler_height; iGLValGetHandlerSize(ih, is_horizontal, &handler_width, &handler_height); if (is_horizontal) { *p1 = handler_width / 2; *p2 = ih->currentwidth - 1 - handler_width / 2; *p = dx; if (handler_op_size) *handler_op_size = handler_height; return handler_width; } else { *p1 = handler_height / 2; *p2 = ih->currentheight - 1 - handler_height / 2; *p = dy; if (handler_op_size) *handler_op_size = handler_width; return handler_height; } } static void iGLValGetSliderOpositeInfo(Ihandle* ih, int dx, int dy, int is_horizontal, int *q, int *op_size) { if (is_horizontal) { *op_size = ih->currentheight; *q = dy; } else { *op_size = ih->currentwidth; *q = dx; } } static int iGLValMoveHandler(Ihandle* ih, int dx, int dy) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); int is_horizontal = iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "HORIZONTAL"); double percent, old_percent, delta; int dp, p1, p2; iGLValGetSliderInfo(ih, dx, dy, is_horizontal, &dp, &p1, &p2, NULL); if (dp == 0) return 0; old_percent = percent = (val->value - val->vmin) / (val->vmax - val->vmin); delta = (double)dp / (double)(p2 - p1); if (!is_horizontal) delta *= -1.0; percent += delta; if (percent < 0.0) percent = 0; if (percent > 1.0) percent = 1.0; if (old_percent == percent) return 0; val->value = percent * (val->vmax - val->vmin) + val->vmin; return 1; } static int iGLValIsInsideHandler(Ihandle* ih, int x, int y) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); int is_horizontal = iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "HORIZONTAL"); double percent; int p, p1, p2, pmid, handler_op_size; int handler_size = iGLValGetSliderInfo(ih, x, y, is_horizontal, &p, &p1, &p2, &handler_op_size); percent = (val->value - val->vmin) / (val->vmax - val->vmin); if (!is_horizontal) percent = 1.0 - percent; pmid = p1 + iupRound((p2 - p1) * percent); p1 = pmid - handler_size / 2; p2 = pmid + handler_size / 2; if (p >= p1 && p <= p2) { int q, q1, q2, qmid, op_size; iGLValGetSliderOpositeInfo(ih, x, y, is_horizontal, &q, &op_size); qmid = op_size / 2; q1 = qmid - handler_op_size / 2; q2 = qmid + handler_op_size / 2; if (q >= q1 && q <= q2) return 1; else return 0; } else return 0; } static int iGLValBUTTON_CB(Ihandle* ih, int button, int pressed, int x, int y, char* status) { if (button == IUP_BUTTON1) { if (pressed) { if (!iGLValIsInsideHandler(ih, x, y)) iupAttribSet(ih, "PRESSED", NULL); else { iupAttribSetInt(ih, "_IUP_GLVAL_START_X", x); iupAttribSetInt(ih, "_IUP_GLVAL_START_Y", y); } } else { if (iupAttribGet(ih, "_IUP_GLVAL_DRAG")) { IFni cb = (IFni)IupGetCallback(ih, "VALUECHANGING_CB"); if (cb) cb(ih, 0); iupAttribSet(ih, "_IUP_GLVAL_DRAG", NULL); } } iupGLSubCanvasRedraw(ih); } (void)status; return IUP_DEFAULT; } static int iGLValMOTION_CB(Ihandle* ih, int x, int y, char* status) { int redraw = 0; int pressed = iupAttribGetInt(ih, "PRESSED"); /* special highlight processing for handler area */ if (iGLValIsInsideHandler(ih, x, y)) { if (!iupAttribGet(ih, "HIGHLIGHT")) { redraw = 1; iupAttribSet(ih, "HIGHLIGHT", "1"); } } else { if (iupAttribGet(ih, "HIGHLIGHT")) { redraw = 1; iupAttribSet(ih, "HIGHLIGHT", NULL); } } if (pressed) { int start_x = iupAttribGetInt(ih, "_IUP_GLVAL_START_X"); int start_y = iupAttribGetInt(ih, "_IUP_GLVAL_START_Y"); if (iGLValMoveHandler(ih, x - start_x, y - start_y)) { iupGLSubCanvasRedraw(ih); redraw = 0; if (!iupAttribGet(ih, "_IUP_GLVAL_DRAG")) { IFni cb = (IFni)IupGetCallback(ih, "VALUECHANGING_CB"); if (cb) cb(ih, 1); } iupBaseCallValueChangedCb(ih); iupAttribSet(ih, "_IUP_GLVAL_DRAG", "1"); } iupAttribSetInt(ih, "_IUP_GLVAL_START_X", x); iupAttribSetInt(ih, "_IUP_GLVAL_START_Y", y); } if (redraw) iupGLSubCanvasRedraw(ih); (void)status; return IUP_DEFAULT; } static int iGLValENTERWINDOW_CB(Ihandle* ih, int x, int y) { /* special highlight processing for handler area */ if (iGLValIsInsideHandler(ih, x, y)) iupAttribSet(ih, "HIGHLIGHT", "1"); else iupAttribSet(ih, "HIGHLIGHT", NULL); return iupGLSubCanvasRedraw(ih); } static int iGLValSetValueAttrib(Ihandle* ih, const char* value) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); if (iupStrToDouble(value, &(val->value))) iGLValCropValue(val); return 0; /* do not store value in hash table */ } static char* iGLValGetValueAttrib(Ihandle* ih) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); return iupStrReturnDouble(val->value); } static int iGLValSetMinAttrib(Ihandle* ih, const char* value) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); if (iupStrToDouble(value, &(val->vmin))) iGLValCropValue(val); return 0; /* do not store value in hash table */ } static char* iGLValGetMinAttrib(Ihandle* ih) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); return iupStrReturnDouble(val->vmin); } static int iGLValSetMaxAttrib(Ihandle* ih, const char* value) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); if (iupStrToDouble(value, &(val->vmax))) iGLValCropValue(val); return 0; /* do not store value in hash table */ } static char* iGLValGetMaxAttrib(Ihandle* ih) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); return iupStrReturnDouble(val->vmax); } static void iGLValComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *children_expand) { int natural_w = 0, natural_h = 0; int fit2backimage = iupAttribGetBoolean(ih, "FITTOBACKIMAGE"); char* bgimage = iupAttribGet(ih, "BACKIMAGE"); if (fit2backimage && bgimage) { iupAttribSet(ih, "BORDERWIDTH", "0"); iupGLImageGetInfo(bgimage, &natural_w, &natural_h, NULL); } else { int charwidth, charheight; int is_horizontal = iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "HORIZONTAL"); iupGLFontGetCharSize(ih, &charwidth, &charheight); if (is_horizontal) { natural_h = charheight; if (ih->userwidth <= 0) natural_w = 15 * charwidth; } else { natural_w = charheight; if (ih->userheight <= 0) natural_h = 15 * charwidth; } } *w = natural_w; *h = natural_h; (void)children_expand; /* unset if not a container */ } static int iGLValCreateMethod(Ihandle* ih, void **params) { iGLVal* val = (iGLVal*)malloc(sizeof(iGLVal)); iupAttribSet(ih, "_IUP_GLVAL", (char*)val); memset(val, 0, sizeof(iGLVal)); /* default values */ val->vmax = 1; IupSetCallback(ih, "GL_ACTION", (Icallback)iGLValACTION_CB); IupSetCallback(ih, "GL_BUTTON_CB", (Icallback)iGLValBUTTON_CB); IupSetCallback(ih, "GL_MOTION_CB", (Icallback)iGLValMOTION_CB); IupSetCallback(ih, "GL_LEAVEWINDOW_CB", iupGLSubCanvasRedraw); IupSetCallback(ih, "GL_ENTERWINDOW_CB", (Icallback)iGLValENTERWINDOW_CB); (void)params; return IUP_NOERROR; } static void iGLValDestroyMethod(Ihandle* ih) { iGLVal* val = (iGLVal*)iupAttribGet(ih, "_IUP_GLVAL"); free(val); } Iclass* iupGLValNewClass(void) { Iclass* ic = iupClassNew(iupRegisterFindClass("glsubcanvas")); ic->name = "glval"; ic->cons = "GLVal"; ic->format = NULL; /* no parameters */ ic->nativetype = IUP_TYPEVOID; ic->childtype = IUP_CHILDNONE; ic->is_interactive = 0; /* Class functions */ ic->New = iupGLValNewClass; ic->Create = iGLValCreateMethod; ic->Destroy = iGLValDestroyMethod; ic->ComputeNaturalSize = iGLValComputeNaturalSizeMethod; /* Callbacks */ iupClassRegisterCallback(ic, "VALUECHANGED_CB", ""); iupClassRegisterCallback(ic, "VALUECHANGING_CB", "i"); /* IupGLVal only */ iupClassRegisterAttribute(ic, "MIN", iGLValGetMinAttrib, iGLValSetMinAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "MAX", iGLValGetMaxAttrib, iGLValSetMaxAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "VALUE", iGLValGetValueAttrib, iGLValSetValueAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "ORIENTATION", NULL, NULL, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SLIDERSIZE", NULL, NULL, IUPAF_SAMEASSYSTEM, "5", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "200 225 245", IUPAF_DEFAULT); /* inheritable */ iupClassRegisterAttribute(ic, "HLCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "190 210 230", IUPAF_DEFAULT); /* inheritable */ iupClassRegisterAttribute(ic, "HANDLERSIZE", NULL, NULL, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGE", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEPRESS", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEHIGHLIGHT", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "IMAGEINACTIVE", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BACKIMAGE", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BACKIMAGEPRESS", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BACKIMAGEHIGHLIGHT", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "BACKIMAGEINACTIVE", NULL, NULL, NULL, NULL, IUPAF_IHANDLENAME | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "FITTOBACKIMAGE", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); return ic; } Ihandle* IupGLVal(void) { return IupCreate("glval"); }