summaryrefslogtreecommitdiff
path: root/apps/gui/viewport.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui/viewport.c')
-rw-r--r--apps/gui/viewport.c347
1 files changed, 178 insertions, 169 deletions
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index 9a7cfbd3cb..fbf5ea82ad 100644
--- a/apps/gui/viewport.c
+++ b/apps/gui/viewport.c
@@ -28,6 +28,8 @@
28#include "screen_access.h" 28#include "screen_access.h"
29#include "settings.h" 29#include "settings.h"
30#include "misc.h" 30#include "misc.h"
31#include "panic.h"
32#include "viewport.h"
31 33
32/*some short cuts for fg/bg/line selector handling */ 34/*some short cuts for fg/bg/line selector handling */
33#ifdef HAVE_LCD_COLOR 35#ifdef HAVE_LCD_COLOR
@@ -38,10 +40,6 @@
38#define BG_FALLBACK LCD_DEFAULT_BG 40#define BG_FALLBACK LCD_DEFAULT_BG
39#endif 41#endif
40 42
41#ifdef HAVE_LCD_BITMAP
42static void set_default_align_flags(struct viewport *vp);
43#endif
44
45/* all below isn't needed for pc tools (i.e. checkwps/wps editor) 43/* all below isn't needed for pc tools (i.e. checkwps/wps editor)
46 * only viewport_parse_viewport() is */ 44 * only viewport_parse_viewport() is */
47#ifndef __PCTOOL__ 45#ifndef __PCTOOL__
@@ -56,115 +54,187 @@ static void set_default_align_flags(struct viewport *vp);
56#endif 54#endif
57#include "statusbar-skinned.h" 55#include "statusbar-skinned.h"
58#include "debug.h" 56#include "debug.h"
57#include "viewport.h"
59 58
60 59#define VPSTACK_DEPTH 16
61static int statusbar_enabled = 0; 60struct viewport_stack_item
62 61{
63#ifdef HAVE_LCD_BITMAP
64static struct {
65 struct viewport* vp; 62 struct viewport* vp;
66 int active[NB_SCREENS]; 63 bool enabled;
67} ui_vp_info; 64};
68 65
69static struct viewport custom_vp[NB_SCREENS]; 66#ifdef HAVE_LCD_BITMAP
70
71/* callbacks for GUI_EVENT_* events */
72static void viewportmanager_ui_vp_changed(void *param);
73static void viewportmanager_call_draw_func(void *param);
74static void statusbar_toggled(void* param);
75static unsigned viewport_init_ui_vp(void);
76#endif
77static void viewportmanager_redraw(void* data); 67static void viewportmanager_redraw(void* data);
68
69static int theme_stack_top[NB_SCREENS]; /* the last item added */
70static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH];
71static bool is_theme_enabled(enum screen_type screen);
78 72
79int viewport_get_nb_lines(const struct viewport *vp) 73static void toggle_theme(void)
80{ 74{
81#ifdef HAVE_LCD_BITMAP 75 bool enable_event = false;
82 return vp->height/font_get(vp->font)->height; 76 static bool was_enabled[NB_SCREENS] = {false};
83#else 77 int i;
84 (void)vp; 78 FOR_NB_SCREENS(i)
85 return 2; 79 {
80 enable_event = enable_event || is_theme_enabled(i);
81 }
82 if (enable_event)
83 {
84 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
85#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
86 add_event(LCD_EVENT_ACTIVATION, false, do_sbs_update_callback);
86#endif 87#endif
87} 88 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false,
88 89 do_sbs_update_callback);
89static bool showing_bars(enum screen_type screen) 90 add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false,
90{ 91 do_sbs_update_callback);
91 if (statusbar_enabled & VP_SB_ONSCREEN(screen)) 92
93 /* remove the left overs from the previous screen.
94 * could cause a tiny flicker. Redo your screen code if that happens */
95 FOR_NB_SCREENS(i)
96 {
97 if (!was_enabled[i])
98 {
99 struct viewport deadspace, user;
100 viewport_set_defaults(&user, i);
101 deadspace = user; /* get colours and everything */
102 /* above */
103 deadspace.x = 0;
104 deadspace.y = 0;
105 deadspace.width = screens[i].lcdwidth;
106 deadspace.height = user.y;
107 if (deadspace.width && deadspace.height)
108 {
109 screens[i].set_viewport(&deadspace);
110 screens[i].clear_viewport();
111 screens[i].update_viewport();
112 }
113 /* below */
114 deadspace.y = user.y + user.height;
115 deadspace.height = screens[i].lcdheight - deadspace.y;
116 if (deadspace.width && deadspace.height)
117 {
118 screens[i].set_viewport(&deadspace);
119 screens[i].clear_viewport();
120 screens[i].update_viewport();
121 }
122 /* left */
123 deadspace.x = 0;
124 deadspace.y = 0;
125 deadspace.width = user.x;
126 deadspace.height = screens[i].lcdheight;
127 if (deadspace.width && deadspace.height)
128 {
129 screens[i].set_viewport(&deadspace);
130 screens[i].clear_viewport();
131 screens[i].update_viewport();
132 }
133 /* below */
134 deadspace.x = user.x + user.width;
135 deadspace.width = screens[i].lcdwidth - deadspace.x;
136 if (deadspace.width && deadspace.height)
137 {
138 screens[i].set_viewport(&deadspace);
139 screens[i].clear_viewport();
140 screens[i].update_viewport();
141 }
142 }
143 }
144 send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); /* force a redraw */
145 }
146 else
92 { 147 {
93#ifdef HAVE_LCD_BITMAP 148 FOR_NB_SCREENS(i)
94 int ignore; 149 screens[i].stop_scroll();
95 ignore = statusbar_enabled & VP_SB_IGNORE_SETTING(screen); 150#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
96 return ignore || (statusbar_position(screen) != STATUSBAR_OFF); 151 remove_event(LCD_EVENT_ACTIVATION, do_sbs_update_callback);
97#else
98 return true;
99#endif 152#endif
153 remove_event(PLAYBACK_EVENT_TRACK_CHANGE, do_sbs_update_callback);
154 remove_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, do_sbs_update_callback);
155 remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
100 } 156 }
101 return false; 157
158 FOR_NB_SCREENS(i)
159 was_enabled[i] = is_theme_enabled(i);
102} 160}
103 161
104 162void viewportmanager_theme_enable(enum screen_type screen, bool enable,
105void viewportmanager_init(void) 163 struct viewport *viewport)
106{ 164{
107#ifdef HAVE_LCD_BITMAP 165 int top = ++theme_stack_top[screen];
108 add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, statusbar_toggled); 166 if (top >= VPSTACK_DEPTH-1)
109#endif 167 panicf("Stack overflow... viewportmanager");
110 viewportmanager_set_statusbar(VP_SB_ALLSCREENS); 168 theme_stack[screen][top].enabled = enable;
169 theme_stack[screen][top].vp = viewport;
170 toggle_theme();
171 /* then be nice and set the viewport up */
172 if (viewport)
173 viewport_set_defaults(viewport, screen);
111} 174}
112 175
113int viewportmanager_get_statusbar(void) 176void viewportmanager_theme_undo(enum screen_type screen)
114{ 177{
115 return statusbar_enabled; 178 int top = --theme_stack_top[screen];
179 if (top < 0)
180 panicf("Stack underflow... viewportmanager");
181
182 toggle_theme();
116} 183}
117 184
118int viewportmanager_set_statusbar(const int enabled) 185
186static bool is_theme_enabled(enum screen_type screen)
119{ 187{
120 int old = statusbar_enabled; 188 int top = theme_stack_top[screen];
121 int i; 189 return theme_stack[screen][top].enabled;
122 190}
123 statusbar_enabled = enabled;
124 191
125 FOR_NB_SCREENS(i) 192static bool custom_vp_loaded_ok[NB_SCREENS];
126 { 193static struct viewport custom_vp[NB_SCREENS];
127 if (showing_bars(i)
128 && statusbar_position(i) != STATUSBAR_CUSTOM)
129 {
130 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
131 gui_statusbar_draw(&statusbars.statusbars[i], true);
132 }
133 else
134 remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
135 }
136 194
195static unsigned viewport_init_ui_vp(void);
196#endif /* HAVE_LCD_BITMAP */
197
198int viewport_get_nb_lines(const struct viewport *vp)
199{
137#ifdef HAVE_LCD_BITMAP 200#ifdef HAVE_LCD_BITMAP
138 FOR_NB_SCREENS(i) 201 return vp->height/font_get(vp->font)->height;
139 { 202#else
140 sb_skin_set_state(showing_bars(i) 203 (void)vp;
141 && statusbar_position(i) == STATUSBAR_CUSTOM, i); 204 return 2;
142 }
143#endif 205#endif
144 return old;
145} 206}
146 207
147static void viewportmanager_redraw(void* data) 208static void viewportmanager_redraw(void* data)
148{ 209{
149 int i; 210 int i;
150
151 FOR_NB_SCREENS(i) 211 FOR_NB_SCREENS(i)
152 { 212 {
153 if (showing_bars(i) 213#ifdef HAVE_LCD_BITMAP
154 && statusbar_position(i) != STATUSBAR_CUSTOM) 214 if (statusbar_position(i) == STATUSBAR_CUSTOM)
215 sb_skin_update(i, NULL != data);
216 else if (statusbar_position(i) != STATUSBAR_OFF)
217#endif
155 gui_statusbar_draw(&statusbars.statusbars[i], NULL != data); 218 gui_statusbar_draw(&statusbars.statusbars[i], NULL != data);
156 } 219 }
157} 220}
158#ifdef HAVE_LCD_BITMAP
159 221
160static void statusbar_toggled(void* param) 222void viewportmanager_init()
161{ 223{
162 (void)param; 224#ifdef HAVE_LCD_BITMAP
163 /* update vp manager for the new setting and reposition vps 225 int i;
164 * if necessary */ 226 FOR_NB_SCREENS(i)
165 viewportmanager_theme_changed(THEME_STATUSBAR); 227 {
228 theme_stack_top[i] = -1; /* the next call fixes this to 0 */
229 /* We always want the theme enabled by default... */
230 viewportmanager_theme_enable(i, true, NULL);
231 }
232#else
233 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
234#endif
166} 235}
167 236
237#ifdef HAVE_LCD_BITMAP
168void viewportmanager_theme_changed(const int which) 238void viewportmanager_theme_changed(const int which)
169{ 239{
170 int i; 240 int i;
@@ -177,91 +247,25 @@ void viewportmanager_theme_changed(const int which)
177#endif 247#endif
178 if (which & THEME_UI_VIEWPORT) 248 if (which & THEME_UI_VIEWPORT)
179 { 249 {
180 int retval = viewport_init_ui_vp(); 250 viewport_init_ui_vp();
181 /* reset the ui viewport */
182 FOR_NB_SCREENS(i)
183 ui_vp_info.active[i] = retval & BIT_N(i);
184 /* and point to it */
185 ui_vp_info.vp = custom_vp;
186 } 251 }
187 else if (which & THEME_LANGUAGE) 252 if (which & THEME_LANGUAGE)
188 { /* THEME_UI_VIEWPORT handles rtl already */ 253 {
189 FOR_NB_SCREENS(i)
190 set_default_align_flags(&custom_vp[i]);
191 } 254 }
192 if (which & THEME_STATUSBAR) 255 if (which & THEME_STATUSBAR)
193 { 256 {
194 statusbar_enabled = 0;
195 FOR_NB_SCREENS(i) 257 FOR_NB_SCREENS(i)
196 { 258 {
197 if (statusbar_position(i) != STATUSBAR_OFF) 259 /* This can probably be done better...
198 statusbar_enabled |= VP_SB_ONSCREEN(i); 260 * disable the theme so it's forced to do a full redraw */
261 viewportmanager_theme_enable(i, false, NULL);
262 viewportmanager_theme_undo(i);
199 } 263 }
200
201 viewportmanager_set_statusbar(statusbar_enabled);
202
203 /* reposition viewport to fit statusbar, only if not using the ui vp */
204
205 FOR_NB_SCREENS(i)
206 {
207 if (!ui_vp_info.active[i])
208 viewport_set_fullscreen(&custom_vp[i], i);
209 }
210 }
211
212 int event_add = 0;
213 FOR_NB_SCREENS(i)
214 {
215 event_add |= ui_vp_info.active[i];
216 event_add |= (statusbar_position(i) == STATUSBAR_CUSTOM);
217 }
218
219 /* add one of those to ensure the draw function is called always */
220 if (event_add)
221 {
222 add_event(GUI_EVENT_REFRESH, false, viewportmanager_ui_vp_changed);
223 remove_event(GUI_EVENT_REFRESH, viewportmanager_call_draw_func);
224 }
225 else
226 {
227 add_event(GUI_EVENT_REFRESH, false, viewportmanager_call_draw_func);
228 remove_event(GUI_EVENT_REFRESH, viewportmanager_ui_vp_changed);
229 } 264 }
230
231 send_event(GUI_EVENT_THEME_CHANGED, NULL); 265 send_event(GUI_EVENT_THEME_CHANGED, NULL);
232} 266}
233 267
234/* 268/*
235 * simply calls a function that draws stuff, this exists to ensure the
236 * drawing function call in the GUI_EVENT_REFRESH event
237 *
238 * param should be 'void func(void)' */
239static void viewportmanager_call_draw_func(void *param)
240{
241 /* cast param to a function */
242 void (*draw_func)(void) = ((void(*)(void))param);
243 /* call the passed function which will redraw the content of
244 * the current screen */
245 if (draw_func != NULL)
246 draw_func();
247}
248
249static void viewportmanager_ui_vp_changed(void *param)
250{
251 /* if the user changed the theme, we need to initiate a full redraw */
252 int i;
253 /* start with clearing the screen */
254 FOR_NB_SCREENS(i)
255 screens[i].clear_display();
256 /* redraw the statusbar if it was enabled */
257 send_event(GUI_EVENT_ACTIONUPDATE, (void*)true);
258 /* call redraw function */
259 viewportmanager_call_draw_func(param);
260 FOR_NB_SCREENS(i)
261 screens[i].update();
262}
263
264/*
265 * (re)parse the UI vp from the settings 269 * (re)parse the UI vp from the settings
266 * - Returns 270 * - Returns
267 * 0 if no UI vp is used at all 271 * 0 if no UI vp is used at all
@@ -270,7 +274,7 @@ static void viewportmanager_ui_vp_changed(void *param)
270static unsigned viewport_init_ui_vp(void) 274static unsigned viewport_init_ui_vp(void)
271{ 275{
272 int screen; 276 int screen;
273 unsigned ret = 0; 277 const char *ret = NULL;
274 char *setting; 278 char *setting;
275 FOR_NB_SCREENS(screen) 279 FOR_NB_SCREENS(screen)
276 { 280 {
@@ -280,15 +284,13 @@ static unsigned viewport_init_ui_vp(void)
280 else 284 else
281#endif 285#endif
282 setting = global_settings.ui_vp_config; 286 setting = global_settings.ui_vp_config;
283
284 287
285 if (!(viewport_parse_viewport(&custom_vp[screen], screen, 288 ret = viewport_parse_viewport(&custom_vp[screen], screen,
286 setting, ','))) 289 setting, ',');
287 viewport_set_fullscreen(&custom_vp[screen], screen); 290
288 else 291 custom_vp_loaded_ok[screen] = ret?true:false;
289 ret |= BIT_N(screen);
290 } 292 }
291 return ret; 293 return true; /* meh fixme */
292} 294}
293 295
294#ifdef HAVE_TOUCHSCREEN 296#ifdef HAVE_TOUCHSCREEN
@@ -301,6 +303,16 @@ bool viewport_point_within_vp(const struct viewport *vp,
301 return (is_x && is_y); 303 return (is_x && is_y);
302} 304}
303#endif /* HAVE_TOUCHSCREEN */ 305#endif /* HAVE_TOUCHSCREEN */
306
307static void set_default_align_flags(struct viewport *vp)
308{
309 vp->flags &= ~VP_FLAG_ALIGNMENT_MASK;
310#ifndef __PCTOOL__
311 if (UNLIKELY(lang_is_rtl()))
312 vp->flags |= VP_FLAG_ALIGN_RIGHT;
313#endif
314}
315
304#endif /* HAVE_LCD_BITMAP */ 316#endif /* HAVE_LCD_BITMAP */
305#endif /* __PCTOOL__ */ 317#endif /* __PCTOOL__ */
306 318
@@ -363,11 +375,17 @@ void viewport_set_defaults(struct viewport *vp,
363#if defined(HAVE_LCD_BITMAP) && !defined(__PCTOOL__) 375#if defined(HAVE_LCD_BITMAP) && !defined(__PCTOOL__)
364 376
365 struct viewport *sbs_area = NULL, *user_setting = NULL; 377 struct viewport *sbs_area = NULL, *user_setting = NULL;
378 if (!is_theme_enabled(screen))
379 {
380 viewport_set_fullscreen(vp, screen);
381 return;
382 }
366 /* get the two viewports */ 383 /* get the two viewports */
367 if (ui_vp_info.active[screen]) 384 if (custom_vp_loaded_ok[screen])
368 user_setting = &ui_vp_info.vp[screen]; 385 user_setting = &custom_vp[screen];
369 if (sb_skin_get_state(screen)) 386 if (sb_skin_get_state(screen))
370 sbs_area = sb_skin_get_info_vp(screen); 387 sbs_area = sb_skin_get_info_vp(screen);
388
371 /* have both? get their intersection */ 389 /* have both? get their intersection */
372 if (sbs_area && user_setting) 390 if (sbs_area && user_setting)
373 { 391 {
@@ -380,6 +398,7 @@ void viewport_set_defaults(struct viewport *vp,
380 { 398 {
381 /* copy from ui vp first (for other field),fix coordinates after */ 399 /* copy from ui vp first (for other field),fix coordinates after */
382 *vp = *user_setting; 400 *vp = *user_setting;
401 set_default_align_flags(vp);
383 vp->x = MAX(a->x, b->x); 402 vp->x = MAX(a->x, b->x);
384 vp->y = MAX(a->y, b->y); 403 vp->y = MAX(a->y, b->y);
385 vp->width = MIN(a->x + a->width, b->x + b->width) - vp->x; 404 vp->width = MIN(a->x + a->width, b->x + b->width) - vp->x;
@@ -405,16 +424,6 @@ void viewport_set_defaults(struct viewport *vp,
405 424
406 425
407#ifdef HAVE_LCD_BITMAP 426#ifdef HAVE_LCD_BITMAP
408
409static void set_default_align_flags(struct viewport *vp)
410{
411 vp->flags &= ~VP_FLAG_ALIGNMENT_MASK;
412#ifndef __PCTOOL__
413 if (UNLIKELY(lang_is_rtl()))
414 vp->flags |= VP_FLAG_ALIGN_RIGHT;
415#endif
416}
417
418const char* viewport_parse_viewport(struct viewport *vp, 427const char* viewport_parse_viewport(struct viewport *vp,
419 enum screen_type screen, 428 enum screen_type screen,
420 const char *bufptr, 429 const char *bufptr,