1 /*****************************************************************************
2 * theme.cpp
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
5 * $Id: 710047ed00c3668aa472b345cbe495243d5cf74c $
6 *
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 * Olivier Teulière <ipkiss@via.ecp.fr>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
24
25 #include "theme.hpp"
26 #include "top_window.hpp"
27 #include <sstream>
28
29
~Theme()30 Theme::~Theme()
31 {
32 // Be sure things are destroyed in the right order (XXX check)
33 m_layouts.clear();
34 m_controls.clear();
35 m_windows.clear();
36 m_bitmaps.clear();
37 m_fonts.clear();
38 m_commands.clear();
39 m_vars.clear();
40 m_curves.clear();
41 }
42
43
loadConfig()44 void Theme::loadConfig()
45 {
46 msg_Dbg( getIntf(), "loading theme configuration");
47
48 if( readConfig() == VLC_SUCCESS )
49 {
50 applyConfig();
51 }
52 else
53 {
54 getWindowManager().showAll( true );
55 }
56 }
57
58
applyConfig()59 void Theme::applyConfig()
60 {
61 msg_Dbg( getIntf(), "Apply saved configuration");
62
63 std::list<save_t>::const_iterator it;
64 for( it = m_saved.begin(); it!= m_saved.end(); ++it )
65 {
66 TopWindow *pWin = (*it).win;
67 GenericLayout *pLayout = (*it).layout;
68 int x = (*it).x;
69 int y = (*it).y;
70 int width = (*it).width;
71 int height = (*it).height;
72
73 // Restore the layout
74 m_windowManager.setActiveLayout( *pWin, *pLayout );
75 if( pLayout->getWidth() != width ||
76 pLayout->getHeight() != height )
77 {
78 m_windowManager.startResize( *pLayout, WindowManager::kResizeSE );
79 m_windowManager.resize( *pLayout, width, height );
80 m_windowManager.stopResize();
81 }
82 // Move the window (which incidentally takes care of the anchoring)
83 m_windowManager.startMove( *pWin );
84 m_windowManager.move( *pWin, x, y );
85 m_windowManager.stopMove();
86 }
87
88 for( it = m_saved.begin(); it != m_saved.end(); ++it )
89 {
90 if( (*it).visible )
91 m_windowManager.show( *((*it).win) );
92 }
93 }
94
95
readConfig()96 int Theme::readConfig()
97 {
98 msg_Dbg( getIntf(), "reading theme configuration");
99
100 // Get config from vlcrc file
101 char *save = config_GetPsz( getIntf(), "skins2-config" );
102 if( !save || !*save )
103 {
104 free( save );
105 return VLC_EGENERIC;
106 }
107
108 std::istringstream inStream( save );
109 free( save );
110
111 char sep;
112 std::string winId, layId;
113 int x, y, width, height, visible;
114 bool somethingVisible = false;
115 while( !inStream.eof() )
116 {
117 std::stringbuf buf, buf2;
118
119 inStream >> sep;
120 if( sep != '[' )
121 goto invalid;
122
123 inStream >> sep;
124 if( sep != '"' )
125 goto invalid;
126 inStream.get( buf, '"' );
127 winId = buf.str();
128 inStream >> sep;
129
130 inStream >> sep;
131 if( sep != '"' )
132 goto invalid;
133 inStream.get( buf2, '"' );
134 layId = buf2.str();
135 inStream >> sep;
136
137 inStream >> x >> y >> width >> height >> visible >> sep >> std::ws;
138 if( sep != ']' )
139 goto invalid;
140
141 // Try to find the window and the layout
142 std::map<std::string, TopWindowPtr>::const_iterator itWin;
143 std::map<std::string, GenericLayoutPtr>::const_iterator itLay;
144 itWin = m_windows.find( winId );
145 itLay = m_layouts.find( layId );
146 if( itWin == m_windows.end() || itLay == m_layouts.end() )
147 goto invalid;
148
149 save_t save;
150 save.win = itWin->second.get();
151 save.layout = itLay->second.get();
152 save.x = x;
153 save.y = y;
154 save.width = width;
155 save.height = height;
156 save.visible = visible;
157
158 m_saved.push_back( save );
159
160 if( visible )
161 somethingVisible = true;
162 }
163
164 if( !somethingVisible )
165 goto invalid;
166
167 return VLC_SUCCESS;
168
169 invalid:
170 msg_Dbg( getIntf(), "invalid config: %s", inStream.str().c_str() );
171 m_saved.clear();
172 return VLC_EGENERIC;
173 }
174
175
saveConfig()176 void Theme::saveConfig()
177 {
178 msg_Dbg( getIntf(), "saving theme configuration");
179
180 std::map<std::string, TopWindowPtr>::const_iterator itWin;
181 std::map<std::string, GenericLayoutPtr>::const_iterator itLay;
182 std::ostringstream outStream;
183 for( itWin = m_windows.begin(); itWin != m_windows.end(); ++itWin )
184 {
185 TopWindow *pWin = itWin->second.get();
186
187 // Find the layout id for this window
188 std::string layoutId;
189 const GenericLayout *pLayout = &pWin->getActiveLayout();
190 for( itLay = m_layouts.begin(); itLay != m_layouts.end(); ++itLay )
191 {
192 if( itLay->second.get() == pLayout )
193 {
194 layoutId = itLay->first;
195 }
196 }
197
198 outStream << '['
199 << '"' << itWin->first << '"' << ' '
200 << '"' << layoutId << '"' << ' '
201 << pWin->getLeft() << ' ' << pWin->getTop() << ' '
202 << pLayout->getWidth() << ' ' << pLayout->getHeight() << ' '
203 << (pWin->getVisibleVar().get() ? 1 : 0) << ']';
204 }
205
206 // Save config to file
207 config_PutPsz( getIntf(), "skins2-config", outStream.str().c_str() );
208 }
209
210
211 // Takes an ID of the form "id1;id2;id3", and returns the object
212 // corresponding to the first valid ID. If no ID is valid, it returns NULL.
213 // XXX The string handling here probably could be improved.
214 template<class T> typename T::pointer
find_first_object(const std::string & id) const215 Theme::IDmap<T>::find_first_object( const std::string &id ) const
216 {
217 std::string rightPart = id;
218 std::string::size_type pos;
219 do
220 {
221 pos = rightPart.find( ";" );
222 std::string leftPart = rightPart.substr( 0, pos );
223
224 typename T::pointer p = find_object( leftPart );
225 if( p ) return p;
226
227 if( pos != std::string::npos )
228 {
229 rightPart = rightPart.substr( pos, rightPart.size() );
230 rightPart =
231 rightPart.substr( rightPart.find_first_not_of( " \t;" ),
232 rightPart.size() );
233 }
234 }
235 while( pos != std::string::npos );
236 return NULL;
237 }
238
getBitmapById(const std::string & id) const239 GenericBitmap *Theme::getBitmapById( const std::string &id ) const
240 {
241 return m_bitmaps.find_first_object( id );
242 }
243
getFontById(const std::string & id) const244 GenericFont *Theme::getFontById( const std::string &id ) const
245 {
246 return m_fonts.find_first_object( id );
247 }
248
249