flyspray is down and I'm ready for bed... this version builds without
warnings on bitmap lcd...

This patch (imo) simplifies the statusbar and viewportmanager API's.
magically fixes a bunch of the current statusbar redraw issues, and
removes some GUI events which would be better if they wern't
required... This also removes the notion of a inbuilt statusbar..
either its enabled or its not (top/bottom/custom all still work),
which means that some screens which used to force the bar cant do this
anymore... I think the only big "issues" here is recording screen
(semi skinnable, so maybe not such a issue) and early chargin/usb
screens which can be sorted out separately.

please test it out and let me know how it goes...
Jonathan

2009/11/30 Jonathan Gordon <jdgo...@gmail.com>:
> small update.. closer to being reviewable.... WPS doesnt work as
> expected, rec screen and lists do, plugins almost working...
>
> 2009/11/25 Jonathan Gordon <jdgo...@gmail.com>:
>> more brain dump...
>> end of last week it was agreed on that really the only place where
>> having a "statusbar" is absolutly required is *early* usb and charging
>> (early being almost never seen by users because its handled in the
>> bootloader...)
>> So, the better solution than trying to hardcode a fallback sbs (like
>> the fallback wps) is to fix those screens with some pretty
>> aniumations, or actually lay the info out on the screen better (TBD).
>>
>> What this means (along with the api rework) is that the only screens
>> that would ever need to enable/disable the theme are ones which
>> actually only disable the theme, all others would just assume that the
>> theme is active. This means a fair bit of simplification (specifically
>> the fm and rec screens).
>>
>> We could allow some screens to force toggle the theme (e.g do_menu() )
>> but I'm leaning more to making it required of the calling code to
>> re-enable the theme before calling do_menu() which means we can get
>> rid of some logic there which currently handles showing the bars.
>>
>> The big annoyance will be for plugins here.. so we could fix a
>> do_menu() wrapper for them to undo the theme, call do_menu(), then
>> redo the theme change... not sure if thats a good idea though.
>> In the core, I cant think of too many screens which would ever need to
>> disable the theme... (Actually, only the quick/pitch screens, and the
>> graphic EQ changer screen come to mind...)
>>
>> Jonathan
>>
>> 2009/11/24 Jonathan Gordon <jdgo...@gmail.com>:
>>> Attached is my very quick first effort of doing this change in svn...
>>> it doesnt work, and doesnt even compile yet.. yet enough has changed
>>> so you get some idea of how it simplifies the API a bit (not much
>>> though, but some...)
>>>
>>> It turns out that we probably cant completely hide _Set_fullscreen and
>>> set_default to just viewport.c, although I'd really like to....
>>> The reason why one funciton for both (externally) works is because of this:
>>> 1) A screen knows how much room it needs... it has exactly 2 choices,
>>> a) use the theme, or b) use full screen.
>>> 2) with a single API call it can say "disable the theme, and setup the
>>> viewport for full screen" which does everything else needed in the
>>> background (i.e disabling the sbs updateing, etc)
>>> 3) if a screen calls _set_fullscreen without disabling the sbs then
>>> bad things will happen, doing it in 1 api call eliminates that
>>> problem.
>>>
>>> anyway.. have a open mind over this... we can argue in the morning :)
>>>
>>> Jonathan
>>>
>>
>
Index: apps/recorder/radio.c
===================================================================
--- apps/recorder/radio.c	(revision 23799)
+++ apps/recorder/radio.c	(working copy)
@@ -482,7 +482,6 @@
     int button_timeout = current_tick + (2*HZ);
 #endif
     struct viewport vp[NB_SCREENS];
-    int oldbars = 0, fmbars = VP_SB_ALLSCREENS;
 #ifdef HAVE_BUTTONBAR
     struct gui_buttonbar buttonbar;
     gui_buttonbar_init(&buttonbar);
@@ -494,11 +493,8 @@
 
     /* always display status bar in radio screen for now */
     FOR_NB_SCREENS(i)
