2002-12-02 19:34:54 +00:00
// Theme.cc for FbTk - Fluxbox ToolKit
2006-02-16 06:53:05 +00:00
// Copyright (c) 2002 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
2002-12-02 19:34:54 +00:00
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
# include "Theme.hh"
2003-05-18 22:12:25 +00:00
# include "XrmDatabaseHelper.hh"
2002-12-02 19:34:54 +00:00
# include "App.hh"
2003-08-28 15:12:36 +00:00
# include "StringUtil.hh"
2004-12-18 01:29:22 +00:00
# include "FileUtil.hh"
2004-06-07 11:46:05 +00:00
# include "I18n.hh"
2004-10-21 16:45:30 +00:00
# include "Image.hh"
2010-09-15 00:07:09 +00:00
# include "STLUtil.hh"
2003-04-28 22:25:13 +00:00
2004-08-31 15:26:40 +00:00
# ifdef HAVE_CSTDIO
# include <cstdio>
# else
# include <stdio.h>
# endif
2003-08-22 22:17:30 +00:00
# include <memory>
2002-12-02 19:34:54 +00:00
# include <iostream>
2006-03-24 10:52:57 +00:00
# include <algorithm>
2003-11-16 22:33:56 +00:00
2006-10-27 06:57:43 +00:00
using std : : cerr ;
using std : : endl ;
using std : : string ;
2003-08-22 22:17:30 +00:00
2002-12-02 19:34:54 +00:00
namespace FbTk {
2006-01-03 10:02:46 +00:00
struct LoadThemeHelper {
LoadThemeHelper ( ) : m_tm ( ThemeManager : : instance ( ) ) { }
void operator ( ) ( Theme * tm ) {
m_tm . loadTheme ( * tm ) ;
}
void operator ( ) ( ThemeManager : : ThemeList & tmlist ) {
2006-10-27 06:57:43 +00:00
2010-09-15 00:07:09 +00:00
STLUtil : : forAll ( tmlist , * this ) ;
2006-01-03 10:02:46 +00:00
// send reconfiguration signal to theme and listeners
ThemeManager : : ThemeList : : iterator it = tmlist . begin ( ) ;
ThemeManager : : ThemeList : : iterator it_end = tmlist . end ( ) ;
for ( ; it ! = it_end ; + + it ) {
2011-04-29 08:52:28 +00:00
( * it ) - > reconfigSig ( ) . emit ( ) ;
2006-01-03 10:02:46 +00:00
}
}
2006-10-27 06:57:43 +00:00
ThemeManager & m_tm ;
2006-01-03 10:02:46 +00:00
} ;
2002-12-02 19:34:54 +00:00
Theme : : Theme ( int screen_num ) : m_screen_num ( screen_num ) {
2003-08-28 23:06:27 +00:00
ThemeManager : : instance ( ) . registerTheme ( * this ) ;
2002-12-02 19:34:54 +00:00
}
Theme : : ~ Theme ( ) {
2003-08-28 23:06:27 +00:00
ThemeManager : : instance ( ) . unregisterTheme ( * this ) ;
2002-12-02 19:34:54 +00:00
}
ThemeManager & ThemeManager : : instance ( ) {
static ThemeManager tm ;
return tm ;
}
ThemeManager : : ThemeManager ( ) :
2006-10-27 06:57:43 +00:00
// max_screens: we initialize this later so we can set m_verbose
2004-01-02 22:55:35 +00:00
// without having a display connection
2006-10-27 06:57:43 +00:00
m_max_screens ( - 1 ) ,
2003-11-16 22:33:56 +00:00
m_verbose ( false ) ,
m_themelocation ( " " ) {
2002-12-02 19:34:54 +00:00
}
bool ThemeManager : : registerTheme ( Theme & tm ) {
2006-01-03 10:02:46 +00:00
if ( m_max_screens < 0 ) {
2004-01-02 22:55:35 +00:00
m_max_screens = ScreenCount ( FbTk : : App : : instance ( ) - > display ( ) ) ;
2006-01-03 10:02:46 +00:00
m_themes . resize ( m_max_screens ) ;
}
2004-01-02 22:55:35 +00:00
2002-12-02 19:34:54 +00:00
// valid screen num?
if ( m_max_screens < tm . screenNum ( ) | | tm . screenNum ( ) < 0 )
return false ;
2006-01-03 10:02:46 +00:00
2007-12-16 08:50:59 +00:00
ThemeList : : const_iterator it = m_themes [ tm . screenNum ( ) ] . begin ( ) ,
it_end = m_themes [ tm . screenNum ( ) ] . end ( ) ;
if ( std : : find ( it , it_end , & tm ) = = it_end ) {
m_themes [ tm . screenNum ( ) ] . push_back ( & tm ) ;
return true ;
}
return false ;
2002-12-02 19:34:54 +00:00
}
bool ThemeManager : : unregisterTheme ( Theme & tm ) {
2006-01-03 10:02:46 +00:00
if ( m_max_screens < tm . screenNum ( ) | | tm . screenNum ( ) < 0 )
return false ;
m_themes [ tm . screenNum ( ) ] . remove ( & tm ) ;
2002-12-02 19:34:54 +00:00
return true ;
}
2006-10-27 06:57:43 +00:00
bool ThemeManager : : load ( const string & filename ,
const string & overlay_filename , int screen_num ) {
2012-12-11 18:37:59 +00:00
2006-10-27 06:57:43 +00:00
string location = FbTk : : StringUtil : : expandFilename ( filename ) ;
2008-05-14 08:40:53 +00:00
StringUtil : : removeTrailingWhitespace ( location ) ;
StringUtil : : removeFirstWhitespace ( location ) ;
2006-10-27 06:57:43 +00:00
string prefix = " " ;
2003-11-16 22:33:56 +00:00
2012-12-11 18:37:59 +00:00
if ( FileUtil : : isDirectory ( location . c_str ( ) ) ) {
2003-11-16 22:33:56 +00:00
prefix = location ;
location . append ( " /theme.cfg " ) ;
2004-12-18 01:29:22 +00:00
if ( ! FileUtil : : isRegularFile ( location . c_str ( ) ) ) {
2004-08-26 18:26:39 +00:00
location = prefix ;
location . append ( " /style.cfg " ) ;
2004-12-18 01:29:22 +00:00
if ( ! FileUtil : : isRegularFile ( location . c_str ( ) ) ) {
2004-08-26 18:26:39 +00:00
cerr < < " Error loading theme file " < < location < < " : not a regular file " < < endl ;
return false ;
}
2003-11-16 22:33:56 +00:00
}
} else {
// dirname
prefix = location . substr ( 0 , location . find_last_of ( ' / ' ) ) ;
}
if ( ! m_database . load ( location . c_str ( ) ) )
2002-12-02 19:34:54 +00:00
return false ;
2005-11-16 22:08:05 +00:00
if ( ! overlay_filename . empty ( ) ) {
2006-10-27 06:57:43 +00:00
string overlay_location = FbTk : : StringUtil : : expandFilename ( overlay_filename ) ;
2005-11-16 22:08:05 +00:00
if ( FileUtil : : isRegularFile ( overlay_location . c_str ( ) ) ) {
XrmDatabaseHelper overlay_db ;
if ( overlay_db . load ( overlay_location . c_str ( ) ) ) {
// after a merge the src_db is destroyed
// so, make sure XrmDatabaseHelper::m_database == 0
XrmMergeDatabases ( * overlay_db , & ( * m_database ) ) ;
* overlay_db = 0 ;
}
}
}
2003-11-16 22:33:56 +00:00
// relies on the fact that load_rc clears search paths each time
if ( m_themelocation ! = " " ) {
Image : : removeSearchPath ( m_themelocation ) ;
m_themelocation . append ( " /pixmaps " ) ;
Image : : removeSearchPath ( m_themelocation ) ;
}
m_themelocation = prefix ;
location = prefix ;
Image : : addSearchPath ( location ) ;
location . append ( " /pixmaps " ) ;
Image : : addSearchPath ( location ) ;
2006-01-03 10:02:46 +00:00
LoadThemeHelper load_theme_helper ;
2003-12-29 11:04:09 +00:00
// get list and go throu all the resources and load them
2006-01-03 10:02:46 +00:00
// and then reconfigure them
if ( screen_num < 0 | | screen_num > m_max_screens ) {
2010-09-15 00:07:09 +00:00
STLUtil : : forAll ( m_themes , load_theme_helper ) ;
2006-01-03 10:02:46 +00:00
} else {
load_theme_helper ( m_themes [ screen_num ] ) ;
2002-12-02 19:34:54 +00:00
}
2005-11-16 22:08:05 +00:00
2002-12-02 19:34:54 +00:00
return true ;
}
void ThemeManager : : loadTheme ( Theme & tm ) {
2006-01-03 10:02:46 +00:00
Theme : : ItemList : : iterator i = tm . itemList ( ) . begin ( ) ;
Theme : : ItemList : : iterator i_end = tm . itemList ( ) . end ( ) ;
2002-12-02 19:34:54 +00:00
for ( ; i ! = i_end ; + + i ) {
ThemeItem_base * resource = * i ;
2003-08-19 21:25:26 +00:00
if ( ! loadItem ( * resource ) ) {
// try fallback resource in theme
if ( ! tm . fallback ( * resource ) ) {
2004-06-07 11:46:05 +00:00
if ( verbose ( ) ) {
_FB_USES_NLS ;
2006-06-21 14:41:16 +00:00
cerr < < _FBTK_CONSOLETEXT ( Error , ThemeItem , " Failed to read theme item " , " When reading a style, couldn't read a specific item (following) " ) < < " : " < < resource - > name ( ) < < endl ;
2004-06-07 11:46:05 +00:00
}
resource - > setDefaultValue ( ) ;
2003-08-19 21:25:26 +00:00
}
}
2002-12-02 19:34:54 +00:00
}
2003-08-11 14:54:18 +00:00
// send reconfiguration signal to theme and listeners
2002-12-02 19:34:54 +00:00
}
2003-08-19 21:25:26 +00:00
bool ThemeManager : : loadItem ( ThemeItem_base & resource ) {
return loadItem ( resource , resource . name ( ) , resource . altName ( ) ) ;
}
/// handles resource item loading with specific name/altname
2006-10-27 06:57:43 +00:00
bool ThemeManager : : loadItem ( ThemeItem_base & resource , const string & name , const string & alt_name ) {
2003-08-13 09:24:02 +00:00
XrmValue value ;
char * value_type ;
2003-08-19 21:25:26 +00:00
if ( XrmGetResource ( * m_database , name . c_str ( ) ,
alt_name . c_str ( ) , & value_type , & value ) ) {
2003-08-13 09:24:02 +00:00
resource . setFromString ( value . addr ) ;
2004-04-26 15:04:37 +00:00
resource . load ( & name , & alt_name ) ; // load additional stuff by the ThemeItem
2003-08-19 21:25:26 +00:00
} else
return false ;
return true ;
2003-08-13 09:24:02 +00:00
}
2006-10-27 06:57:43 +00:00
string ThemeManager : : resourceValue ( const string & name , const string & altname ) {
2002-12-02 19:34:54 +00:00
XrmValue value ;
char * value_type ;
if ( * m_database ! = 0 & & XrmGetResource ( * m_database , name . c_str ( ) ,
2004-04-26 15:04:37 +00:00
altname . c_str ( ) , & value_type , & value ) & & value . addr ! = 0 )
2002-12-02 19:34:54 +00:00
return string ( value . addr ) ;
2004-04-26 15:04:37 +00:00
2002-12-02 19:34:54 +00:00
return " " ;
}
2003-08-22 22:17:30 +00:00
/*
2003-09-14 11:17:21 +00:00
void ThemeManager : : listItems ( ) {
ThemeList : : iterator it = m_themelist . begin ( ) ;
ThemeList : : iterator it_end = m_themelist . end ( ) ;
for ( ; it ! = it_end ; + + it ) {
2006-10-27 06:57:43 +00:00
list < ThemeItem_base * > : : iterator item = ( * it ) - > itemList ( ) . begin ( ) ;
list < ThemeItem_base * > : : iterator item_end = ( * it ) - > itemList ( ) . end ( ) ;
2003-09-14 11:17:21 +00:00
for ( ; item ! = item_end ; + + item ) {
2006-10-27 06:57:43 +00:00
2003-09-14 11:17:21 +00:00
if ( typeid ( * * item ) = = typeid ( ThemeItem < Texture > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <texture type> " < < endl ;
cerr < < ( * item ) - > name ( ) < < " .pixmap: <filename> " < < endl ;
cerr < < ( * item ) - > name ( ) < < " .color: <color> " < < endl ;
cerr < < ( * item ) - > name ( ) < < " .colorTo: <color> " < < endl ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < Color > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <color> " < < endl ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < int > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <integer> " < < endl ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < bool > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <boolean> " < < endl ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < PixmapWithMask > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <filename> " < < endl ;
2006-10-27 06:57:43 +00:00
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < string > ) ) {
2003-09-14 11:17:21 +00:00
cerr < < ( * item ) - > name ( ) < < " : <string> " < < endl ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < Font > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <font> " < < endl ;
} else {
cerr < < ( * item ) - > name ( ) < < " : " < < endl ;
}
}
}
2006-10-27 06:57:43 +00:00
2003-09-14 11:17:21 +00:00
}
2003-08-22 22:17:30 +00:00
*/
2008-04-21 22:43:10 +00:00
} // end namespace FbTk