/* extracted from the SCROLLBAR attribute documentation */ void scrollbar_update(Ihandle* ih, int view_width, int view_height) { /* view_width and view_height is the virtual space size */ /* here we assume XMIN=0, XMAX=1, YMIN=0, YMAX=1 */ int elem_width, elem_height; int canvas_width, canvas_height; int scrollbar_size = IupGetInt(NULL, "SCROLLBARSIZE"); int border = IupGetInt(ih, "BORDER"); IupGetIntInt(ih, "RASTERSIZE", &elem_width, &elem_height); /* if view is greater than canvas in one direction, then it has scrollbars, but this affects the opposite direction */ elem_width -= 2 * border; /* remove BORDER (always size=1) */ elem_height -= 2 * border; canvas_width = elem_width; canvas_height = elem_height; if (view_width > elem_width) /* check for horizontal scrollbar */ canvas_height -= scrollbar_size; /* affect vertical size */ if (view_height > elem_height) canvas_width -= scrollbar_size; if (view_width <= elem_width && view_width > canvas_width) /* check if still has horizontal scrollbar */ canvas_height -= scrollbar_size; if (view_height <= elem_height && view_height > canvas_height) canvas_width -= scrollbar_size; if (canvas_width < 0) canvas_width = 0; if (canvas_height < 0) canvas_height = 0; IupSetFloat(ih, "DX", (float)canvas_width / (float)view_width); IupSetFloat(ih, "DY", (float)canvas_height / (float)view_height); }
/* Calculate the size, in pixels, of the invisible columns/lines, the left/above of the first column/line. In fact the start position of the visible area. Depends on the first visible column/line. -> m : choose will operate on lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL] */ void iupMatrixAuxUpdateScrollPos(Ihandle* ih, int m) { float pos; int i, sb, scroll_pos; char* POS; ImatLinColData *p; if (m == IMAT_PROCESS_LIN) { p = &(ih->data->lines); sb = IUP_SB_VERT; POS = "POSY"; } else { p = &(ih->data->columns); sb = IUP_SB_HORIZ; POS = "POSX"; } /* "first" was changed, so update "last" and the scroll pos */ if (p->total_visible_size <= p->current_visible_size) { /* the matrix is fully visible */ p->first = p->num_noscroll; p->first_offset = 0; p->last = p->num==p->num_noscroll? p->num_noscroll: p->num-1; if (ih->data->canvas.sb & sb) IupSetAttribute(ih, POS, "0"); return; } /* must check if it is a valid position */ scroll_pos = 0; for(i = p->num_noscroll; i < p->first; i++) scroll_pos += p->dt[i].size; scroll_pos += p->first_offset; if (scroll_pos + p->current_visible_size > p->total_visible_size) { /* invalid condition, must recalculate so it is valid */ scroll_pos = p->total_visible_size - p->current_visible_size; /* position first and first_offset, according to scroll pos */ iupMatrixAuxAdjustFirstFromScrollPos(p, scroll_pos); } pos = (float)scroll_pos/(float)p->total_visible_size; /* update last */ iupMatrixAuxUpdateLast(p); /* update scroll pos */ if (ih->data->canvas.sb & sb) IupSetFloat(ih, POS, pos); }
void scroll_center(Ihandle* canvas, float old_center_x, float old_center_y) { /* always update the scroll position keeping it proportional to the old position relative to the center of the canvas. */ float dx = IupGetFloat(canvas, "DX"); float dy = IupGetFloat(canvas, "DY"); float posx = old_center_x - dx / 2.0f; float posy = old_center_y - dy / 2.0f; if (posx < 0) posx = 0; if (posx > 1 - dx) posx = 1 - dx; if (posy < 0) posy = 0; if (posy > 1 - dy) posy = 1 - dy; IupSetFloat(canvas, "POSX", posx); IupSetFloat(canvas, "POSY", posy); }
static void iMatrixAuxUpdateVisibleSize(Ihandle* ih, int m) { char *D, *AUTOHIDE; ImatLinColData *p; int canvas_size, fixed_size, i, SB; if (m == IMAT_PROCESS_LIN) { D = "DY"; /* when configuring the vertical scrollbar check if horizontal scrollbar can be hidden */ AUTOHIDE = "XAUTOHIDE"; SB = IUP_SB_HORIZ; p = &(ih->data->lines); canvas_size = ih->data->h; } else { D = "DX"; /* when configuring the horizontal scrollbar check if vertical scrollbar can be hidden */ AUTOHIDE = "YAUTOHIDE"; SB = IUP_SB_VERT; p = &(ih->data->columns); canvas_size = ih->data->w; } fixed_size = 0; for (i=0; i<p->num_noscroll; i++) fixed_size += p->dt[i].size; /* Matrix useful area is the current size minus the non scrollable area */ p->current_visible_size = canvas_size - fixed_size; if (p->current_visible_size > p->total_visible_size) p->current_visible_size = p->total_visible_size; if (!p->total_visible_size || p->current_visible_size == p->total_visible_size) IupSetAttribute(ih, D, "1"); else { if (ih->data->limit_expand && (ih->data->canvas.sb & SB) && iupAttribGetBoolean(ih, AUTOHIDE)) { /* Must perform an extra check or the scrollbar will be always visible */ int sb_size = iupdrvGetScrollbarSize(); if (p->current_visible_size + sb_size == p->total_visible_size) p->current_visible_size = p->total_visible_size; } IupSetFloat(ih, D, (float)p->current_visible_size/(float)p->total_visible_size); } }
static void motCanvasInputCallback(Widget w, Ihandle *ih, XtPointer call_data) { XEvent *evt = ((XmDrawingAreaCallbackStruct*)call_data)->event; if (!XtWindow(w) || !ih) return; switch (evt->type) { case ButtonPress: /* Force focus on canvas click */ if (iupAttribGetBoolean(ih, "CANFOCUS")) XmProcessTraversal(w, XmTRAVERSE_CURRENT); /* break missing on purpose... */ case ButtonRelease: { XButtonEvent *but_evt = (XButtonEvent*)evt; Boolean cont = True; iupmotButtonPressReleaseEvent(w, ih, evt, &cont); if (cont == False) return; if ((evt->type==ButtonPress) && (but_evt->button==Button4 || but_evt->button==Button5)) { IFnfiis wcb = (IFnfiis)IupGetCallback(ih, "WHEEL_CB"); if (wcb) { char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT; int delta = but_evt->button==Button4? 1: -1; iupmotButtonKeySetStatus(but_evt->state, but_evt->button, status, 0); wcb(ih, (float)delta, but_evt->x, but_evt->y, status); } else { IFniff scb = (IFniff)IupGetCallback(ih,"SCROLL_CB"); float posy = ih->data->posy; int delta = but_evt->button==Button4? 1: -1; int op = but_evt->button==Button4? IUP_SBUP: IUP_SBDN; posy -= delta*iupAttribGetFloat(ih, "DY")/10.0f; IupSetFloat(ih, "POSY", posy); if (scb) scb(ih,op,ih->data->posx,ih->data->posy); } } } break; } }
int canvas_wheel_cb(Ihandle* canvas, float delta) { if (IupGetInt(NULL, "CONTROLKEY")) { if (delta < 0) zoomout_action_cb(canvas); else zoomin_action_cb(canvas); } else { float posy = IupGetFloat(canvas, "POSY"); posy -= delta * IupGetFloat(canvas, "DY") / 10.0f; IupSetFloat(canvas, "POSY", posy); IupUpdate(canvas); } return IUP_DEFAULT; }