-        fmbars |= VP_SB_IGNORE_SETTING(i);
-    oldbars = viewportmanager_set_statusbar(fmbars);
-    FOR_NB_SCREENS(i)
     {
-        viewport_set_defaults(&vp[i], i);
+        viewportmanager_theme_enable(i, true, &vp[i]);
 #ifdef HAVE_BUTTONBAR
         if (global_settings.buttonbar)
             vp[i].height -= BUTTONBAR_HEIGHT;
@@ -750,14 +746,16 @@
                 break;
 
             case ACTION_FM_MENU:
-                viewportmanager_set_statusbar(oldbars);
                 FOR_NB_SCREENS(i)
+				{
+					viewportmanager_theme_undo(i, &vp[i]);
                     screens[i].scroll_stop(&vp[i]);
+				}
                 radio_menu();
                 curr_preset = find_preset(curr_freq);
-                viewportmanager_set_statusbar(fmbars);
                 FOR_NB_SCREENS(i)
                 {
+					viewportmanager_theme_enable(i, true, &vp[i]);					
                     screens[i].set_viewport(&vp[i]);
                     screens[i].clear_viewport();
                     screens[i].update_viewport();
@@ -787,11 +785,12 @@
 
                     break;
                 }
-                viewportmanager_set_statusbar(oldbars);
+                FOR_NB_SCREENS(i)
+					viewportmanager_theme_undo(i, &vp[i]);
                 handle_radio_presets();
-                viewportmanager_set_statusbar(fmbars);
                 FOR_NB_SCREENS(i)
                 {
+					viewportmanager_theme_enable(i, true, &vp[i]);
                     screens[i].set_viewport(&vp[i]);
                     screens[i].stop_scroll();
                     screens[i].clear_viewport();
@@ -1085,8 +1084,10 @@
     cpu_idle_mode(false);
 #endif
     FOR_NB_SCREENS(i)
+    {
         screens[i].scroll_stop(&vp[i]);
-    viewportmanager_set_statusbar(oldbars);
+		viewportmanager_theme_undo(i, &vp[i]);
+	}
     in_screen = false;
 #if CONFIG_CODEC != SWCODEC
     return have_recorded;
Index: apps/recorder/keyboard.c
===================================================================
--- apps/recorder/keyboard.c	(revision 23799)
+++ apps/recorder/keyboard.c	(working copy)
@@ -291,10 +291,10 @@
     unsigned char morse_code = 0;
     int morse_tick = 0;
 #endif
-    int oldbars = viewportmanager_set_statusbar(VP_SB_HIDE_ALL);
     FOR_NB_SCREENS(l)
     {
         struct keyboard_parameters *pm = &param[l];
+        viewportmanager_theme_enable(l, false, NULL);
 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
         struct screen *sc = &screens[l];
 
@@ -1126,9 +1126,9 @@
 #endif /* HAVE_MORSE_INPUT && KBD_TOGGLE_INPUT */
 
     FOR_NB_SCREENS(l)
+    {
         screens[l].setfont(FONT_UI);
-    viewportmanager_set_statusbar(oldbars);
-    send_event(GUI_EVENT_REFRESH, NULL);
-
+        viewportmanager_theme_undo(l, NULL);
+	}
     return ret;
 }
Index: apps/recorder/recording.c
===================================================================
--- apps/recorder/recording.c	(revision 23799)
+++ apps/recorder/recording.c	(working copy)
@@ -1019,7 +1019,6 @@
     int peak_l, peak_r;
     int balance = 0;
 #endif
-    int oldbars, recbars = VP_SB_ALLSCREENS;
     int i;
     int pm_x[NB_SCREENS];           /* peakmeter (and trigger bar) x pos */
     int pm_y[NB_SCREENS];           /* peakmeter y pos */
@@ -1082,9 +1081,6 @@
 
     /* viewport init and calculations that only needs to be done once */
     FOR_NB_SCREENS(i)
-        recbars |= VP_SB_IGNORE_SETTING(i);
-    oldbars = viewportmanager_set_statusbar(recbars);
-    FOR_NB_SCREENS(i)
     {
         struct viewport *v;
         /* top vp, 4 lines, force sys font if total screen < 6 lines
@@ -1576,7 +1572,6 @@
                     /* led is restored at begin of loop / end of function */
                     led(false);
 #endif
-                    viewportmanager_set_statusbar(oldbars);
                     if (recording_menu(no_source))
                     {
                         done = 1;
@@ -1590,7 +1585,6 @@
                         done = -1;
                         /* the init is now done at the beginning of the loop */
                     }
-                    viewportmanager_set_statusbar(recbars);
                 }
                 break;
 
@@ -1602,7 +1596,6 @@
                     /* led is restored at begin of loop / end of function */
                     led(false);
 #endif
-                    viewportmanager_set_statusbar(oldbars);
                     if (f2_rec_screen())
                     {
                         rec_status |= RCSTAT_HAVE_RECORDED;
@@ -1610,7 +1603,6 @@
                     }
                     else
                         update_countdown = 0; /* Update immediately */
-                    viewportmanager_set_statusbar(recbars);
                 }
                 break;
 
@@ -1626,7 +1618,6 @@
                     /* led is restored at begin of loop / end of function */
                     led(false);
 #endif
-                    viewportmanager_set_statusbar(oldbars);
                     if (f3_rec_screen())
                     {
                         rec_status |= RCSTAT_HAVE_RECORDED;
@@ -1634,7 +1625,6 @@
                     }
                     else
                         update_countdown = 0; /* Update immediately */
-                    viewportmanager_set_statusbar(recbars);
                 }
                 break;
 #endif /*  CONFIG_KEYPAD == RECORDER_PAD */
