summaryrefslogtreecommitdiff
path: root/apps/gui/viewport.c
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2009-12-09 07:25:46 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2009-12-09 07:25:46 +0000
commitb2eb44ce0eb24632a46b0ea8c8c46a8f2ba35e24 (patch)
treeff3c0e14e9a53c08749ee1f233a5b1e887d3561a /apps/gui/viewport.c
parent85aad9b3972208b0e34ba0241ebb5314118ae05e (diff)
FS#10824 - viewport/statusbar API rework.
Hopefully the only user visible changes are: - fm and recording screens go by the statusbar setting (sbs or inbuilt) - plugins go back to using the theme as they should for menus and lists - splash screens might get cut a bit... entirely theme and splash dependant.. if there is a problematic one we can look at it later. - hopefully nothing more than very minor screen flickerings... let me know exactly where they are so they can be fixed New GUI screen rules: * Screens assume that the theme (sbs+ui viewport+ maybe background image) are always enabled. They may be disabled on a per display basis, but MUST be re-enabled on exit * Screens must not be coded in a way that requires a statusbar of any type.. the inbuilt bar will be removed shortly. ALWAYS RESPECT THE USERS SETTINGS unless the screen requires the full display to fit. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23904 a1c6a512-1295-4272-9138-f99709370657
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 @@
#include "screen_access.h"
#include "settings.h"
#include "misc.h"
+#include "panic.h"
+#include "viewport.h"
/*some short cuts for fg/bg/line selector handling */
#ifdef HAVE_LCD_COLOR
@@ -38,10 +40,6 @@
#define BG_FALLBACK LCD_DEFAULT_BG
#endif
-#ifdef HAVE_LCD_BITMAP
-static void set_default_align_flags(struct viewport *vp);
-#endif
-
/* all below isn't needed for pc tools (i.e. checkwps/wps editor)
* only viewport_parse_viewport() is */
#ifndef __PCTOOL__
@@ -56,115 +54,187 @@ static void set_default_align_flags(struct viewport *vp);
#endif
#include "statusbar-skinned.h"
#include "debug.h"
+#include "viewport.h"
-
-static int statusbar_enabled = 0;
-
-#ifdef HAVE_LCD_BITMAP
-static struct {
+#define VPSTACK_DEPTH 16
+struct viewport_stack_item
+{
struct viewport* vp;
- int active[NB_SCREENS];
-} ui_vp_info;
+ bool enabled;
+};
-static struct viewport custom_vp[NB_SCREENS];
-
-/* callbacks for GUI_EVENT_* events */
-static void viewportmanager_ui_vp_changed(void *param);
-static void viewportmanager_call_draw_func(void *param);
-static void statusbar_toggled(void* param);
-static unsigned viewport_init_ui_vp(void);
-#endif
+#ifdef HAVE_LCD_BITMAP
static void viewportmanager_redraw(void* data);
+
+static int theme_stack_top[NB_SCREENS]; /* the last item added */
+static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH];
+static bool is_theme_enabled(enum screen_type screen);
-int viewport_get_nb_lines(const struct viewport *vp)
+static void toggle_theme(void)
{
-#ifdef HAVE_LCD_BITMAP
- return vp->height/font_get(vp->font)->height;
-#else
- (void)vp;
- return 2;
+ bool enable_event = false;
+ static bool was_enabled[NB_SCREENS] = {false};
+ int i;
+ FOR_NB_SCREENS(i)
+ {
+ enable_event = enable_event || is_theme_enabled(i);
+ }
+ if (enable_event)
+ {
+ add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
+#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
+ add_event(LCD_EVENT_ACTIVATION, false, do_sbs_update_callback);
#endif
-}
-
-static bool showing_bars(enum screen_type screen)
-{
- if (statusbar_enabled & VP_SB_ONSCREEN(screen))
+ add_event(PLAYBACK_EVENT_TRACK_CHANGE, false,
+ do_sbs_update_callback);
+ add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false,
+ do_sbs_update_callback);
+
+ /* remove the left overs from the previous screen.
+ * could cause a tiny flicker. Redo your screen code if that happens */
+ FOR_NB_SCREENS(i)
+ {
+ if (!was_enabled[i])
+ {
+ struct viewport deadspace, user;
+ viewport_set_defaults(&user, i);
+ deadspace = user; /* get colours and everything */
+ /* above */
+ deadspace.x = 0;
+ deadspace.y = 0;
+ deadspace.width = screens[i].lcdwidth;
+ deadspace.height = user.y;
+ if (deadspace.width && deadspace.height)
+ {
+ screens[i].set_viewport(&deadspace);
+ screens[i].clear_viewport();
+ screens[i].update_viewport();
+ }
+ /* below */
+ deadspace.y = user.y + user.height;
+ deadspace.height = screens[i].lcdheight - deadspace.y;
+ if (deadspace.width && deadspace.height)
+ {
+ screens[i].set_viewport(&deadspace);
+ screens[i].clear_viewport();
+ screens[i].update_viewport();
+ }
+ /* left */
+ deadspace.x = 0;
+ deadspace.y = 0;
+ deadspace.width = user.x;
+ deadspace.height = screens[i].lcdheight;
+ if (deadspace.width && deadspace.height)
+ {
+ screens[i].set_viewport(&deadspace);
+ screens[i].clear_viewport();
+ screens[i].update_viewport();
+ }
+ /* below */
+ deadspace.x = user.x + user.width;
+ deadspace.width = screens[i].lcdwidth - deadspace.x;
+ if (deadspace.width && deadspace.height)
+ {
+ screens[i].set_viewport(&deadspace);
+ screens[i].clear_viewport();
+ screens[i].update_viewport();
+ }
+ }
+ }
+ send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); /* force a redraw */
+ }
+ else
{
-#ifdef HAVE_LCD_BITMAP
- int ignore;
- ignore = statusbar_enabled & VP_SB_IGNORE_SETTING(screen);
- return ignore || (statusbar_position(screen) != STATUSBAR_OFF);
-#else
- return true;
+ FOR_NB_SCREENS(i)
+ screens[i].stop_scroll();
+#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
+ remove_event(LCD_EVENT_ACTIVATION, do_sbs_update_callback);
#endif
+ remove_event(PLAYBACK_EVENT_TRACK_CHANGE, do_sbs_update_callback);
+ remove_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, do_sbs_update_callback);
+ remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
}
- return false;
+
+ FOR_NB_SCREENS(i)
+ was_enabled[i] = is_theme_enabled(i);
}
-
-void viewportmanager_init(void)
+void viewportmanager_theme_enable(enum screen_type screen, bool enable,
+ struct viewport *viewport)
{
-#ifdef HAVE_LCD_BITMAP
- add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, statusbar_toggled);
-#endif
- viewportmanager_set_statusbar(VP_SB_ALLSCREENS);
+ int top = ++theme_stack_top[screen];
+ if (top >= VPSTACK_DEPTH-1)
+ panicf("Stack overflow... viewportmanager");
+ theme_stack[screen][top].enabled = enable;
+ theme_stack[screen][top].vp = viewport;
+ toggle_theme();
+ /* then be nice and set the viewport up */
+ if (viewport)
+ viewport_set_defaults(viewport, screen);
}
-int viewportmanager_get_statusbar(void)
+void viewportmanager_theme_undo(enum screen_type screen)
{
- return statusbar_enabled;
+ int top = --theme_stack_top[screen];
+ if (top < 0)
+ panicf("Stack underflow... viewportmanager");
+
+ toggle_theme();
}
-int viewportmanager_set_statusbar(const int enabled)
+
+static bool is_theme_enabled(enum screen_type screen)
{
- int old = statusbar_enabled;
- int i;
-
- statusbar_enabled = enabled;
+ int top = theme_stack_top[screen];
+ return theme_stack[screen][top].enabled;
+}
- FOR_NB_SCREENS(i)
- {
- if (showing_bars(i)
- && statusbar_position(i) != STATUSBAR_CUSTOM)
- {
- add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
- gui_statusbar_draw(&statusbars.statusbars[i], true);
- }
- else
- remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
- }
+static bool custom_vp_loaded_ok[NB_SCREENS];
+static struct viewport custom_vp[NB_SCREENS];
+static unsigned viewport_init_ui_vp(void);
+#endif /* HAVE_LCD_BITMAP */
+
+int viewport_get_nb_lines(const struct viewport *vp)
+{
#ifdef HAVE_LCD_BITMAP
- FOR_NB_SCREENS(i)
- {
- sb_skin_set_state(showing_bars(i)
- && statusbar_position(i) == STATUSBAR_CUSTOM, i);
- }
+ return vp->height/font_get(vp->font)->height;
+#else
+ (void)vp;
+ return 2;
#endif
- return old;
}
static void viewportmanager_redraw(void* data)
{
int i;
-
FOR_NB_SCREENS(i)
{
- if (showing_bars(i)
- && statusbar_position(i) != STATUSBAR_CUSTOM)
+#ifdef HAVE_LCD_BITMAP
+ if (statusbar_position(i) == STATUSBAR_CUSTOM)
+ sb_skin_update(i, NULL != data);
+ else if (statusbar_position(i) != STATUSBAR_OFF)
+#endif
gui_statusbar_draw(&statusbars.statusbars[i], NULL != data);
}
}
-#ifdef HAVE_LCD_BITMAP
-static void statusbar_toggled(void* param)
+void viewportmanager_init()
{
- (void)param;
- /* update vp manager for the new setting and reposition vps
- * if necessary */
- viewportmanager_theme_changed(THEME_STATUSBAR);
+#ifdef HAVE_LCD_BITMAP
+ int i;
+ FOR_NB_SCREENS(i)
+ {
+ theme_stack_top[i] = -1; /* the next call fixes this to 0 */
+ /* We always want the theme enabled by default... */
+ viewportmanager_theme_enable(i, true, NULL);
+ }
+#else
+ add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
+#endif
}
+#ifdef HAVE_LCD_BITMAP
void viewportmanager_theme_changed(const int which)
{
int i;
@@ -177,91 +247,25 @@ void viewportmanager_theme_changed(const int which)
#endif
if (which & THEME_UI_VIEWPORT)
{
- int retval = viewport_init_ui_vp();
- /* reset the ui viewport */
- FOR_NB_SCREENS(i)
- ui_vp_info.active[i] = retval & BIT_N(i);
- /* and point to it */
- ui_vp_info.vp = custom_vp;
+ viewport_init_ui_vp();
}
- else if (which & THEME_LANGUAGE)
- { /* THEME_UI_VIEWPORT handles rtl already */
- FOR_NB_SCREENS(i)
- set_default_align_flags(&custom_vp[i]);
+ if (which & THEME_LANGUAGE)
+ {
}
if (which & THEME_STATUSBAR)
{
- statusbar_enabled = 0;
FOR_NB_SCREENS(i)
{
- if (statusbar_position(i) != STATUSBAR_OFF)
- statusbar_enabled |= VP_SB_ONSCREEN(i);
+ /* This can probably be done better...
+ * disable the theme so it's forced to do a full redraw */
+ viewportmanager_theme_enable(i, false, NULL);
+ viewportmanager_theme_undo(i);
}
-
- viewportmanager_set_statusbar(statusbar_enabled);
-
- /* reposition viewport to fit statusbar, only if not using the ui vp */
-
- FOR_NB_SCREENS(i)
- {
- if (!ui_vp_info.active[i])
- viewport_set_fullscreen(&custom_vp[i], i);
- }
- }
-
- int event_add = 0;
- FOR_NB_SCREENS(i)
- {
- event_add |= ui_vp_info.active[i];
- event_add |= (statusbar_position(i) == STATUSBAR_CUSTOM);
- }
-
- /* add one of those to ensure the draw function is called always */
- if (event_add)
- {
- add_event(GUI_EVENT_REFRESH, false, viewportmanager_ui_vp_changed);
- remove_event(GUI_EVENT_REFRESH, viewportmanager_call_draw_func);
- }
- else
- {
- add_event(GUI_EVENT_REFRESH, false, viewportmanager_call_draw_func);
- remove_event(GUI_EVENT_REFRESH, viewportmanager_ui_vp_changed);
}
-
send_event(GUI_EVENT_THEME_CHANGED, NULL);
}
/*
- * simply calls a function that draws stuff, this exists to ensure the
- * drawing function call in the GUI_EVENT_REFRESH event
- *
- * param should be 'void func(void)' */
-static void viewportmanager_call_draw_func(void *param)
-{
- /* cast param to a function */
- void (*draw_func)(void) = ((void(*)(void))param);
- /* call the passed function which will redraw the content of
- * the current screen */
- if (draw_func != NULL)
- draw_func();
-}
-
-static void viewportmanager_ui_vp_changed(void *param)
-{
- /* if the user changed the theme, we need to initiate a full redraw */
- int i;
- /* start with clearing the screen */
- FOR_NB_SCREENS(i)
- screens[i].clear_display();
- /* redraw the statusbar if it was enabled */
- send_event(GUI_EVENT_ACTIONUPDATE, (void*)true);
- /* call redraw function */
- viewportmanager_call_draw_func(param);
- FOR_NB_SCREENS(i)
- screens[i].update();
-}
-
-/*
* (re)parse the UI vp from the settings
* - Returns
* 0 if no UI vp is used at all
@@ -270,7 +274,7 @@ static void viewportmanager_ui_vp_changed(void *param)
static unsigned viewport_init_ui_vp(void)
{
int screen;
- unsigned ret = 0;
+ const char *ret = NULL;
char *setting;
FOR_NB_SCREENS(screen)
{
@@ -280,15 +284,13 @@ static unsigned viewport_init_ui_vp(void)
else
#endif
setting = global_settings.ui_vp_config;
-
- if (!(viewport_parse_viewport(&custom_vp[screen], screen,
- setting, ',')))
- viewport_set_fullscreen(&custom_vp[screen], screen);
- else
- ret |= BIT_N(screen);
+ ret = viewport_parse_viewport(&custom_vp[screen], screen,
+ setting, ',');
+
+ custom_vp_loaded_ok[screen] = ret?true:false;
}
- return ret;
+ return true; /* meh fixme */
}
#ifdef HAVE_TOUCHSCREEN
@@ -301,6 +303,16 @@ bool viewport_point_within_vp(const struct viewport *vp,
return (is_x && is_y);
}
#endif /* HAVE_TOUCHSCREEN */
+
+static void set_default_align_flags(struct viewport *vp)
+{
+ vp->flags &= ~VP_FLAG_ALIGNMENT_MASK;
+#ifndef __PCTOOL__
+ if (UNLIKELY(lang_is_rtl()))
+ vp->flags |= VP_FLAG_ALIGN_RIGHT;
+#endif
+}
+
#endif /* HAVE_LCD_BITMAP */
#endif /* __PCTOOL__ */
@@ -363,11 +375,17 @@ void viewport_set_defaults(struct viewport *vp,
#if defined(HAVE_LCD_BITMAP) && !defined(__PCTOOL__)
struct viewport *sbs_area = NULL, *user_setting = NULL;
+ if (!is_theme_enabled(screen))
+ {
+ viewport_set_fullscreen(vp, screen);
+ return;
+ }
/* get the two viewports */
- if (ui_vp_info.active[screen])
- user_setting = &ui_vp_info.vp[screen];
+ if (custom_vp_loaded_ok[screen])
+ user_setting = &custom_vp[screen];
if (sb_skin_get_state(screen))
sbs_area = sb_skin_get_info_vp(screen);
+
/* have both? get their intersection */
if (sbs_area && user_setting)
{
@@ -380,6 +398,7 @@ void viewport_set_defaults(struct viewport *vp,
{
/* copy from ui vp first (for other field),fix coordinates after */
*vp = *user_setting;
+ set_default_align_flags(vp);
vp->x = MAX(a->x, b->x);
vp->y = MAX(a->y, b->y);
vp->width = MIN(a->x + a->width, b->x + b->width) - vp->x;
@@ -405,16 +424,6 @@ void viewport_set_defaults(struct viewport *vp,
#ifdef HAVE_LCD_BITMAP
-
-static void set_default_align_flags(struct viewport *vp)
-{
- vp->flags &= ~VP_FLAG_ALIGNMENT_MASK;
-#ifndef __PCTOOL__
- if (UNLIKELY(lang_is_rtl()))
- vp->flags |= VP_FLAG_ALIGN_RIGHT;
-#endif
-}
-
const char* viewport_parse_viewport(struct viewport *vp,
enum screen_type screen,
const char *bufptr,