/** * @brief Tries to scroll a widget up/down by direction. * * @param wgt Widget to scroll. * @param direction Direction to scroll. Positive is up, negative * is down and absolute value is number of elements to scroll. */ static void iar_scroll( Widget* iar, int direction ) { double w,h; int yelem; double hmax; if (iar == NULL) return; /* element dimensions */ iar_getDim( iar, &w, &h ); /* number of elements */ yelem = iar->dat.iar.yelem; /* maximum */ hmax = h * (yelem - (int)(iar->h / h)); if (hmax < 0.) hmax = 0.; /* move */ iar->dat.iar.pos -= direction * h; /* Boundary check. */ iar->dat.iar.pos = CLAMP( 0., hmax, iar->dat.iar.pos ); if (iar->dat.iar.fptr) iar->dat.iar.fptr( iar->wdw, iar->name ); }
/** * @brief Centers on the selection if needed. * * @param iar Widget to center on selection. */ static void iar_centerSelected( Widget *iar ) { int y; double h; double hmax; double ypos; /* Get dimensions. */ iar_getDim( iar, NULL, &h ); /* Ignore fancy stuff if smaller than height. */ if (h * iar->dat.iar.yelem < iar->h) return; /* Move if needed. */ hmax = h * (iar->dat.iar.yelem - (int)(iar->h / h)); y = iar->dat.iar.selected / iar->dat.iar.xelem; ypos = y * h; /* Below. */ if (ypos < iar->dat.iar.pos) iar->dat.iar.pos = ypos; /* Above. */ if (ypos > iar->dat.iar.pos + iar->h - h) iar->dat.iar.pos = ypos - h*floor(iar->h/h) + 10.; iar->dat.iar.pos = CLAMP( 0., hmax, iar->dat.iar.pos ); }
/** * @brief Mouse event focus on image array. * * @param iar Image Array widget. * @param bx X position click. * @param by Y position click. */ static void iar_focus( Widget* iar, double bx, double by ) { double y, h; double scroll_pos, hmax; int yelem; int selected; /* element dimensions */ iar_getDim( iar, NULL, &h ); /* number of elements */ yelem = iar->dat.iar.yelem; /* Test for item click. */ selected = iar_focusImage( iar, bx, by ); if (selected >= 0) { iar->dat.iar.selected = selected; if (iar->dat.iar.fptr != NULL) iar->dat.iar.fptr( iar->wdw, iar->name ); } /* Scrollbar click. */ else if (bx > iar->w - 10.) { /* Get bar position (center). */ hmax = h * (yelem - (int)(iar->h / h)); if (fabs(hmax) < 1e-05) scroll_pos = 0.; else scroll_pos = iar->dat.iar.pos / hmax; y = iar->h - (iar->h - 30.) * scroll_pos - 15.; /* Click below the bar. */ if (by < y-15.) iar_scroll( iar, -2 ); /* Click above the bar. */ else if (by > y+15.) iar_scroll( iar, +2 ); /* Click on the bar. */ else iar->status = WIDGET_STATUS_SCROLLING; } }
/** * @brief See what widget is being focused. */ static int iar_focusImage( Widget* iar, double bx, double by ) { int i,j; double y, w,h, ycurs,xcurs; int xelem, yelem; double xspace; /* positions */ y = by + iar->y; /* element dimensions */ iar_getDim( iar, &w, &h ); /* number of elements */ xelem = iar->dat.iar.xelem; yelem = iar->dat.iar.yelem; xspace = (double)(((int)iar->w - 10) % (int)w) / (double)(xelem + 1); if (bx < iar->w - 10.) { /* Loop through elements until finding collision. */ ycurs = iar->h - h + iar->dat.iar.pos; for (j=0; j<yelem; j++) { xcurs = xspace; for (i=0; i<xelem; i++) { /* Out of elements. */ if ((j*xelem + i) >= iar->dat.iar.nelements) break; /* Check for collision. */ if ((bx > xcurs) && (bx < xcurs+w-4.) && (by > ycurs) && (by < ycurs+h-4.)) { return j*xelem + i; } xcurs += xspace + w; } ycurs -= h; } } return -1; }
/** * @brief Handles mouse movement for an image array. * * @param iar Widget handling the mouse motion. * @param mmove Mouse motion event to handle. * @return 1 if the event is used. */ static int iar_mmove( Widget* iar, int x, int y, int rx, int ry ) { (void) rx; (void) ry; double w,h; int xelem, yelem; double hmax; if (iar->status == WIDGET_STATUS_SCROLLING) { y = CLAMP( 15, iar->h - 15., iar->h - y ); /* element dimensions */ iar_getDim( iar, &w, &h ); /* number of elements */ xelem = iar->dat.iar.xelem; yelem = iar->dat.iar.yelem; hmax = h * (yelem - (int)(iar->h / h)); iar->dat.iar.pos = (y - 15.) * hmax / (iar->h - 30.); /* Does boundry checks. */ iar_scroll( iar, 0 ); return 1; } else { if ((x < 0) || (x >= iar->w) || (y < 0) || (y >= iar->h)) iar->dat.iar.alt = -1; else { iar->dat.iar.alt = iar_focusImage( iar, x, y ); iar->dat.iar.altx = x; iar->dat.iar.alty = y; } } return 0; }
/** * @brief Sets the Image Array offset. */ int toolkit_setImageArrayOffset( const unsigned int wid, const char* name, double off ) { double h; double hmax; Widget *wgt = iar_getWidget( wid, name ); if (wgt == NULL) return -1; /* Get dimensions. */ iar_getDim( wgt, NULL, &h ); /* Ignore fancy stuff if smaller than height. */ if (h * wgt->dat.iar.yelem < wgt->h) { wgt->dat.iar.pos = 0.; return 0; } /* Move if needed. */ hmax = h * (wgt->dat.iar.yelem - (int)(wgt->h / h)); wgt->dat.iar.pos = CLAMP( 0., hmax, off ); return 0; }
/** * @brief Renders an image array. * * @param iar Image array widget to render. * @param bx Base X position. * @param by Base Y position. */ static void iar_render( Widget* iar, double bx, double by ) { int i,j, pos; double x,y, w,h, xcurs,ycurs; double scroll_pos; int xelem, yelem; double xspace; glColour *c, *dc, *lc, tc, fontcolour; int is_selected; int tw; double d; /* * Calculations. */ /* position */ x = bx + iar->x; y = by + iar->y; /* element dimensions */ iar_getDim( iar, &w, &h ); /* number of elements */ xelem = iar->dat.iar.xelem; yelem = iar->dat.iar.yelem; xspace = (double)(((int)iar->w - 10) % (int)w) / (double)(xelem + 1); /* background */ toolkit_drawRect( x, y, iar->w, iar->h, &cBlack, NULL ); /* * Scrollbar. */ d = h * (yelem - (int)(iar->h / h)); if (fabs(d) < 1e-05) scroll_pos = 0.; else scroll_pos = iar->dat.iar.pos / d; toolkit_drawScrollbar( x + iar->w - 10., y, 10., iar->h, scroll_pos ); /* * Main drawing loop. */ gl_clipRect( x, y, iar->w, iar->h ); ycurs = y + iar->h - h + iar->dat.iar.pos; for (j=0; j<yelem; j++) { xcurs = x + xspace; for (i=0; i<xelem; i++) { /* Get position. */ pos = j*xelem + i; /* Out of elements. */ if ((pos) >= iar->dat.iar.nelements) break; is_selected = (iar->dat.iar.selected == pos) ? 1 : 0; fontcolour = cWhite; /* Draw background. */ if (is_selected) toolkit_drawRect( xcurs + 2., ycurs + 2., w - 5., h - 5., &cDConsole, NULL ); else if (iar->dat.iar.background != NULL) { toolkit_drawRect( xcurs + 2., ycurs + 2., w - 5., h - 5., &iar->dat.iar.background[pos], NULL ); tc = iar->dat.iar.background[pos]; if (((tc.r + tc.g + tc.b) / 3) > 0.5) fontcolour = cBlack; } /* image */ if (iar->dat.iar.images[pos] != NULL) gl_blitScale( iar->dat.iar.images[pos], xcurs + 5., ycurs + gl_smallFont.h + 7., iar->dat.iar.iw, iar->dat.iar.ih, NULL ); /* caption */ if (iar->dat.iar.captions[pos] != NULL) gl_printMidRaw( &gl_smallFont, iar->dat.iar.iw, xcurs + 5., ycurs + 5., (is_selected) ? &cBlack : &fontcolour, iar->dat.iar.captions[pos] ); /* quantity. */ if (iar->dat.iar.quantity != NULL) { if (iar->dat.iar.quantity[pos] != NULL) { /* Rectangle to highlight better. */ tw = gl_printWidthRaw( &gl_smallFont, iar->dat.iar.quantity[pos] ); if (is_selected) tc = cDConsole; else if (iar->dat.iar.background != NULL) tc = iar->dat.iar.background[pos]; else tc = cBlack; tc.a = 0.75; toolkit_drawRect( xcurs + 2., ycurs + 5. + iar->dat.iar.ih, tw + 4., gl_smallFont.h + 4., &tc, NULL ); /* Quantity number. */ gl_printMaxRaw( &gl_smallFont, iar->dat.iar.iw, xcurs + 5., ycurs + iar->dat.iar.ih + 7., &fontcolour, iar->dat.iar.quantity[pos] ); } } /* Slot type. */ if (iar->dat.iar.slottype != NULL) { if (iar->dat.iar.slottype[pos] != NULL) { /* Rectangle to highlight better. Width is a hack due to lack of monospace font. */ tw = gl_printWidthRaw( &gl_smallFont, "M" ); if (is_selected) tc = cDConsole; else if (iar->dat.iar.background != NULL) tc = iar->dat.iar.background[pos]; else tc = cBlack; tc.a = 0.75; toolkit_drawRect( xcurs + iar->dat.iar.iw - 6., ycurs + 5. + iar->dat.iar.ih, tw + 2., gl_smallFont.h + 4., &tc, NULL ); /* Slot size letter. */ gl_printMaxRaw( &gl_smallFont, iar->dat.iar.iw, xcurs + iar->dat.iar.iw - 4., ycurs + iar->dat.iar.ih + 7., &fontcolour, iar->dat.iar.slottype[pos] ); } } /* outline */ if (is_selected) { lc = &cWhite; c = &cGrey80; dc = &cGrey60; } else { lc = toolkit_colLight; c = toolkit_col; dc = toolkit_colDark; } toolkit_drawOutline( xcurs + 2., ycurs + 2., w - 4., h - 4., 1., lc, c ); toolkit_drawOutline( xcurs + 2., ycurs + 2., w - 4., h - 4., 2., dc, NULL ); xcurs += w + xspace; } ycurs -= h; } gl_unclipRect(); /* * Final outline. */ toolkit_drawOutline( x+1, y+1, iar->w-2, iar->h-2, 1., toolkit_colLight, toolkit_col ); toolkit_drawOutline( x+1, y+1, iar->w-2, iar->h-2, 2., toolkit_colDark, NULL ); }