@@ -1920,8 +1910,6 @@
     FOR_NB_SCREENS(i)
         screens[i].setfont(FONT_UI);
         
-    viewportmanager_set_statusbar(oldbars);
-    send_event(GUI_EVENT_REFRESH, NULL);
 
     /* if the directory was created or recording happened, make sure the
        browser is updated */
Index: apps/gui/usb_screen.c
===================================================================
--- apps/gui/usb_screen.c	(revision 23799)
+++ apps/gui/usb_screen.c	(working copy)
@@ -150,7 +150,7 @@
 
     viewport_set_defaults(parent, screen->screen_type);
     if (parent->width < logo_width || parent->height < logo_height)
-        viewport_set_fullscreen(parent, screen->screen_type);
+        viewportmanager_theme_enable(screen->screen_type, false, parent);
 
     *logo = *parent;
     logo->x = parent->x + parent->width - logo_width;
@@ -180,8 +180,6 @@
 static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar)
 {
     int i;
-    int usb_bars = VP_SB_ALLSCREENS; /* force statusbars */
-
     lcd_clear_display();
 #ifdef HAVE_LCD_REMOTE
     lcd_remote_clear_display();
@@ -236,18 +234,12 @@
 
         screen->update_viewport();
         screen->set_viewport(NULL);
-
-        /* force statusbar by ignoring the setting */
-        usb_bars |= VP_SB_IGNORE_SETTING(i);
     }
-
-    viewportmanager_set_statusbar(usb_bars);
 }
 
 void gui_usb_screen_run(void)
 {
     int i;
-    int old_bars  = viewportmanager_get_statusbar();
     struct usb_screen_vps_t usb_screen_vps_ar[NB_SCREENS];
 #if defined HAVE_TOUCHSCREEN
     enum touchscreen_mode old_mode = touchscreen_get_mode();
@@ -319,9 +311,8 @@
     FOR_NB_SCREENS(i)
     {
         screens[i].backlight_on();
+        viewportmanager_theme_undo(i, NULL/* fix this */);
     }
-    viewportmanager_set_statusbar(old_bars);
-    send_event(GUI_EVENT_REFRESH, NULL);
 
 }
 #endif /* !defined(USB_NONE) */
Index: apps/gui/statusbar-skinned.c
===================================================================
--- apps/gui/statusbar-skinned.c	(revision 23799)
+++ apps/gui/statusbar-skinned.c	(working copy)
@@ -41,7 +41,7 @@
 static struct wps_sync_data sb_skin_sync_data        = { .do_full_update = false };
 
 /* initial setup of wps_data  */
-static void sb_skin_update(void*);
+
 static bool loaded_ok[NB_SCREENS] = { false };
 static int update_delay = DEFAULT_UPDATE_DELAY;
 
@@ -68,9 +68,6 @@
         vp->hidden_flags = VP_NEVER_VISIBLE;
     }
 
-    if (!success)
-        remove_event(GUI_EVENT_ACTIONUPDATE, sb_skin_update);
-
     loaded_ok[screen] = success;
 }
 
@@ -96,7 +93,6 @@
 
 inline bool sb_skin_get_state(enum screen_type screen)
 {
-    int skinbars = sb_skin[screen].sync_data->statusbars;
     /* Temp fix untill the hardcoded bar is removed */
     int bar_setting = global_settings.statusbar;
 #if NB_SCREENS > 1
@@ -106,72 +102,24 @@
     switch (bar_setting)
     {
         case STATUSBAR_CUSTOM:
-            return loaded_ok[screen] && (skinbars & VP_SB_ONSCREEN(screen));
+            return loaded_ok[screen];
         case STATUSBAR_TOP:
         case STATUSBAR_BOTTOM:
+			return true;
         case STATUSBAR_OFF:
-            return (viewportmanager_get_statusbar()&VP_SB_ONSCREEN(screen));
+            return false;
     }
     return false; /* Should never actually get here */
 }
 
