1 /*
2 * See Licensing and Copyright notice in naev.h
3 */
4
5 /**
6 * @file imagearray.c
7 *
8 * @brief Image array widget.
9 */
10
11
12 #include "tk/toolkit_priv.h"
13
14 #include <stdlib.h>
15 #include "nstring.h"
16
17 #include "opengl.h"
18
19
20 /* Render. */
21 static void iar_render( Widget* iar, double bx, double by );
22 static void iar_renderOverlay( Widget* iar, double bx, double by );
23 /* Key. */
24 static int iar_key( Widget* iar, SDLKey key, SDLMod mod );
25 /* Mouse. */
26 static int iar_mclick( Widget* iar, int button, int x, int y );
27 #if SDL_VERSION_ATLEAST(2,0,0)
28 static int iar_mwheel( Widget* lst, SDL_MouseWheelEvent event );
29 #endif /* SDL_VERSION_ATLEAST(2,0,0) */
30 static int iar_mmove( Widget* iar, int x, int y, int rx, int ry );
31 /* Focus. */
32 static int iar_focusImage( Widget* iar, double bx, double by );
33 static void iar_focus( Widget* iar, double bx, double by );
34 static void iar_scroll( Widget* iar, int direction );
35 static void iar_centerSelected( Widget *iar );
36 /* Misc. */
37 static void iar_setAltTextPos( Widget *iar, double bx, double by );
38 static Widget *iar_getWidget( const unsigned int wid, const char *name );
39 static char* toolkit_getNameById( Widget *wgt, int elem );
40 /* Clean up. */
41 static void iar_cleanup( Widget* iar );
42
43
44 /**
45 * @brief Adds an Image Array widget.
46 *
47 * Position origin is 0,0 at bottom left. If you use negative X or Y
48 * positions. They actually count from the opposite side in.
49 *
50 * @param wid Window to add to.
51 * @param x X position.
52 * @param y Y position.
53 * @param w Width.
54 * @param h Height.
55 * @param name Internal widget name.
56 * @param iw Image width to use.
57 * @param ih Image height to use.
58 * @param tex Texture array to use (not freed).
59 * @param caption Caption array to use (freed).
60 * @param nelem Elements in tex and caption.
61 * @param call Callback when modified.
62 */
window_addImageArray(const unsigned int wid,const int x,const int y,const int w,const int h,char * name,const int iw,const int ih,glTexture ** tex,char ** caption,int nelem,void (* call)(unsigned int wdw,char * wgtname),void (* rmcall)(unsigned int wdw,char * wgtname))63 void window_addImageArray( const unsigned int wid,
64 const int x, const int y, /* position */
65 const int w, const int h, /* size */
66 char* name, const int iw, const int ih,
67 glTexture** tex, char** caption, int nelem,
68 void (*call) (unsigned int wdw, char* wgtname),
69 void (*rmcall) (unsigned int wdw, char* wgtname) )
70 {
71 Window *wdw = window_wget(wid);
72 Widget *wgt = window_newWidget(wdw, name);
73 if (wgt == NULL)
74 return;
75
76 /* generic */
77 wgt->type = WIDGET_IMAGEARRAY;
78
79 /* position/size */
80 wgt->w = (double) w;
81 wgt->h = (double) h;
82 toolkit_setPos( wdw, wgt, x, y );
83
84 /* specific */
85 wgt->render = iar_render;
86 wgt->renderOverlay = iar_renderOverlay;
87 wgt->cleanup = iar_cleanup;
88 wgt_setFlag(wgt, WGT_FLAG_CANFOCUS);
89 wgt->keyevent = iar_key;
90 wgt->mclickevent = iar_mclick;
91 #if SDL_VERSION_ATLEAST(2,0,0)
92 wgt->mwheelevent = iar_mwheel;
93 #endif /* SDL_VERSION_ATLEAST(2,0,0) */
94 wgt->mmoveevent = iar_mmove;
95 wgt_setFlag(wgt, WGT_FLAG_ALWAYSMMOVE);
96 wgt->dat.iar.images = tex;
97 wgt->dat.iar.captions = caption;
98 wgt->dat.iar.nelements = nelem;
99 wgt->dat.iar.selected = 0;
100 wgt->dat.iar.pos = 0;
101 wgt->dat.iar.alt = -1;
102 wgt->dat.iar.altx = -1;
103 wgt->dat.iar.alty = -1;
104 wgt->dat.iar.iw = iw;
105 wgt->dat.iar.ih = ih;
106 wgt->dat.iar.fptr = call;
107 wgt->dat.iar.rmptr = rmcall;
108 wgt->dat.iar.xelem = floor((w - 10.) / (double)(wgt->dat.iar.iw+10));
109 wgt->dat.iar.yelem = (wgt->dat.iar.xelem == 0) ? 0 :
110 (int)wgt->dat.iar.nelements / wgt->dat.iar.xelem + 1;
111
112 if (wdw->focus == -1) /* initialize the focus */
113 toolkit_nextFocus( wdw );
114 }
115
116
117 /**
118 * @brief Gets image array effective dimensions.
119 */
iar_getDim(Widget * iar,double * w,double * h)120 static void iar_getDim( Widget* iar, double *w, double *h )
121 {
122 if (w != NULL)
123 *w = iar->dat.iar.iw + 5.*2.;
124 if (h != NULL)
125 *h = iar->dat.iar.ih + 5.*2. + 2. + gl_smallFont.h;
126 }
127
128
129 /**
130 * @brief Renders an image array.
131 *
132 * @param iar Image array widget to render.
133 * @param bx Base X position.
134 * @param by Base Y position.
135 */
iar_render(Widget * iar,double bx,double by)136 static void iar_render( Widget* iar, double bx, double by )
137 {
138 int i,j, pos;
139 double x,y, w,h, xcurs,ycurs;
140 double scroll_pos;
141 int xelem, yelem;
142 double xspace;
143 const glColour *c, *dc, *lc;
144 glColour tc, fontcolour;
145 int is_selected;
146 int tw;
147 double d;
148
149 /*
150 * Calculations.
151 */
152 /* position */
153 x = bx + iar->x;
154 y = by + iar->y;
155
156 /* element dimensions */
157 iar_getDim( iar, &w, &h );
158
159 /* number of elements */
160 xelem = iar->dat.iar.xelem;
161 yelem = iar->dat.iar.yelem;
162 xspace = (double)(((int)iar->w - 10) % (int)w) / (double)(xelem + 1);
163
164 /* background */
165 toolkit_drawRect( x, y, iar->w, iar->h, &cBlack, NULL );
166
167 /*
168 * Scrollbar.
169 */
170 d = h * (yelem - (int)(iar->h / h));
171 if (fabs(d) < 1e-05)
172 scroll_pos = 0.;
173 else
174 scroll_pos = iar->dat.iar.pos / d;
175 toolkit_drawScrollbar( x + iar->w - 10., y, 10., iar->h, scroll_pos );
176
177 /*
178 * Main drawing loop.
179 */
180 gl_clipRect( x, y, iar->w, iar->h );
181 ycurs = y + iar->h - h + iar->dat.iar.pos;
182 for (j=0; j<yelem; j++) {
183 xcurs = x + xspace;
184
185 /* Skip rows that are wholly outside of the viewport. */
186 if ((ycurs > y + iar->h) || (ycurs + h < y)) {
187 ycurs -= h;
188 continue;
189 }
190
191 for (i=0; i<xelem; i++) {
192
193 /* Get position. */
194 pos = j*xelem + i;
195
196 /* Out of elements. */
197 if ((pos) >= iar->dat.iar.nelements)
198 break;
199
200 is_selected = (iar->dat.iar.selected == pos) ? 1 : 0;
201
202 fontcolour = cWhite;
203 /* Draw background. */
204 if (is_selected)
205 toolkit_drawRect( xcurs + 2.,
206 ycurs + 2.,
207 w - 5., h - 5., &cDConsole, NULL );
208 else if (iar->dat.iar.background != NULL) {
209 toolkit_drawRect( xcurs + 2.,
210 ycurs + 2.,
211 w - 5., h - 5., &iar->dat.iar.background[pos], NULL );
212
213 tc = iar->dat.iar.background[pos];
214
215 if (((tc.r + tc.g + tc.b) / 3) > 0.5)
216 fontcolour = cBlack;
217 }
218
219 /* image */
220 if (iar->dat.iar.images[pos] != NULL)
221 gl_blitScale( iar->dat.iar.images[pos],
222 xcurs + 5., ycurs + gl_smallFont.h + 7.,
223 iar->dat.iar.iw, iar->dat.iar.ih, NULL );
224
225 /* caption */
226 if (iar->dat.iar.captions[pos] != NULL)
227 gl_printMidRaw( &gl_smallFont, iar->dat.iar.iw, xcurs + 5., ycurs + 5.,
228 (is_selected) ? &cBlack : &fontcolour,
229 iar->dat.iar.captions[pos] );
230
231 /* quantity. */
232 if (iar->dat.iar.quantity != NULL) {
233 if (iar->dat.iar.quantity[pos] != NULL) {
234 /* Rectangle to highlight better. */
235 tw = gl_printWidthRaw( &gl_smallFont,
236 iar->dat.iar.quantity[pos] );
237
238 if (is_selected)
239 tc = cDConsole;
240 else if (iar->dat.iar.background != NULL)
241 tc = iar->dat.iar.background[pos];
242 else
243 tc = cBlack;
244
245 tc.a = 0.75;
246 toolkit_drawRect( xcurs + 2.,
247 ycurs + 5. + iar->dat.iar.ih,
248 tw + 4., gl_smallFont.h + 4., &tc, NULL );
249 /* Quantity number. */
250 gl_printMaxRaw( &gl_smallFont, iar->dat.iar.iw,
251 xcurs + 5., ycurs + iar->dat.iar.ih + 7.,
252 &fontcolour, iar->dat.iar.quantity[pos] );
253 }
254 }
255
256 /* Slot type. */
257 if (iar->dat.iar.slottype != NULL) {
258 if (iar->dat.iar.slottype[pos] != NULL) {
259 /* Rectangle to highlight better. Width is a hack due to lack of monospace font. */
260 tw = gl_printWidthRaw( &gl_smallFont, "M" );
261
262 if (is_selected)
263 tc = cDConsole;
264 else if (iar->dat.iar.background != NULL)
265 tc = iar->dat.iar.background[pos];
266 else
267 tc = cBlack;
268
269 tc.a = 0.75;
270 toolkit_drawRect( xcurs + iar->dat.iar.iw - 6.,
271 ycurs + 5. + iar->dat.iar.ih,
272 tw + 2., gl_smallFont.h + 4., &tc, NULL );
273 /* Slot size letter. */
274 gl_printMaxRaw( &gl_smallFont, iar->dat.iar.iw,
275 xcurs + iar->dat.iar.iw - 4., ycurs + iar->dat.iar.ih + 7.,
276 &fontcolour, iar->dat.iar.slottype[pos] );
277 }
278 }
279
280 /* outline */
281 if (is_selected) {
282 lc = &cWhite;
283 c = &cGrey80;
284 dc = &cGrey60;
285 }
286 else {
287 lc = toolkit_colLight;
288 c = toolkit_col;
289 dc = toolkit_colDark;
290 }
291 toolkit_drawOutline( xcurs + 2.,
292 ycurs + 2.,
293 w - 4., h - 4., 1., lc, c );
294 toolkit_drawOutline( xcurs + 2.,
295 ycurs + 2.,
296 w - 4., h - 4., 2., dc, NULL );
297 xcurs += w + xspace;
298 }
299 ycurs -= h;
300 }
301 gl_unclipRect();
302
303 /*
304 * Final outline.
305 */
306 toolkit_drawOutline( x+1, y+1, iar->w-2, iar->h-2, 1., toolkit_colLight, toolkit_col );
307 toolkit_drawOutline( x+1, y+1, iar->w-2, iar->h-2, 2., toolkit_colDark, NULL );
308 }
309
310
311 /**
312 * @brief Renders the overlay.
313 */
iar_renderOverlay(Widget * iar,double bx,double by)314 static void iar_renderOverlay( Widget* iar, double bx, double by )
315 {
316 double x, y;
317
318 /*
319 * Draw Alt text if applicable.
320 */
321 if ((iar->dat.iar.alts != NULL) && (iar->dat.iar.alt >= 0) &&
322 (iar->dat.iar.altx != -1) && (iar->dat.iar.alty != -1) &&
323 (iar->dat.iar.alts[iar->dat.iar.alt] != NULL)) {
324
325 /* Calculate position. */
326 x = bx + iar->x + iar->dat.iar.altx;
327 y = by + iar->y + iar->dat.iar.alty;
328
329 /* Draw alt text. */
330 toolkit_drawAltText( x, y, iar->dat.iar.alts[iar->dat.iar.alt] );
331 }
332 }
333
334
335 /**
336 * @brief Handles input for an image array widget.
337 *
338 * @param iar Image array widget to handle event.
339 * @param key Key being handled.
340 * @param mod Mods when key is being pressed.
341 * @return 1 if the event was used, 0 if it wasn't.
342 */
iar_key(Widget * iar,SDLKey key,SDLMod mod)343 static int iar_key( Widget* iar, SDLKey key, SDLMod mod )
344 {
345 (void) mod;
346
347 switch (key) {
348 case SDLK_UP:
349 iar->dat.iar.selected -= iar->dat.iar.xelem;
350 break;
351 case SDLK_DOWN:
352 iar->dat.iar.selected += iar->dat.iar.xelem;
353 break;
354 case SDLK_RIGHT:
355 iar->dat.iar.selected += 1;
356 break;
357 case SDLK_LEFT:
358 iar->dat.iar.selected -= 1;
359 break;
360
361 default:
362 return 0;
363 }
364
365 /* Check boundaries. */
366 iar->dat.iar.selected = CLAMP( 0, iar->dat.iar.nelements-1, iar->dat.iar.selected);
367
368 /* Run function pointer if needed. */
369 if (iar->dat.iar.fptr)
370 iar->dat.iar.fptr( iar->wdw, iar->name);
371
372 iar_centerSelected( iar );
373 return 1;
374 }
375
376
377 /**
378 * @brief Centers on the selection if needed.
379 *
380 * @param iar Widget to center on selection.
381 */
iar_centerSelected(Widget * iar)382 static void iar_centerSelected( Widget *iar )
383 {
384 int y;
385 double h;
386 double hmax;
387 double ypos;
388
389 /* Get dimensions. */
390 iar_getDim( iar, NULL, &h );
391
392 /* Ignore fancy stuff if smaller than height. */
393 if (h * iar->dat.iar.yelem < iar->h)
394 return;
395
396 /* Move if needed. */
397 hmax = h * (iar->dat.iar.yelem - (int)(iar->h / h));
398 y = iar->dat.iar.selected / iar->dat.iar.xelem;
399 ypos = y * h;
400 /* Below. */
401 if (ypos < iar->dat.iar.pos)
402 iar->dat.iar.pos = ypos;
403 /* Above. */
404 if (ypos > iar->dat.iar.pos + iar->h - h)
405 iar->dat.iar.pos = ypos - h*floor(iar->h/h) + 10.;
406 iar->dat.iar.pos = CLAMP( 0., hmax, iar->dat.iar.pos );
407
408 iar_setAltTextPos( iar, iar->dat.iar.altx, iar->dat.iar.alty );
409 }
410
411
412 /**
413 * @brief Image array widget mouse click handler.
414 *
415 * @param iar Widget receiving the event.
416 * @param mclick The mouse click event.
417 * @return 1 if event is used.
418 */
iar_mclick(Widget * iar,int button,int x,int y)419 static int iar_mclick( Widget* iar, int button, int x, int y )
420 {
421 /* Handle different mouse clicks. */
422 switch (button) {
423 case SDL_BUTTON_LEFT:
424 iar_focus( iar, x, y );
425 return 1;
426 #if !SDL_VERSION_ATLEAST(2,0,0)
427 case SDL_BUTTON_WHEELUP:
428 iar_scroll( iar, +1 );
429 return 1;
430 case SDL_BUTTON_WHEELDOWN:
431 iar_scroll( iar, -1 );
432 return 1;
433 #endif /* !SDL_VERSION_ATLEAST(2,0,0) */
434 case SDL_BUTTON_RIGHT:
435 iar_focus( iar, x, y );
436 if (iar->dat.iar.rmptr != NULL)
437 iar->dat.iar.rmptr( iar->wdw, iar->name );
438
439 iar_setAltTextPos( iar, x, y );
440
441 return 1;
442
443 default:
444 break;
445 }
446 return 0;
447 }
448
449
450 #if SDL_VERSION_ATLEAST(2,0,0)
451 /**
452 * @brief Handler for mouse wheel events for an image array.
453 *
454 * @param iar The widget handling the mouse wheel event.
455 * @param event The event the widget should handle.
456 * @return 1 if the widget uses the event.
457 */
iar_mwheel(Widget * iar,SDL_MouseWheelEvent event)458 static int iar_mwheel( Widget* iar, SDL_MouseWheelEvent event )
459 {
460 if (event.y > 0)
461 iar_scroll( iar, +1 );
462 else
463 iar_scroll( iar, -1 );
464
465 return 1;
466 }
467 #endif /* SDL_VERSION_ATLEAST(2,0,0) */
468
469
470 /**
471 * @brief Handles mouse movement for an image array.
472 *
473 * @param iar Widget handling the mouse motion.
474 * @param mmove Mouse motion event to handle.
475 * @return 1 if the event is used.
476 */
iar_mmove(Widget * iar,int x,int y,int rx,int ry)477 static int iar_mmove( Widget* iar, int x, int y, int rx, int ry )
478 {
479 (void) rx;
480 (void) ry;
481 double w,h;
482 int yelem;
483 double hmax;
484
485 if (iar->status == WIDGET_STATUS_SCROLLING) {
486
487 y = CLAMP( 15, iar->h - 15., iar->h - y );
488
489 /* element dimensions */
490 iar_getDim( iar, &w, &h );
491
492 /* number of elements */
493 yelem = iar->dat.iar.yelem;
494
495 hmax = h * (yelem - (int)(iar->h / h));
496 iar->dat.iar.pos = (y - 15.) * hmax / (iar->h - 30.);
497
498 /* Does boundary checks. */
499 iar_scroll( iar, 0 );
500
501 return 1;
502 }
503 else {
504 if ((x < 0) || (x >= iar->w) || (y < 0) || (y >= iar->h))
505 iar->dat.iar.alt = -1;
506 else
507 iar_setAltTextPos( iar, x, y );
508 }
509
510 return 0;
511 }
512
513
514 /**
515 * @brief Clean up function for the image array widget.
516 *
517 * @param iar Image array widget to clean up.
518 */
iar_cleanup(Widget * iar)519 static void iar_cleanup( Widget* iar )
520 {
521 int i;
522
523 if (iar->dat.iar.nelements > 0) { /* Free each text individually */
524 for (i=0; i<iar->dat.iar.nelements; i++) {
525 if (iar->dat.iar.captions[i])
526 free(iar->dat.iar.captions[i]);
527 if (iar->dat.iar.alts && iar->dat.iar.alts[i])
528 free(iar->dat.iar.alts[i]);
529 if (iar->dat.iar.quantity && iar->dat.iar.quantity[i])
530 free(iar->dat.iar.quantity[i]);
531 }
532 }
533
534 /* Clean up slottypes. */
535 if (iar->dat.iar.slottype != NULL) {
536 for (i=0; i<iar->dat.iar.nelements; i++) {
537 if (iar->dat.iar.slottype[i] != NULL)
538 free( iar->dat.iar.slottype[i] );
539 }
540 free(iar->dat.iar.slottype);
541 }
542
543
544 /* Free the arrays */
545 if (iar->dat.iar.captions != NULL)
546 free( iar->dat.iar.captions );
547 if (iar->dat.iar.images != NULL)
548 free( iar->dat.iar.images );
549 if (iar->dat.iar.alts != NULL)
550 free(iar->dat.iar.alts);
551 if (iar->dat.iar.quantity != NULL)
552 free(iar->dat.iar.quantity);
553 if (iar->dat.iar.background != NULL)
554 free(iar->dat.iar.background);
555 }
556
557
558 /**
559 * @brief Tries to scroll a widget up/down by direction.
560 *
561 * @param wgt Widget to scroll.
562 * @param direction Direction to scroll. Positive is up, negative
563 * is down and absolute value is number of elements to scroll.
564 */
iar_scroll(Widget * iar,int direction)565 static void iar_scroll( Widget* iar, int direction )
566 {
567 double w,h;
568 int yelem;
569 double hmax;
570
571 if (iar == NULL)
572 return;
573
574 /* element dimensions */
575 iar_getDim( iar, &w, &h );
576
577 /* number of elements */
578 yelem = iar->dat.iar.yelem;
579
580 /* maximum */
581 hmax = h * (yelem - (int)(iar->h / h));
582 if (hmax < 0.)
583 hmax = 0.;
584
585 /* move */
586 iar->dat.iar.pos -= direction * h;
587
588 /* Boundary check. */
589 iar->dat.iar.pos = CLAMP( 0., hmax, iar->dat.iar.pos );
590 if (iar->dat.iar.fptr)
591 iar->dat.iar.fptr( iar->wdw, iar->name );
592
593 iar_setAltTextPos( iar, iar->dat.iar.altx, iar->dat.iar.alty );
594 }
595
596
597 /**
598 * @brief See what widget is being focused.
599 */
iar_focusImage(Widget * iar,double bx,double by)600 static int iar_focusImage( Widget* iar, double bx, double by )
601 {
602 int x, y;
603 double w, h;
604 int xelem;
605 double xspace;
606
607 /* element dimensions */
608 iar_getDim( iar, &w, &h );
609
610 /* number of elements */
611 xelem = iar->dat.iar.xelem;
612 xspace = (double)(((int)iar->w - 10) % (int)w) / (double)(xelem + 1);
613
614 x = bx / (xspace + w);
615 y = (iar->h - by + iar->dat.iar.pos) / h;
616
617 /* Reject anything too close to the scroll bar or exceeding nelements. */
618 if (y * xelem + x >= iar->dat.iar.nelements || bx >= iar->w - 10.)
619 return -1;
620
621 /* Verify that the mouse is on an icon. */
622 if ((bx < (x+1) * xspace + x * w) || (bx > (x+1) * (xspace + w) - 4.) ||
623 (by > iar->h + iar->dat.iar.pos - y * h - 4.))
624 return -1;
625
626 return y * xelem + x;
627 }
628
629
630
631 /**
632 * @brief Mouse event focus on image array.
633 *
634 * @param iar Image Array widget.
635 * @param bx X position click.
636 * @param by Y position click.
637 */
iar_focus(Widget * iar,double bx,double by)638 static void iar_focus( Widget* iar, double bx, double by )
639 {
640 double y, h;
641 double scroll_pos, hmax;
642 int yelem;
643 int selected;
644
645 /* element dimensions */
646 iar_getDim( iar, NULL, &h );
647
648 /* number of elements */
649 yelem = iar->dat.iar.yelem;
650
651 /* Test for item click. */
652 selected = iar_focusImage( iar, bx, by );
653 if (selected >= 0) {
654 iar->dat.iar.selected = selected;
655 if (iar->dat.iar.fptr != NULL)
656 iar->dat.iar.fptr( iar->wdw, iar->name );
657 }
658 /* Scrollbar click. */
659 else if (bx > iar->w - 10.) {
660 /* Get bar position (center). */
661 hmax = h * (yelem - (int)(iar->h / h));
662 if (fabs(hmax) < 1e-05)
663 scroll_pos = 0.;
664 else
665 scroll_pos = iar->dat.iar.pos / hmax;
666 y = iar->h - (iar->h - 30.) * scroll_pos - 15.;
667
668 /* Click below the bar. */
669 if (by < y-15.)
670 iar_scroll( iar, -2 );
671 /* Click above the bar. */
672 else if (by > y+15.)
673 iar_scroll( iar, +2 );
674 /* Click on the bar. */
675 else
676 iar->status = WIDGET_STATUS_SCROLLING;
677 }
678 }
679
680
681 /**
682 * @brief Chooses correct alt text for the given coordinates
683 *
684 */
iar_setAltTextPos(Widget * iar,double bx,double by)685 static void iar_setAltTextPos( Widget *iar, double bx, double by )
686 {
687 iar->dat.iar.alt = iar_focusImage( iar, bx, by );
688 iar->dat.iar.altx = bx;
689 iar->dat.iar.alty = by;
690 }
691
692
693 /**
694 * @brief Gets an image array.
695 */
iar_getWidget(const unsigned int wid,const char * name)696 static Widget *iar_getWidget( const unsigned int wid, const char *name )
697 {
698 Widget *wgt = window_getwgt(wid,name);
699
700 /* Must be found in stack. */
701 if (wgt == NULL) {
702 WARN("Widget '%s' not found", name);
703 return NULL;
704 }
705
706 /* Must be an image array. */
707 if (wgt->type != WIDGET_IMAGEARRAY) {
708 WARN("Widget '%s' is not an image array.", name);
709 return NULL;
710 }
711
712 return wgt;
713 }
714
715
716 /**
717 * @brief Gets the name of the element.
718 *
719 * @param wid Window where image array is.
720 * @param name Name of the image array.
721 * @param elem The element in the image array.
722 * @return The name of the selected object.
723 */
toolkit_getNameById(Widget * wgt,int elem)724 static char* toolkit_getNameById( Widget *wgt, int elem )
725 {
726 if (wgt == NULL)
727 return NULL;
728
729 /* Nothing selected. */
730 if (elem == -1)
731 return NULL;
732
733 return wgt->dat.iar.captions[ elem ];
734 }
735
736
737 /**
738 * @brief Gets what is selected currently in an Image Array.
739 *
740 * @param wid Window where image array is.
741 * @param name Name of the image array.
742 * @return The name of the selected object.
743 */
toolkit_getImageArray(const unsigned int wid,const char * name)744 char* toolkit_getImageArray( const unsigned int wid, const char* name )
745 {
746 Widget *wgt = iar_getWidget( wid, name );
747 if (wgt == NULL)
748 return NULL;
749
750 return toolkit_getNameById( wgt, wgt->dat.iar.selected );
751 }
752
753
754 /**
755 * @brief Sets an image array based on value.
756 */
toolkit_setImageArray(const unsigned int wid,const char * name,char * elem)757 int toolkit_setImageArray( const unsigned int wid, const char* name, char* elem )
758 {
759 int i;
760 Widget *wgt = iar_getWidget( wid, name );
761 if (wgt == NULL)
762 return -1;
763
764 /* Case NULL. */
765 if (elem == NULL) {
766 wgt->dat.iar.selected = -1;
767 return 0;
768 }
769
770 /* Try to find the element. */
771 for (i=0; i<wgt->dat.iar.nelements; i++) {
772 if (strcmp(elem,wgt->dat.iar.captions[i])==0) {
773 wgt->dat.iar.selected = i;
774 return 0;
775 }
776 }
777
778 /* Element not found. */
779 return -1;
780 }
781
782
783 /**
784 * @brief Gets what is selected currently in an Image Array.
785 *
786 * @param wid Window where image array is.
787 * @param name Name of the image array.
788 * @return The position of selected object.
789 */
toolkit_getImageArrayPos(const unsigned int wid,const char * name)790 int toolkit_getImageArrayPos( const unsigned int wid, const char* name )
791 {
792 Widget *wgt = iar_getWidget( wid, name );
793 if (wgt == NULL)
794 return -1;
795
796 return wgt->dat.iar.selected;
797 }
798
799
800 /**
801 * @brief Gets the Image Array offset.
802 */
toolkit_getImageArrayOffset(const unsigned int wid,const char * name)803 double toolkit_getImageArrayOffset( const unsigned int wid, const char* name )
804 {
805 Widget *wgt = iar_getWidget( wid, name );
806 if (wgt == NULL)
807 return -1.;
808
809 return wgt->dat.iar.pos;
810 }
811
812
813 /**
814 * @brief Sets the Image Array offset.
815 */
toolkit_setImageArrayOffset(const unsigned int wid,const char * name,double off)816 int toolkit_setImageArrayOffset( const unsigned int wid, const char* name, double off )
817 {
818 double h;
819 double hmax;
820
821 Widget *wgt = iar_getWidget( wid, name );
822 if (wgt == NULL)
823 return -1;
824
825 /* Get dimensions. */
826 iar_getDim( wgt, NULL, &h );
827
828 /* Ignore fancy stuff if smaller than height. */
829 if (h * wgt->dat.iar.yelem < wgt->h) {
830 wgt->dat.iar.pos = 0.;
831 return 0;
832 }
833
834 /* Move if needed. */
835 hmax = h * (wgt->dat.iar.yelem - (int)(wgt->h / h));
836 wgt->dat.iar.pos = CLAMP( 0., hmax, off );
837
838 iar_setAltTextPos( wgt, wgt->dat.iar.altx, wgt->dat.iar.alty );
839
840 return 0;
841 }
842
843
844 /**
845 * @brief Sets the active element in the Image Array.
846 *
847 * @param wid Window where image array is.
848 * @param name Name of the image array.
849 * @param pos Position to set to.
850 * @return 0 on success.
851 */
toolkit_setImageArrayPos(const unsigned int wid,const char * name,int pos)852 int toolkit_setImageArrayPos( const unsigned int wid, const char* name, int pos )
853 {
854 Widget *wgt = iar_getWidget( wid, name );
855 if (wgt == NULL)
856 return -1;
857
858 /* Set position. */
859 wgt->dat.iar.selected = CLAMP( 0, wgt->dat.iar.nelements-1, pos );
860
861 /* Call callback - dangerous if called from within callback. */
862 if (wgt->dat.iar.fptr != NULL)
863 wgt->dat.iar.fptr( wgt->wdw, wgt->name );
864
865 iar_centerSelected( wgt );
866
867 return 0;
868 }
869
870
871 /**
872 * @brief Sets the alt text for the images in the image array.
873 *
874 * @param wid Window where image array is.
875 * @param name Name of the image array.
876 * @param alt Array of alt text the size of the images in the array.
877 * @return 0 on success.
878 */
toolkit_setImageArrayAlt(const unsigned int wid,const char * name,char ** alt)879 int toolkit_setImageArrayAlt( const unsigned int wid, const char* name, char **alt )
880 {
881 int i;
882 Widget *wgt = iar_getWidget( wid, name );
883 if (wgt == NULL)
884 return -1;
885
886 /* Clean up. */
887 if (wgt->dat.iar.alts != NULL) {
888 for (i=0; i<wgt->dat.iar.nelements; i++)
889 if (wgt->dat.iar.alts[i] != NULL)
890 free(wgt->dat.iar.alts[i]);
891 free(wgt->dat.iar.alts);
892 }
893
894 /* Set. */
895 wgt->dat.iar.alts = alt;
896 return 0;
897 }
898
899
900 /**
901 * @brief Sets the quantity text for the images in the image array.
902 *
903 * @param wid Window where image array is.
904 * @param name Name of the image array.
905 * @param quantity Array of quantities for the images in the array.
906 * @return 0 on success.
907 */
toolkit_setImageArrayQuantity(const unsigned int wid,const char * name,char ** quantity)908 int toolkit_setImageArrayQuantity( const unsigned int wid, const char* name,
909 char **quantity )
910 {
911 int i;
912 Widget *wgt = iar_getWidget( wid, name );
913 if (wgt == NULL)
914 return -1;
915
916 /* Clean up. */
917 if (wgt->dat.iar.quantity != NULL) {
918 for (i=0; i<wgt->dat.iar.nelements; i++)
919 if (wgt->dat.iar.quantity[i] != NULL)
920 free(wgt->dat.iar.quantity[i]);
921 free(wgt->dat.iar.quantity);
922 }
923
924 /* Set. */
925 wgt->dat.iar.quantity = quantity;
926 return 0;
927 }
928
929
930 /**
931 * @brief Sets the slot type text for the images in the image array.
932 *
933 * @param wid Window where image array is.
934 * @param name Name of the image array.
935 * @param slottype Array of slot sizes for the images in the array.
936 * @return 0 on success.
937 */
toolkit_setImageArraySlotType(const unsigned int wid,const char * name,char ** slottype)938 int toolkit_setImageArraySlotType( const unsigned int wid, const char* name,
939 char **slottype )
940 {
941 int i;
942 Widget *wgt = iar_getWidget( wid, name );
943 if (wgt == NULL)
944 return -1;
945
946 /* Clean up. */
947 if (wgt->dat.iar.slottype != NULL) {
948 for (i=0; i<wgt->dat.iar.nelements; i++)
949 if (wgt->dat.iar.slottype[i] != NULL)
950 free(wgt->dat.iar.slottype[i]);
951 free(wgt->dat.iar.slottype);
952 }
953
954 /* Set. */
955 wgt->dat.iar.slottype = slottype;
956 return 0;
957 }
958
959
960 /**
961 * @brief Sets the background colour for the images in the image array.
962 *
963 * @param wid Window where image array is.
964 * @param name Name of the image array.
965 * @param bg Background colour for the image array.
966 * @return 0 on success.
967 */
toolkit_setImageArrayBackground(const unsigned int wid,const char * name,glColour * bg)968 int toolkit_setImageArrayBackground( const unsigned int wid, const char* name,
969 glColour *bg )
970 {
971 Widget *wgt = iar_getWidget( wid, name );
972 if (wgt == NULL)
973 return -1;
974
975 /* Free if already exists. */
976 if (wgt->dat.iar.background != NULL)
977 free( wgt->dat.iar.background );
978
979 /* Set. */
980 wgt->dat.iar.background = bg;
981 return 0;
982 }
983
984
985 /**
986 * @brief Stores several image array attributes.
987 *
988 * @param wid Window containing the image array.
989 * @param name Name of the image array widget.
990 * @param iar_data Pointer to an iar_data_t struct.
991 * @return 0 on success.
992 */
toolkit_saveImageArrayData(const unsigned int wid,const char * name,iar_data_t * iar_data)993 int toolkit_saveImageArrayData( const unsigned int wid, const char *name,
994 iar_data_t *iar_data )
995 {
996 Widget *wgt = iar_getWidget( wid, name );
997 if (wgt == NULL)
998 return -1;
999
1000 iar_data->pos = wgt->dat.iar.selected;
1001 iar_data->offset = wgt->dat.iar.pos;
1002
1003 return 0;
1004 }
1005