Correct beast manual install instructions in Windows.
[kugel-rb.git] / apps / gui / viewport.c
blobb5696842e30ddf569860fb403e1e5dde4ab7289f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Jonathan Gordon
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <stdlib.h>
23 #include "config.h"
24 #include "lcd.h"
25 #include "lcd-remote.h"
26 #include "font.h"
27 #include "viewport.h"
28 #include "screen_access.h"
29 #include "settings.h"
30 #include "misc.h"
32 /*some short cuts for fg/bg/line selector handling */
33 #ifdef HAVE_LCD_COLOR
34 #define FG_FALLBACK global_settings.fg_color
35 #define BG_FALLBACK global_settings.bg_color
36 #else
37 #define FG_FALLBACK LCD_DEFAULT_FG
38 #define BG_FALLBACK LCD_DEFAULT_BG
39 #endif
41 /* all below isn't needed for pc tools (i.e. checkwps/wps editor)
42 * only viewport_parse_viewport() is */
43 #ifndef __PCTOOL__
44 #include "sprintf.h"
45 #include "string.h"
46 #include "kernel.h"
47 #include "system.h"
48 #include "statusbar.h"
49 #include "appevents.h"
50 #ifdef HAVE_LCD_BITMAP
51 #include "language.h"
52 #endif
53 #include "statusbar-skinned.h"
54 #include "debug.h"
57 static int statusbar_enabled = 0;
59 #ifdef HAVE_LCD_BITMAP
60 static void set_default_align_flags(struct viewport *vp);
62 static struct {
63 struct viewport* vp;
64 int active[NB_SCREENS];
65 } ui_vp_info;
67 static struct viewport custom_vp[NB_SCREENS];
69 /* callbacks for GUI_EVENT_* events */
70 static void viewportmanager_ui_vp_changed(void *param);
71 static void statusbar_toggled(void* param);
72 static unsigned viewport_init_ui_vp(void);
73 #endif
74 static void viewportmanager_redraw(void* data);
76 int viewport_get_nb_lines(const struct viewport *vp)
78 #ifdef HAVE_LCD_BITMAP
79 return vp->height/font_get(vp->font)->height;
80 #else
81 (void)vp;
82 return 2;
83 #endif
86 static bool showing_bars(enum screen_type screen)
88 if (statusbar_enabled & VP_SB_ONSCREEN(screen))
90 #ifdef HAVE_LCD_BITMAP
91 int ignore;
92 ignore = statusbar_enabled & VP_SB_IGNORE_SETTING(screen);
93 return ignore || (statusbar_position(screen) != STATUSBAR_OFF);
94 #else
95 return true;
96 #endif
98 return false;
101 void viewport_set_fullscreen(struct viewport *vp,
102 const enum screen_type screen)
104 vp->x = 0;
105 vp->width = screens[screen].lcdwidth;
107 #ifdef HAVE_LCD_BITMAP
108 struct viewport *sb_skin_vp = sb_skin_get_info_vp(screen);
109 if (sb_skin_vp && sb_skin_get_state(screen)
110 && statusbar_enabled & VP_SB_ONSCREEN(screen))
112 *vp = *sb_skin_vp;
114 else
116 if (statusbar_position(screen) != STATUSBAR_BOTTOM && showing_bars(screen))
117 vp->y = STATUSBAR_HEIGHT;
118 else
119 vp->y = 0;
120 #else
122 vp->y = 0;
123 #endif
124 vp->height = screens[screen].lcdheight
125 - (showing_bars(screen)?STATUSBAR_HEIGHT:0);
128 #ifdef HAVE_LCD_BITMAP
129 set_default_align_flags(vp);
130 vp->font = FONT_UI; /* default to UI to discourage SYSFONT use */
131 vp->drawmode = DRMODE_SOLID;
132 #if LCD_DEPTH > 1
133 #ifdef HAVE_REMOTE_LCD
134 /* We only need this test if there is a remote LCD */
135 if (screen == SCREEN_MAIN)
136 #endif
138 vp->fg_pattern = FG_FALLBACK;
139 vp->bg_pattern = BG_FALLBACK;
140 #ifdef HAVE_LCD_COLOR
141 vp->lss_pattern = global_settings.lss_color;
142 vp->lse_pattern = global_settings.lse_color;
143 vp->lst_pattern = global_settings.lst_color;
144 #endif
146 #endif
148 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
149 if (screen == SCREEN_REMOTE)
151 vp->fg_pattern = LCD_REMOTE_DEFAULT_FG;
152 vp->bg_pattern = LCD_REMOTE_DEFAULT_BG;
154 #endif
155 #endif
158 void viewport_set_defaults(struct viewport *vp,
159 const enum screen_type screen)
161 #ifdef HAVE_LCD_BITMAP
162 if (ui_vp_info.active[screen])
163 *vp = ui_vp_info.vp[screen];
164 else
165 #endif
166 viewport_set_fullscreen(vp, screen);
170 void viewportmanager_init(void)
172 #ifdef HAVE_LCD_BITMAP
173 int retval, i;
174 add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, statusbar_toggled);
175 retval = viewport_init_ui_vp();
176 FOR_NB_SCREENS(i)
177 ui_vp_info.active[i] = retval & BIT_N(i);
178 ui_vp_info.vp = custom_vp;
179 #endif
180 viewportmanager_set_statusbar(VP_SB_ALLSCREENS);
183 int viewportmanager_get_statusbar(void)
185 return statusbar_enabled;
188 int viewportmanager_set_statusbar(const int enabled)
190 int old = statusbar_enabled;
191 int i;
193 statusbar_enabled = enabled;
195 FOR_NB_SCREENS(i)
197 if (showing_bars(i)
198 && statusbar_position(i) != STATUSBAR_CUSTOM)
200 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
201 gui_statusbar_draw(&statusbars.statusbars[i], true);
203 else
204 remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
207 #ifdef HAVE_LCD_BITMAP
208 FOR_NB_SCREENS(i)
210 sb_skin_set_state(showing_bars(i)
211 && statusbar_position(i) == STATUSBAR_CUSTOM, i);
213 #endif
214 return old;
217 static void viewportmanager_redraw(void* data)
219 int i;
221 FOR_NB_SCREENS(i)
223 if (showing_bars(i)
224 && statusbar_position(i) != STATUSBAR_CUSTOM)
225 gui_statusbar_draw(&statusbars.statusbars[i], NULL != data);
228 #ifdef HAVE_LCD_BITMAP
230 static void statusbar_toggled(void* param)
232 (void)param;
233 /* update vp manager for the new setting and reposition vps
234 * if necessary */
235 viewportmanager_theme_changed(THEME_STATUSBAR);
238 void viewportmanager_theme_changed(const int which)
240 int i;
241 #ifdef HAVE_BUTTONBAR
242 if (which & THEME_BUTTONBAR)
243 { /* don't handle further, the custom ui viewport ignores the buttonbar,
244 * as does viewport_set_defaults(), since only lists use it*/
245 screens[SCREEN_MAIN].has_buttonbar = global_settings.buttonbar;
247 #endif
248 if (which & THEME_UI_VIEWPORT)
250 int retval = viewport_init_ui_vp();
251 /* reset the ui viewport */
252 FOR_NB_SCREENS(i)
253 ui_vp_info.active[i] = retval & BIT_N(i);
254 /* and point to it */
255 ui_vp_info.vp = custom_vp;
257 else if (which & THEME_LANGUAGE)
258 { /* THEME_UI_VIEWPORT handles rtl already */
259 FOR_NB_SCREENS(i)
260 set_default_align_flags(&custom_vp[i]);
262 if (which & THEME_STATUSBAR)
264 statusbar_enabled = 0;
265 FOR_NB_SCREENS(i)
267 if (statusbar_position(i) != STATUSBAR_OFF)
268 statusbar_enabled |= VP_SB_ONSCREEN(i);
271 viewportmanager_set_statusbar(statusbar_enabled);
273 /* reposition viewport to fit statusbar, only if not using the ui vp */
275 FOR_NB_SCREENS(i)
277 if (!ui_vp_info.active[i])
278 viewport_set_fullscreen(&custom_vp[i], i);
282 int event_add = 0;
283 FOR_NB_SCREENS(i)
285 event_add |= ui_vp_info.active[i];
286 event_add |= (statusbar_position(i) == STATUSBAR_CUSTOM);
289 if (event_add)
290 add_event(GUI_EVENT_REFRESH, false, viewportmanager_ui_vp_changed);
291 else
292 remove_event(GUI_EVENT_REFRESH, viewportmanager_ui_vp_changed);
294 send_event(GUI_EVENT_THEME_CHANGED, NULL);
297 static void viewportmanager_ui_vp_changed(void *param)
299 /* if the user changed the theme, we need to initiate a full redraw */
300 int i;
301 /* cast param to a function */
302 void (*draw_func)(void) = ((void(*)(void))param);
303 /* start with clearing the screen */
304 FOR_NB_SCREENS(i)
305 screens[i].clear_display();
306 /* redraw the statusbar if it was enabled */
307 send_event(GUI_EVENT_ACTIONUPDATE, (void*)true);
308 /* call the passed function which will redraw the content of
309 * the current screen */
310 if (draw_func != NULL)
311 draw_func();
312 FOR_NB_SCREENS(i)
313 screens[i].update();
316 void viewport_set_current_vp(struct viewport* vp)
318 if (vp != NULL)
319 ui_vp_info.vp = vp;
320 else
321 ui_vp_info.vp = custom_vp;
323 /* must be done after the assignment above or event handler get old vps */
324 send_event(GUI_EVENT_THEME_CHANGED, NULL);
327 struct viewport* viewport_get_current_vp(void)
329 return ui_vp_info.vp;
332 bool viewport_ui_vp_get_state(enum screen_type screen)
334 return ui_vp_info.active[screen];
338 * (re)parse the UI vp from the settings
339 * - Returns
340 * 0 if no UI vp is used at all
341 * else the bit for the screen (1<<screen) is set
343 static unsigned viewport_init_ui_vp(void)
345 int screen;
346 unsigned ret = 0;
347 char *setting;
348 FOR_NB_SCREENS(screen)
350 #ifdef HAVE_REMOTE_LCD
351 if ((screen == SCREEN_REMOTE))
352 setting = global_settings.remote_ui_vp_config;
353 else
354 #endif
355 setting = global_settings.ui_vp_config;
358 if (!(viewport_parse_viewport(&custom_vp[screen], screen,
359 setting, ',')))
360 viewport_set_fullscreen(&custom_vp[screen], screen);
361 else
362 ret |= BIT_N(screen);
364 return ret;
367 #ifdef HAVE_TOUCHSCREEN
368 /* check if a point (x and y coordinates) are within a viewport */
369 bool viewport_point_within_vp(const struct viewport *vp,
370 const int x, const int y)
372 bool is_x = (x >= vp->x && x < (vp->x + vp->width));
373 bool is_y = (y >= vp->y && y < (vp->y + vp->height));
374 return (is_x && is_y);
376 #endif /* HAVE_TOUCHSCREEN */
377 #endif /* HAVE_LCD_BITMAP */
378 #endif /* __PCTOOL__ */
380 #ifdef HAVE_LCD_COLOR
381 #define ARG_STRING(_depth) ((_depth) == 2 ? "dddddgg":"dddddcc")
382 #else
383 #define ARG_STRING(_depth) "dddddgg"
384 #endif
386 #ifdef HAVE_LCD_BITMAP
388 static void set_default_align_flags(struct viewport *vp)
390 vp->flags &= ~VP_FLAG_ALIGNMENT_MASK;
391 #ifndef __PCTOOL__
392 if (UNLIKELY(lang_is_rtl()))
393 vp->flags |= VP_FLAG_ALIGN_RIGHT;
394 #endif
397 const char* viewport_parse_viewport(struct viewport *vp,
398 enum screen_type screen,
399 const char *bufptr,
400 const char separator)
402 /* parse the list to the viewport struct */
403 const char *ptr = bufptr;
404 int depth;
405 uint32_t set = 0;
407 enum {
408 PL_X = 0,
409 PL_Y,
410 PL_WIDTH,
411 PL_HEIGHT,
412 PL_FONT,
413 PL_FG,
414 PL_BG,
417 /* Work out the depth of this display */
418 depth = screens[screen].depth;
419 #if (LCD_DEPTH == 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH == 1)
420 if (depth == 1)
422 if (!(ptr = parse_list("ddddd", &set, separator, ptr,
423 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font)))
424 return NULL;
426 else
427 #endif
428 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
429 if (depth >= 2)
431 if (!(ptr = parse_list(ARG_STRING(depth), &set, separator, ptr,
432 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font,
433 &vp->fg_pattern,&vp->bg_pattern)))
434 return NULL;
436 else
437 #endif
439 #undef ARG_STRING
441 /* X and Y *must* be set */
442 if (!LIST_VALUE_PARSED(set, PL_X) || !LIST_VALUE_PARSED(set, PL_Y))
443 return NULL;
444 /* check for negative values */
445 if (vp->x < 0)
446 vp->x += screens[screen].lcdwidth;
447 if (vp->y < 0)
448 vp->y += screens[screen].lcdheight;
450 /* fix defaults,
451 * and negative width/height which means "extend to edge minus value */
452 if (!LIST_VALUE_PARSED(set, PL_WIDTH))
453 vp->width = screens[screen].lcdwidth - vp->x;
454 else if (vp->width < 0)
455 vp->width = (vp->width + screens[screen].lcdwidth) - vp->x;
456 if (!LIST_VALUE_PARSED(set, PL_HEIGHT))
457 vp->height = screens[screen].lcdheight - vp->y;
458 else if (vp->height < 0)
459 vp->height = (vp->height + screens[screen].lcdheight) - vp->y;
461 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
462 if (!LIST_VALUE_PARSED(set, PL_FG))
463 vp->fg_pattern = FG_FALLBACK;
464 if (!LIST_VALUE_PARSED(set, PL_BG))
465 vp->bg_pattern = BG_FALLBACK;
466 #endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */
468 #ifdef HAVE_LCD_COLOR
469 vp->lss_pattern = global_settings.lss_color;
470 vp->lse_pattern = global_settings.lse_color;
471 vp->lst_pattern = global_settings.lst_color;
472 #endif
474 /* Validate the viewport dimensions - we know that the numbers are
475 non-negative integers, ignore bars and assume the viewport takes them
476 * into account */
477 if ((vp->x >= screens[screen].lcdwidth) ||
478 ((vp->x + vp->width) > screens[screen].lcdwidth) ||
479 (vp->y >= screens[screen].lcdheight) ||
480 ((vp->y + vp->height) > screens[screen].lcdheight))
482 return NULL;
485 /* Default to using the user font if the font was an invalid number or '-'*/
486 if (((vp->font != FONT_SYSFIXED) && (vp->font != FONT_UI))
487 || !LIST_VALUE_PARSED(set, PL_FONT)
489 vp->font = FONT_UI;
491 /* Set the defaults for fields not user-specified */
492 vp->drawmode = DRMODE_SOLID;
493 set_default_align_flags(vp);
495 return ptr;
497 #endif