-
-static void do_update_callback(void *param)
+void sb_skin_update(enum screen_type screen)
 {
-    (void)param;
-    /* the WPS handles changing the actual id3 data in the id3 pointers
-     * we imported, we just want a full update */
-    sb_skin_sync_data.do_full_update = true;
-    /* force timeout in wps main loop, so that the update is instantly */
-    queue_post(&button_queue, BUTTON_NONE, 0);
-}
-
-
-void sb_skin_set_state(int state, enum screen_type screen)
-{
-    sb_skin[screen].sync_data->do_full_update = true;
-    int skinbars = sb_skin[screen].sync_data->statusbars;
-    if (state && loaded_ok[screen])
-    {
-        skinbars |= VP_SB_ONSCREEN(screen);
-    }
-    else
-    {
-        skinbars &= ~VP_SB_ONSCREEN(screen);
-    }
-
-    if (skinbars)
-    {
-#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
-        add_event(LCD_EVENT_ACTIVATION, false, do_update_callback);
-#endif
-        add_event(PLAYBACK_EVENT_TRACK_CHANGE, false,
-                                                do_update_callback);
-        add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false,
-                                                do_update_callback);
-        add_event(GUI_EVENT_ACTIONUPDATE, false, sb_skin_update);
-    }
-    else
-    {
-#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
-        remove_event(LCD_EVENT_ACTIVATION, do_update_callback);
-#endif
-        remove_event(PLAYBACK_EVENT_TRACK_CHANGE, do_update_callback);
-        remove_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, do_update_callback);
-        remove_event(GUI_EVENT_ACTIONUPDATE, sb_skin_update);
-    }
-        
-    sb_skin[screen].sync_data->statusbars = skinbars;
-}
-
-static void sb_skin_update(void* param)
-{
     static long next_update = 0;
-    int i;
-    int forced_draw = param ||  sb_skin[SCREEN_MAIN].sync_data->do_full_update;
+    int i = screen;
+    int forced_draw = true;
     if (TIME_AFTER(current_tick, next_update) || forced_draw)
     {
-        FOR_NB_SCREENS(i)
+   //     FOR_NB_SCREENS(i)
         {
             if (sb_skin_get_state(i))
             {
@@ -209,7 +157,6 @@
         /* Currently no seperate wps_state needed/possible
            so use the only available ( "global" ) one */
         sb_skin[i].state = &wps_state;
-        sb_skin_sync_data.statusbars = VP_SB_HIDE_ALL;
         sb_skin[i].sync_data = &sb_skin_sync_data;
     }
 }
Index: apps/gui/statusbar-skinned.h
===================================================================
--- apps/gui/statusbar-skinned.h	(revision 23799)
+++ apps/gui/statusbar-skinned.h	(working copy)
@@ -35,9 +35,9 @@
 
 /* probably temporary, to shut the classic statusbar up */
 bool sb_skin_get_state(enum screen_type screen);
-void sb_skin_set_state(int state, enum screen_type screen);
 void sb_skin_init(void);
 struct viewport *sb_skin_get_info_vp(enum screen_type screen);
+void sb_skin_update(enum screen_type screen);
 
 void sb_skin_set_update_delay(int delay);
 
Index: apps/gui/skin_engine/skin_display.c
===================================================================
--- apps/gui/skin_engine/skin_display.c	(revision 23799)
+++ apps/gui/skin_engine/skin_display.c	(working copy)
@@ -1084,11 +1084,6 @@
 #ifdef HAVE_LCD_BITMAP
     data->peak_meter_enabled = enable_pm;
 #endif
-
-    if (refresh_mode & WPS_REFRESH_STATUSBAR)
-    {
-        viewportmanager_set_statusbar(gwps->sync_data->statusbars);
-    }
     /* Restore the default viewport */
     display->set_viewport(NULL);
 
Index: apps/gui/wps.c
===================================================================
--- apps/gui/wps.c	(revision 23799)
+++ apps/gui/wps.c	(working copy)
@@ -88,9 +88,6 @@
 static void wps_state_init(void);
 static void track_changed_callback(void *param);
 static void nextid3available_callback(void* param);
-#ifdef HAVE_LCD_BITMAP
-static void statusbar_toggle_handler(void *data);
-#endif
 
 #define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
 #ifdef HAVE_REMOTE_LCD
@@ -562,17 +559,15 @@
 
 static void gwps_leave_wps(void)
 {
-    int i, oldbars = VP_SB_HIDE_ALL;
+    int i;
 
     FOR_NB_SCREENS(i)
     {
         gui_wps[i].display->stop_scroll();
         gui_wps[i].display->backdrop_show(BACKDROP_MAIN);
-        if (statusbar_position(i) != STATUSBAR_OFF)
-            oldbars |= VP_SB_ONSCREEN(i);
+		viewportmanager_theme_undo(i, NULL);
     }
 
-    viewportmanager_set_statusbar(oldbars);
 #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
     /* Play safe and unregister the hook */
     remove_event(LCD_EVENT_ACTIVATION, wps_lcd_activation_hook);
@@ -591,7 +586,15 @@
     {
         struct gui_wps *gwps = &gui_wps[i];
         struct screen *display = gwps->display;
+        bool draw = false;
 
+        /* fix up gui_wps::statusbars, so that the viewportmanager accepts it*/
+        if (gui_wps[i].data->wps_sb_tag)
+            draw = gui_wps[i].data->show_sb_on_wps;
+        else if (statusbar_position(i) != STATUSBAR_OFF)
+            draw = true;
+        viewportmanager_theme_enable(i, draw, NULL);
+
         display->stop_scroll();
         /* Update the values in the first (default) viewport - in case the user
            has modified the statusbar or colour settings */
@@ -725,8 +728,6 @@
 #ifdef HAVE_LCD_CHARCELLS
     status_set_audio(true);
     status_set_param(false);
-#else
-    statusbar_toggle_handler(NULL);
 #endif
 
 #ifdef AB_REPEAT_ENABLE
@@ -734,7 +735,7 @@
     ab_reset_markers();
 #endif
     wps_state_init();
-
+    
     while ( 1 )
     {
         bool audio_paused = (audio_status() & AUDIO_STATUS_PAUSE)?true:false;
@@ -1271,33 +1272,6 @@
 }
 
 
-#ifdef HAVE_LCD_BITMAP
-static void statusbar_toggle_handler(void *data)
-{
-    (void)data;
-    int i;
-
-    int *wpsbars = &wps_sync_data.statusbars;
-    *wpsbars = VP_SB_HIDE_ALL;
-    FOR_NB_SCREENS(i)
-    {   /* fix viewports if needed */
-        skin_statusbar_changed(&gui_wps[i]);
-
-        bool draw = false;
-
-        /* fix up gui_wps::statusbars, so that the viewportmanager accepts it*/
-        if (gui_wps[i].data->wps_sb_tag)
-            draw = gui_wps[i].data->show_sb_on_wps;
-        else if (statusbar_position(i) != STATUSBAR_OFF)
-            draw = true;
-        if (draw)
-            *wpsbars |=
-                    (VP_SB_ONSCREEN(i) | VP_SB_IGNORE_SETTING(i));
-    }
-}
-#endif
-
-
 void gui_sync_wps_init(void)
 {
     int i;
@@ -1315,11 +1289,7 @@
         gui_wps[i].display->backdrop_unload(BACKDROP_SKIN_WPS);
         /* must point to the same struct for both screens */
         gui_wps[i].sync_data = &wps_sync_data;
-        gui_wps[i].sync_data->statusbars = VP_SB_ALLSCREENS;
     }
-#ifdef HAVE_LCD_BITMAP
-    add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, statusbar_toggle_handler);
-#endif
 }
 
 
Index: apps/gui/list.c
===================================================================
--- apps/gui/list.c	(revision 23799)
+++ apps/gui/list.c	(working copy)
@@ -822,14 +822,17 @@
 bool simplelist_show_list(struct simplelist_info *info)
 {
     struct gui_synclist lists;
-    int action, old_line_count = simplelist_line_count;
-    int oldbars = viewportmanager_set_statusbar(VP_SB_ALLSCREENS);
+    int action, old_line_count = simplelist_line_count, i;
     const char* (*getname)(int item, void * data, char *buffer, size_t buffer_len);
     int wrap = LIST_WRAP_UNLESS_HELD;
     if (info->get_name)
         getname = info->get_name;
     else
         getname = simplelist_static_getname;
+        
+    FOR_NB_SCREENS(i)
+		viewportmanager_theme_enable(i, true, NULL);
+		
     gui_synclist_init(&lists, getname,  info->callback_data, 
                       info->scroll_all, info->selection_size, NULL);
 
@@ -904,7 +907,8 @@
             return true;
     }
     talk_shutup();
-    viewportmanager_set_statusbar(oldbars);
+    FOR_NB_SCREENS(i)
+		viewportmanager_theme_undo(i, NULL);
     return false;
 }
 
Index: apps/gui/viewport.c
===================================================================
--- apps/gui/viewport.c	(revision 23799)
+++ apps/gui/viewport.c	(working copy)
@@ -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
@@ -56,25 +58,87 @@
 #endif
 #include "statusbar-skinned.h"
 #include "debug.h"
+#include "viewport.h"
 
+#define VPSTACK_DEPTH 16
+struct viewport_stack_item
+{
+    struct  viewport* vp;
+    bool	enabled;
+};
 
-static int statusbar_enabled = 0;
 
-#ifdef HAVE_LCD_BITMAP
-static struct {
-    struct  viewport* vp;
-    int     active[NB_SCREENS];
-} ui_vp_info;
+static void viewportmanager_redraw(void* data);
+	
+static int theme_stack_top[NB_SCREENS];
+static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH];
+static bool is_theme_enabled(enum screen_type screen);
 
