]> git.sesse.net Git - vlc/blobdiff - modules/gui/skins2/src/theme.cpp
skins2: rework theme loader
[vlc] / modules / gui / skins2 / src / theme.cpp
index bcfef87db483d02c716867b4706c5c024985f3e2..f233f79597abf2458053623c2a4f8e9ae93a947f 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
- *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #include "theme.hpp"
+#include "top_window.hpp"
+#include <sstream>
 
 
 Theme::~Theme()
@@ -41,115 +43,206 @@ Theme::~Theme()
 
 void Theme::loadConfig()
 {
-    msg_Dbg( getIntf(), "Loading theme configuration");
+    msg_Dbg( getIntf(), "loading theme configuration");
 
-    // Get config from vlcrc file
-    char *save = config_GetPsz( getIntf(), "skins2-config" );
-    if( !save ) return;
-
-    // Is there an existing config?
-    if( !strcmp( save, "" ) )
+    if( readConfig() == VLC_SUCCESS )
     {
-        // Show the windows
-        m_windowManager.showAll( true );
-        return;
+        applyConfig();
     }
+    else
+    {
+        getWindowManager().showAll( true );
+    }
+}
 
-    // Initialization
-    map<string, TopWindowPtr>::const_iterator it;
-    int i = 0;
-    int x, y, visible, scan;
 
