[Add] Significant inprovements to imageArray, including scrollwheel functionality.

This commit is contained in:
Allanis 2013-10-26 01:11:02 +01:00
parent 88c40143c2
commit e955b58817

View File

@ -31,7 +31,8 @@ typedef enum WidgetType_ {
typedef enum WidgetStatus_ { typedef enum WidgetStatus_ {
WIDGET_STATUS_NORMAL, WIDGET_STATUS_NORMAL,
WIDGET_STATUS_MOUSEOVER, WIDGET_STATUS_MOUSEOVER,
WIDGET_STATUS_MOUSEDOWN WIDGET_STATUS_MOUSEDOWN,
WIDGET_STATUS_SCROLLING
} WidgetStatus; } WidgetStatus;
typedef struct Widget_ { typedef struct Widget_ {
@ -135,6 +136,10 @@ static glColour* toolkit_colLight = &cGrey90;
static glColour* toolkit_col = &cGrey70; static glColour* toolkit_col = &cGrey70;
static glColour* toolkit_colDark = &cGrey30; static glColour* toolkit_colDark = &cGrey30;
/* Converts absolute mouse events to relative mouse events. */
static double last_x = 0.; /**< Last x mouse position. */
static double last_y = 0.; /**< Last y mouse position. */
/* Widgets. */ /* Widgets. */
static Widget* window_newWidget(Window* w); static Widget* window_newWidget(Window* w);
static void widget_cleanup(Widget* widget); static void widget_cleanup(Widget* widget);
@ -145,6 +150,7 @@ static void toolkit_setPos(Window* wdw, Widget* wgt, int x, int y);
static int toolkit_inputInput(Uint8 type, Widget* inp, SDLKey key); static int toolkit_inputInput(Uint8 type, Widget* inp, SDLKey key);
static void toolkit_mouseEvent(SDL_Event* event); static void toolkit_mouseEvent(SDL_Event* event);
static int toolkit_keyEvent(SDL_Event* event); static int toolkit_keyEvent(SDL_Event* event);
static void toolkit_imgarrMove(Widget* iar, double ry);
/* Focus. */ /* Focus. */
static void toolkit_nextFocus(void); static void toolkit_nextFocus(void);
static int toolkit_isFocusable(Widget* wgt); static int toolkit_isFocusable(Widget* wgt);
@ -1188,6 +1194,7 @@ static void toolkit_renderImageArray(Widget* iar, double bx, double by) {
double scroll_pos, sx, sy; double scroll_pos, sx, sy;
int xelem, yelem, xspace; int xelem, yelem, xspace;
glColour* c, *dc, *lc; glColour* c, *dc, *lc;
int is_selected;
x = bx + iar->x; x = bx + iar->x;
y = by + iar->y; y = by + iar->y;
@ -1202,7 +1209,7 @@ static void toolkit_renderImageArray(Widget* iar, double bx, double by) {
yelem = (int)iar->dat.iar.nelements / xelem + 1; yelem = (int)iar->dat.iar.nelements / xelem + 1;
/* Background. */ /* Background. */
toolkit_drawRect(x, y, iar->w, iar->h, toolkit_colDark, NULL); toolkit_drawRect(x, y, iar->w, iar->h, &cBlack, NULL);
/* Scrollbar. */ /* Scrollbar. */
@ -1227,10 +1234,17 @@ static void toolkit_renderImageArray(Widget* iar, double bx, double by) {
for(j = 0; j < yelem; j++) { for(j = 0; j < yelem; j++) {
xcurs = x + xspace + (double)SCREEN_W/2.; xcurs = x + xspace + (double)SCREEN_W/2.;
for(i = 0; i < xelem; i++) { for(i = 0; i < xelem; i++) {
/* Outfit elements. */ /* Out of elements. */
if((j*xelem + i) >= iar->dat.iar.nelements) if((j*xelem + i) >= iar->dat.iar.nelements)
break; break;
is_selected = (iar->dat.iar.selected == j*xelem + i) ? 1 : 0;
if(is_selected)
toolkit_drawRect(xcurs-(double)SCREEN_W/2. + 2.,
ycurs-(double)SCREEN_H/2. + 2.,
w - 4., h - 4., &cDConsole, NULL);
/* Image. */ /* Image. */
if(iar->dat.iar.images[j*xelem + i] != NULL) if(iar->dat.iar.images[j*xelem + i] != NULL)
gl_blitScale(iar->dat.iar.images[j*xelem + i], gl_blitScale(iar->dat.iar.images[j*xelem + i],
@ -1239,10 +1253,11 @@ static void toolkit_renderImageArray(Widget* iar, double bx, double by) {
/* Caption. */ /* Caption. */
gl_printMid(&gl_smallFont, iar->dat.iar.iw, xcurs + 5., ycurs + 5., gl_printMid(&gl_smallFont, iar->dat.iar.iw, xcurs + 5., ycurs + 5.,
&cBlack, iar->dat.iar.captions[j*xelem + i]); (is_selected) ? &cBlack : &cWhite,
iar->dat.iar.captions[j*xelem + i]);
/* Outline. */ /* Outline. */
if(iar->dat.iar.selected == j*xelem + i) { if(is_selected) {
lc = &cWhite; lc = &cWhite;
c = &cGrey80; c = &cGrey80;
dc = &cGrey60; dc = &cGrey60;
@ -1347,7 +1362,7 @@ int toolkit_input(SDL_Event* event) {
static int mouse_down = 0; static int mouse_down = 0;
static void toolkit_mouseEvent(SDL_Event* event) { static void toolkit_mouseEvent(SDL_Event* event) {
int i; int i;
double x, y; double x, y, rel_x, rel_y;
Window* w; Window* w;
Widget* wgt, *wgt_func; Widget* wgt, *wgt_func;
@ -1359,6 +1374,11 @@ static void toolkit_mouseEvent(SDL_Event* event) {
if(event->type == SDL_MOUSEMOTION) { if(event->type == SDL_MOUSEMOTION) {
x = (double)event->motion.x; x = (double)event->motion.x;
y = SCREEN_H - (double)event->motion.y; y = SCREEN_H - (double)event->motion.y;
/* Create relative events. */
rel_x = x - last_x;
rel_y = y - last_y;
last_x = x;
last_y = y;
} }
else if((event->type == SDL_MOUSEBUTTONDOWN) || (event->type == SDL_MOUSEBUTTONUP)) { else if((event->type == SDL_MOUSEBUTTONDOWN) || (event->type == SDL_MOUSEBUTTONUP)) {
x = (double)event->button.x; x = (double)event->button.x;
@ -1390,10 +1410,24 @@ static void toolkit_mouseEvent(SDL_Event* event) {
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
if(!mouse_down) if(!mouse_down)
wgt->status = WIDGET_STATUS_MOUSEOVER; wgt->status = WIDGET_STATUS_MOUSEOVER;
else {
if(wgt->type == WIDGET_IMAGEARRAY)
toolkit_imgarrMove(wgt, rel_y);
}
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
wgt->status = WIDGET_STATUS_MOUSEDOWN; wgt->status = WIDGET_STATUS_MOUSEDOWN;
/* Handle mouse wheel. */
if(event->button.button == SDL_BUTTON_WHEELUP) {
toolkit_listScroll(wgt, +1);
break;
}
if(event->button.button == SDL_BUTTON_WHEELDOWN) {
toolkit_listScroll(wgt, -1);
break;
}
if(toolkit_isFocusable(wgt)) if(toolkit_isFocusable(wgt))
w->focus = i; w->focus = i;
@ -1407,6 +1441,11 @@ static void toolkit_mouseEvent(SDL_Event* event) {
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
/* Since basically only buttons are handled here, we ignore
* it all except the left mouse button. */
if(event->button.button != SDL_BUTTON_LEFT)
break;
if(wgt->status == WIDGET_STATUS_MOUSEDOWN) { if(wgt->status == WIDGET_STATUS_MOUSEDOWN) {
if((wgt->type == WIDGET_BUTTON) && if((wgt->type == WIDGET_BUTTON) &&
(wgt->dat.btn.disabled==0)) { (wgt->dat.btn.disabled==0)) {
@ -1428,6 +1467,9 @@ static void toolkit_mouseEvent(SDL_Event* event) {
else if(!mouse_down) else if(!mouse_down)
wgt->status = WIDGET_STATUS_NORMAL; wgt->status = WIDGET_STATUS_NORMAL;
} }
/* We trigger this at the end in case it destroys the window that is calling
* this function. Otherwise ugly segfaults appear. */
if(wgt_func) (*wgt_func->dat.btn.fptr)(wgt_func->name); if(wgt_func) (*wgt_func->dat.btn.fptr)(wgt_func->name);
} }
@ -1568,6 +1610,7 @@ static int toolkit_isFocusable(Widget* wgt) {
if(wgt->dat.btn.disabled == 1) return 0; if(wgt->dat.btn.disabled == 1) return 0;
case WIDGET_LIST: case WIDGET_LIST:
case WIDGET_INPUT: case WIDGET_INPUT:
case WIDGET_IMAGEARRAY:
return 1; return 1;
default: default:
return 0; return 0;
@ -1599,6 +1642,10 @@ static void toolkit_triggerFocus(void) {
/* Try to scroll up/down by direction. */ /* Try to scroll up/down by direction. */
static void toolkit_listScroll(Widget* wgt, int direction) { static void toolkit_listScroll(Widget* wgt, int direction) {
double w, h;
int xelem, yelem;
double hmax;
if(wgt == NULL) return; if(wgt == NULL) return;
switch(wgt->type) { switch(wgt->type) {
@ -1608,6 +1655,28 @@ static void toolkit_listScroll(Widget* wgt, int direction) {
wgt->dat.lst.selected = MIN(wgt->dat.lst.selected, wgt->dat.lst.noptions-1); wgt->dat.lst.selected = MIN(wgt->dat.lst.selected, wgt->dat.lst.noptions-1);
if(wgt->dat.lst.fptr) (*wgt->dat.lst.fptr)(wgt->name); if(wgt->dat.lst.fptr) (*wgt->dat.lst.fptr)(wgt->name);
break; break;
case WIDGET_IMAGEARRAY:
/* Element dimensions. */
w = wgt->dat.iar.iw + 5.*2.; /* Includes border. */
h = wgt->dat.iar.ih + 5.*2. + 2 + gl_smallFont.h;
/* Number of elements. */
xelem = (int)((wgt->w - 10.) / w);
yelem = (int)wgt->dat.iar.nelements / xelem + 1;
/* Maximum. */
hmax = h * (yelem - (int)(wgt->h / h));
/* Move. */
wgt->dat.iar.pos -= direction * h;
/* Boundry check. */
wgt->dat.iar.pos = MAX(wgt->dat.iar.pos, 0.);
wgt->dat.iar.pos = MIN(wgt->dat.iar.pos, hmax);
if(wgt->dat.iar.fptr)(*wgt->dat.iar.fptr)(wgt->name);
break;
default: default:
break; break;
} }
@ -1735,25 +1804,46 @@ static void toolkit_imgarrFocus(Widget* iar, double bx, double by) {
y = iar->h - (iar->h - 30.) * scroll_pos - 15.; y = iar->h - (iar->h - 30.) * scroll_pos - 15.;
/* Click below the bar. */ /* Click below the bar. */
if(by < y-15.) { if(by < y-15.)
iar->dat.iar.pos += h*2.; toolkit_listScroll(iar, -2);
}
/* Click above the bar. */ /* Click above the bar. */
else if(by > y+15.) { else if(by > y+15.)
iar->dat.iar.pos -= h*2.; toolkit_listScroll(iar, +2);
} else { /* Click on the bar. */
else
iar->status = WIDGET_STATUS_SCROLLING;
}
} }
/* Boundry check. */ /**
if(iar->dat.iar.pos < 0.) * @fn static void toolkit_imgarrMove(Widget* iar, double ry)
iar->dat.iar.pos = 0.; *
else if(iar->dat.iar.pos > hmax) * @brief Handles image array movement.
iar->dat.iar.pos = hmax; * @param iar Image Array that has mouse movement.
* @param ry Relative Y mouse movement.
*/
static void toolkit_imgarrMove(Widget* iar, double ry) {
double w, h;
int xelem, yelem;
double hmax;
if(iar->status == WIDGET_STATUS_SCROLLING) {
/* Element dimensions. */
w = iar->dat.iar.iw + 5.*2.; /* Includes border. */
h = iar->dat.iar.ih + 5.*2. + 2. + gl_smallFont.h;
/* Number of elements. */
xelem = (int)((iar->w - 10.) / w);
yelem = (int)iar->dat.iar.nelements / xelem + 1;
hmax = h * (yelem - (int)(iar->h / h));
iar->dat.iar.pos -= (ry * (iar->w - 30.) / hmax) / 2.;
/* Does boundry checks. */
toolkit_listScroll(iar, 0);
} }
} }
/* Return the focused widget. */ /* Return the focused widget. */