+static void toggle_theme(void)
+{
+	bool enable_event = 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);
+	}
+	else
+		remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
+}
+
+void viewportmanager_theme_enable(enum screen_type screen, bool enable,
+								  struct viewport *viewport)
+{
+	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;
+	
+	
+	theme_stack_top[screen]++;
+	toggle_theme();
+	/* then be nice and set the viewport up */
+	if (viewport) /* this should only be allowed in viewport init(), or maybe not */
+		viewport_set_defaults(viewport, screen);
+}
+
+void viewportmanager_theme_undo(enum screen_type screen,
+								const struct viewport *viewport)
+{
+	int top = theme_stack_top[screen];
+	if (top < 0)
+		panicf("Stack underflow... viewportmanager");
+	if (theme_stack[screen][top].vp &&
+	    theme_stack[screen][top].vp != viewport)
+	{
+		/* this is sort of an error condition here... */
+	}
+	theme_stack_top[screen]--;
+	toggle_theme();
+}
+
+
+static bool is_theme_enabled(enum screen_type screen)
+{
+	int top = theme_stack_top[screen];
+	return theme_stack[screen][top-1].enabled;
+}
+	
+	
+#ifdef HAVE_LCD_BITMAP
+static bool custom_vp_loaded_ok[NB_SCREENS];
 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