-    // Get config for each window
-    for( it = m_windows.begin(); it != m_windows.end(); it++ )
-    {
-        TopWindow *pWin = (*it).second.get();
-        // Get config
-        scan = sscanf( &save[i * 13], "(%4d,%4d,%1d)", &x, &y, &visible );
+void Theme::applyConfig()
+{
+    msg_Dbg( getIntf(), "Apply saved configuration");
 
-        // If config has the correct number of arguments
-        if( scan > 2 )
+    list<save_t>::const_iterator it;
+    for( it = m_saved.begin(); it!= m_saved.end(); ++it )
+    {
+        TopWindow *pWin = (*it).win;
+        GenericLayout *pLayout = (*it).layout;
+        int x = (*it).x;
+        int y = (*it).y;
+        int width = (*it).width;
+        int height = (*it).height;
+
+        // Restore the layout
+        m_windowManager.setActiveLayout( *pWin, *pLayout );
+        if( pLayout->getWidth() != width ||
+            pLayout->getHeight() != height )
         {
-            m_windowManager.startMove( *pWin );
-            m_windowManager.move( *pWin, x, y );
-            m_windowManager.stopMove();
-            if( visible )
-            {
-                m_windowManager.show( *pWin );
-            }
+            m_windowManager.startResize( *pLayout, WindowManager::kResizeSE );
+            m_windowManager.resize( *pLayout, width, height );
+            m_windowManager.stopResize();
         }
+        // Move the window (which incidentally takes care of the anchoring)
+        m_windowManager.startMove( *pWin );
+        m_windowManager.move( *pWin, x, y );
+        m_windowManager.stopMove();
+    }
 
-        // Next window
-        i++;
+    for( it = m_saved.begin(); it != m_saved.end(); ++it )
+    {
+       if( (*it).visible )
+            m_windowManager.show( *((*it).win) );
     }
-    free( save );
 }
 
 
-void Theme::saveConfig()
+int Theme::readConfig()
 {
-    msg_Dbg( getIntf(), "Saving theme configuration");
+    msg_Dbg( getIntf(), "reading theme configuration");
 
-    // Initialize char where config is stored
-    char *save  = new char[400];
-    map<string, TopWindowPtr>::const_iterator it;
-    int i = 0;
-    int x, y;
-
-    // Save config of every window
-    for( it = m_windows.begin(); it != m_windows.end(); it++ )
+    // Get config from vlcrc file
+    char *save = config_GetPsz( getIntf(), "skins2-config" );
+    if( !save || !*save )
     {
-        TopWindow *pWin = (*it).second.get();
-        // Print config
-        x = pWin->getLeft();
-        y = pWin->getTop();
-        sprintf( &save[i * 13], "(%4d,%4d,%1d)", x, y,
-            pWin->getVisibleVar().get() );
-        i++;
+        free( save );
+        return VLC_EGENERIC;
     }
 
-    // Save config to file
-    config_PutPsz( getIntf(), "skins2-config", save );
+    istringstream inStream( save );
+    free( save );
 
-    // Free memory
-    delete[] save;
-}
+    char sep;
+    string winId, layId;
+    int x, y, width, height, visible;
+    bool somethingVisible = false;
+    while( !inStream.eof() )
+    {
+        stringbuf buf, buf2;
+
+        inStream >> sep;
+        if( sep != '[' )
+            goto invalid;
+
+        inStream >> sep;
+        if( sep != '"' )
+            goto invalid;
+        inStream.get( buf, '"' );
+        winId = buf.str();
+        inStream >> sep;
+
+        inStream >> sep;
+        if( sep != '"' )
+            goto invalid;
+        inStream.get( buf2, '"' );
+        layId = buf2.str();
+        inStream >> sep;
+
+        inStream >> x >> y >> width >> height >> visible >> sep >> ws;
+        if( sep != ']' )
+            goto invalid;
+
+        // Try to find the window and the layout
+        map<string, TopWindowPtr>::const_iterator itWin;
+        map<string, GenericLayoutPtr>::const_iterator itLay;
+        itWin = m_windows.find( winId );
+        itLay = m_layouts.find( layId );
+        if( itWin == m_windows.end() || itLay == m_layouts.end() )
+            goto invalid;
+
+        save_t save;
+        save.win = itWin->second.get();
+        save.layout = itLay->second.get();
+        save.x = x;
+        save.y = y;
+        save.width = width;
+        save.height = height;
+        save.visible = visible;
+
+        m_saved.push_back( save );
+
+        if( visible )
+            somethingVisible = true;
+    }
 
+    if( !somethingVisible )
+        goto invalid;
 
-// Useful macro
-#define FIND_OBJECT( mapData, mapName ) \
-    map<string, mapData>::const_iterator it; \
-    it = mapName.find( id ); \
-    if( it == mapName.end() ) \
-    { \
-        return NULL; \
-    } \
-    return (*it).second.get();
+    return VLC_SUCCESS;
 
-GenericBitmap *Theme::getBitmapById( const string &id )
-{
-    FIND_OBJECT( GenericBitmapPtr, m_bitmaps );
+invalid:
+    msg_Dbg( getIntf(), "invalid config: %s", inStream.str().c_str() );
+    m_saved.clear();
+    return VLC_EGENERIC;
 }
 
-GenericFont *Theme::getFontById( const string &id )
+
+void Theme::saveConfig()
 {
-    FIND_OBJECT( GenericFontPtr, m_fonts );
+    msg_Dbg( getIntf(), "saving theme configuration");
+
+    map<string, TopWindowPtr>::const_iterator itWin;
+    map<string, GenericLayoutPtr>::const_iterator itLay;
+    ostringstream outStream;
+    for( itWin = m_windows.begin(); itWin != m_windows.end(); itWin++ )
+    {
+        TopWindow *pWin = itWin->second.get();
+
+        // Find the layout id for this window
+        string layoutId;
+        const GenericLayout *pLayout = &pWin->getActiveLayout();
+        for( itLay = m_layouts.begin(); itLay != m_layouts.end(); itLay++ )
+        {
+            if( itLay->second.get() == pLayout )
+            {
+                layoutId = itLay->first;
+            }
+        }
+
+        outStream << '['
+            << '"' << itWin->first << '"' << ' '
+            << '"' << layoutId << '"' << ' '
+            << pWin->getLeft() << ' ' << pWin->getTop() << ' '
+            << pLayout->getWidth() << ' ' << pLayout->getHeight() << ' '
+            << (pWin->getVisibleVar().get() ? 1 : 0) << ']';
+    }
+
+    // Save config to file
+    config_PutPsz( getIntf(), "skins2-config", outStream.str().c_str() );
 }
 
-TopWindow *Theme::getWindowById( const string &id )
+
+// Takes an ID of the form "id1;id2;id3", and returns the object
+// corresponding to the first valid ID. If no ID is valid, it returns NULL.
+// XXX The string handling here probably could be improved.
+template<class T> typename T::pointer
+Theme::IDmap<T>::find_first_object( const string &id ) const
 {
-    FIND_OBJECT( TopWindowPtr, m_windows );
+    string rightPart = id;
+    string::size_type pos;
+    do
+    {
+        pos = rightPart.find( ";" );
+        string leftPart = rightPart.substr( 0, pos );
+
+        typename T::pointer p = find_object( leftPart );
+        if( p ) return p;
+
+        if( pos != string::npos )
+        {
+            rightPart = rightPart.substr( pos, rightPart.size() );
+            rightPart =
+                rightPart.substr( rightPart.find_first_not_of( " \t;" ),
+                                  rightPart.size() );
+        }
+    }
+    while( pos != string::npos );
+    return NULL;
 }
 
-GenericLayout *Theme::getLayoutById( const string &id )
+GenericBitmap *Theme::getBitmapById( const string &id ) const
 {
-    FIND_OBJECT( GenericLayoutPtr, m_layouts );
+    return m_bitmaps.find_first_object( id );
 }
 
-CtrlGeneric *Theme::getControlById( const string &id )
+GenericFont *Theme::getFontById( const string &id ) const
 {
-    FIND_OBJECT( CtrlGenericPtr, m_controls );
+    return m_fonts.find_first_object( id );
 }
 
-
-