-static void viewportmanager_redraw(void* data);
 
 int viewport_get_nb_lines(const struct viewport *vp)
 {
@@ -86,85 +150,29 @@
 #endif
 }
 
-static bool showing_bars(enum screen_type screen)
-{
-    if (statusbar_enabled & VP_SB_ONSCREEN(screen))
-    {
-#ifdef HAVE_LCD_BITMAP
-        int ignore;
-        ignore = statusbar_enabled & VP_SB_IGNORE_SETTING(screen);
-        return ignore || (statusbar_position(screen) != STATUSBAR_OFF);
-#else
-        return true;
-#endif
-    }
-    return false;
-}
-
-
 void viewportmanager_init(void)
 {
-#ifdef HAVE_LCD_BITMAP
-    add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, statusbar_toggled);
-#endif
-    viewportmanager_set_statusbar(VP_SB_ALLSCREENS);
+	int i;
+	FOR_NB_SCREENS(i)
+	{
+		theme_stack_top[i] = 0;
+		/* We always want the theme enabled by default... */
+		viewportmanager_theme_enable(i, true, NULL); 
+	}
 }
 
-int viewportmanager_get_statusbar(void)
-{
-    return statusbar_enabled;
-}
-
-int viewportmanager_set_statusbar(const int enabled)
-{
-    int old = statusbar_enabled;
-    int i;
-    
-    statusbar_enabled = 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);
-    }
-
-#ifdef HAVE_LCD_BITMAP
-    FOR_NB_SCREENS(i)
-    {
-        sb_skin_set_state(showing_bars(i)
-                        && statusbar_position(i) == STATUSBAR_CUSTOM, i);
-    }
-#endif
-    return old;
-}
-
 static void viewportmanager_redraw(void* data)
 {
     int i;
-
     FOR_NB_SCREENS(i)
     {
-        if (showing_bars(i)
-                && statusbar_position(i) != STATUSBAR_CUSTOM)
+		if (statusbar_position(i) == STATUSBAR_CUSTOM)
+			sb_skin_update(i);
+        else if (statusbar_position(i) != STATUSBAR_OFF)
             gui_statusbar_draw(&statusbars.statusbars[i], NULL != data);
     }
 }
 #ifdef HAVE_LCD_BITMAP
-
-static void statusbar_toggled(void* param)
-{
-    (void)param;
-    /* update vp manager for the new setting and reposition vps
-     * if necessary */
-    viewportmanager_theme_changed(THEME_STATUSBAR);
-}
-
 void viewportmanager_theme_changed(const int which)
 {
     int i;
@@ -177,12 +185,7 @@
 #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 */
@@ -191,33 +194,18 @@
     }
     if (which & THEME_STATUSBAR)
     {
-        statusbar_enabled = 0;
-        FOR_NB_SCREENS(i)
-        {
-            if (statusbar_position(i) != STATUSBAR_OFF)
-                statusbar_enabled  |= VP_SB_ONSCREEN(i);
-        }
-
-        viewportmanager_set_statusbar(statusbar_enabled);
-
-        /* reposition viewport to fit statusbar, only if not using the ui vp */
+        /* 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)
+    if (1)
     {
         add_event(GUI_EVENT_REFRESH, false, viewportmanager_ui_vp_changed);
         remove_event(GUI_EVENT_REFRESH, viewportmanager_call_draw_func);
@@ -270,7 +258,7 @@
 static unsigned viewport_init_ui_vp(void)
 {
     int screen;
-    unsigned ret = 0;
+    const char *ret = NULL;
     char *setting;
     FOR_NB_SCREENS(screen)
     {
@@ -280,15 +268,13 @@
         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
@@ -363,11 +349,17 @@
 #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)
     {
Index: apps/gui/viewport.h
===================================================================
--- apps/gui/viewport.h	(revision 23799)
+++ apps/gui/viewport.h	(working copy)
@@ -31,59 +31,30 @@
 /* return the number of text lines in the vp viewport */
 int viewport_get_nb_lines(const struct viewport *vp);
 
-void viewport_set_defaults(struct viewport *vp,
-                            const enum screen_type screen);
-
-/* Used to specify which screens the statusbar (SB) should be displayed on.
- *
- * The parameter is a bit OR'ed combination of the following (screen is
- * SCREEN_MAIN or SCREEN_REMOTE from screen_access.h):
- *
- * VP_SB_HIDE_ALL means "hide the SB on all screens"
- * VP_SB_ONSCREEN(screen) means "display the SB on the given screen
- *                              as specified by the SB setting for that screen"
- * VP_SB_IGNORE_SETTING(screen) means "ignore the SB setting for that screen"
- * VP_SB_ALLSCREENS means "VP_SB_ONSCREEN for all screens"
- * 
- * In most cases, VP_SB_ALLSCREENS should be used which means display the SB
- * as specified by the settings.
- * For the WPS (and other possible exceptions) use VP_SB_IGNORE_SETTING() to
- * FORCE the statusbar on for the given screen (i.e it will show regardless
- * of the setting)
- *
- * Returns the status before the call. This value can be used to restore the
- * SB "displaying rules".
- */
-
-
 #define THEME_STATUSBAR             (BIT_N(0))
 #define THEME_UI_VIEWPORT           (BIT_N(1))
 #define THEME_BUTTONBAR             (BIT_N(2))
 #define THEME_LANGUAGE              (BIT_N(3))
 #define THEME_ALL                   (~(0u))
 
-#define VP_SB_HIDE_ALL                          0
-#define VP_SB_ONSCREEN(screen)                  BIT_N(screen)
-#define VP_SB_IGNORE_SETTING(screen)            BIT_N(4+screen)
-#define VP_SB_ALLSCREENS            (VP_SB_ONSCREEN(0)|VP_SB_ONSCREEN(1))
-
 #ifndef __PCTOOL__
 /*
  * Initialize the viewportmanager, which in turns initializes the UI vp and
  * statusbar stuff
  */
 void viewportmanager_init(void);
-int viewportmanager_get_statusbar(void);
-int viewportmanager_set_statusbar(const int enabled);
 
 
-/*
- * Initializes the given viewport with maximum dimensions minus status- and
- * buttonbar
- */
+void viewport_set_defaults(struct viewport *vp,
+                            const enum screen_type screen);
 void viewport_set_fullscreen(struct viewport *vp,
-                              const  enum screen_type screen);
+                              const enum screen_type screen);
+void viewportmanager_theme_enable(enum screen_type screen, bool enable,
+								  struct viewport *viewport);
 
+void viewportmanager_theme_undo(enum screen_type screen,
+								const struct viewport *viewport);
+
 #ifdef HAVE_LCD_BITMAP
 
 /* call this when a theme changed */
@@ -95,8 +66,6 @@
 #endif
 
 #else /* HAVE_LCD_CHARCELL */
-#define viewport_set_current_vp(a)
-#define viewport_get_current_vp() NULL
 #define viewportmanager_theme_changed(a)
 #endif
 
Index: apps/menu.c
===================================================================
--- apps/menu.c	(revision 23799)
+++ apps/menu.c	(working copy)
@@ -343,8 +343,8 @@
     const struct menu_item_ex *temp, *menu;
     int ret = 0, i;
     bool redraw_lists;
-    int oldbars = viewportmanager_get_statusbar();
-    viewportmanager_set_statusbar(hide_bars ? VP_SB_HIDE_ALL : oldbars);
+	FOR_NB_SCREENS(i)
+		viewportmanager_theme_enable(i, true/*!hide_bars*/, NULL);
     
     const struct menu_item_ex *menu_stack[MAX_MENUS];
     int menu_stack_selected_item[MAX_MENUS];
@@ -686,7 +686,8 @@
         *start_selected = get_menu_selection(
                             gui_synclist_get_sel_pos(&lists), menu);
     }
-    viewportmanager_set_statusbar(oldbars);
+	FOR_NB_SCREENS(i)
+		viewportmanager_theme_undo(i, NULL);
     return ret;
 }
 
Index: apps/menus/eq_menu.c
===================================================================
--- apps/menus/eq_menu.c	(revision 23799)
+++ apps/menus/eq_menu.c	(working copy)
@@ -391,7 +391,8 @@
     enum eq_type current_type;
     char buf[24];
     int i, w, h, height, start_item, nb_eq_sliders[NB_SCREENS];
-    int barsenabled = viewportmanager_set_statusbar(VP_SB_HIDE_ALL);
+	FOR_NB_SCREENS(i)
+		viewportmanager_theme_enable(i, false, NULL);
 
 
     FOR_NB_SCREENS(i) {
@@ -570,12 +571,13 @@
     }
 
     /* Reset screen settings */
-    FOR_NB_SCREENS(i) {
+    FOR_NB_SCREENS(i) 
+    {
         screens[i].setfont(FONT_UI);
         screens[i].clear_display();
         screens[i].set_viewport(NULL);
+		viewportmanager_theme_undo(i, NULL);
     }
-    viewportmanager_set_statusbar(barsenabled);
     return result;
 }
 
Index: apps/plugin.c
===================================================================
--- apps/plugin.c	(revision 23799)
+++ apps/plugin.c	(working copy)
@@ -230,7 +230,6 @@
     lcd_remote_bitmap,
 #endif
     viewport_set_defaults,
-    viewportmanager_set_statusbar,
     
     /* list */
     gui_synclist_init,
@@ -680,8 +679,7 @@
 
 int plugin_load(const char* plugin, const void* parameter)
 {
-    int rc;
-    int oldbars;
+    int rc, i;
     struct plugin_header *hdr;
 #ifdef SIMULATOR
     void *pd;
@@ -787,7 +785,8 @@
     lcd_remote_update();
 #endif
 
-    oldbars = viewportmanager_set_statusbar(VP_SB_HIDE_ALL);
+	FOR_NB_SCREENS(i)
+		viewportmanager_theme_enable(i, false, NULL);
 
     cpucache_invalidate();
     
@@ -834,7 +833,8 @@
 #endif
 #endif
 
-    viewportmanager_set_statusbar(oldbars);
+	FOR_NB_SCREENS(i)
+		viewportmanager_theme_undo(i, NULL);
 
     if (rc != PLUGIN_GOTO_WPS)
     {
Index: apps/plugin.h
===================================================================
--- apps/plugin.h	(revision 23799)
+++ apps/plugin.h	(working copy)
@@ -335,7 +335,6 @@
                               int height);
 #endif
     void (*viewport_set_defaults)(struct viewport *vp, enum screen_type screen);
-    int (*viewportmanager_set_statusbar)(int enable_status);
     /* list */
     void (*gui_synclist_init)(struct gui_synclist * lists,
             list_get_name callback_get_item_name, void * data,
Index: apps/debug_menu.c
===================================================================
--- apps/debug_menu.c	(revision 23799)
+++ apps/debug_menu.c	(working copy)
@@ -2652,13 +2652,16 @@
     };
 static int menu_action_callback(int btn, struct gui_synclist *lists)
 {
+	int i;
     if (btn == ACTION_STD_OK)
     {
-        int oldbars = viewportmanager_set_statusbar(VP_SB_HIDE_ALL);
+		FOR_NB_SCREENS(i)
+			viewportmanager_theme_enable(i, false, NULL);
         menuitems[gui_synclist_get_sel_pos(lists)].function();
         btn = ACTION_REDRAW;
         send_event(GUI_EVENT_REFRESH, NULL);
-        viewportmanager_set_statusbar(oldbars);
+		FOR_NB_SCREENS(i)
+			viewportmanager_theme_undo(i, NULL);
     }
     return btn;
 }

Reply via email to