2002-12-02 19:34:54 +00:00
// Theme.cc for FbTk - Fluxbox ToolKit
2005-01-24 18:02:34 +00:00
// Copyright (c) 2002 - 2005 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.
2004-11-19 11:37:27 +00:00
// $Id$
2002-12-02 19:34:54 +00:00
# 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"
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>
2003-11-16 22:33:56 +00:00
2002-12-02 19:34:54 +00:00
using namespace std ;
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 ) {
for_each ( tmlist . begin ( ) , tmlist . end ( ) ,
* this ) ;
// 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 ) {
( * it ) - > reconfigTheme ( ) ;
( * it ) - > reconfigSig ( ) . notify ( ) ;
}
}
ThemeManager & m_tm ;
} ;
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 ( ) :
2004-01-02 22:55:35 +00:00
// max_screens: we initialize this later so we can set m_verbose
// without having a display connection
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 ;
// TODO: use find and return false if it's already there
// instead of unique
2006-01-03 10:02:46 +00:00
m_themes [ tm . screenNum ( ) ] . push_back ( & tm ) ;
m_themes [ tm . screenNum ( ) ] . unique ( ) ;
2002-12-02 19:34:54 +00:00
return true ;
}
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 ;
}
2005-11-16 22:08:05 +00:00
bool ThemeManager : : load ( const std : : string & filename ,
2006-01-03 10:02:46 +00:00
const std : : string & overlay_filename , int screen_num ) {
2003-12-03 00:18:58 +00:00
std : : string location = FbTk : : StringUtil : : expandFilename ( filename ) ;
2003-11-16 22:33:56 +00:00
std : : string prefix = " " ;
2004-12-18 01:29:22 +00:00
if ( FileUtil : : isDirectory ( filename . 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 ( ) ) {
std : : string overlay_location = FbTk : : StringUtil : : expandFilename ( overlay_filename ) ;
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 ) {
for_each ( m_themes . begin ( ) ,
m_themes . end ( ) ,
load_theme_helper ) ;
} 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 ;
cerr < < _FBTKTEXT ( Error , ThemeItem , " Failed to read theme item " , " When reading a style, couldn't read a specific item (following) " ) < < " : " < < resource - > name ( ) < < endl ;
}
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
bool ThemeManager : : loadItem ( ThemeItem_base & resource , const std : : string & name , const std : : 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
}
2002-12-02 19:34:54 +00:00
std : : string ThemeManager : : resourceValue ( const std : : string & name , const std : : string & altname ) {
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 ) {
std : : list < ThemeItem_base * > : : iterator item = ( * it ) - > itemList ( ) . begin ( ) ;
std : : list < ThemeItem_base * > : : iterator item_end = ( * it ) - > itemList ( ) . end ( ) ;
for ( ; item ! = item_end ; + + item ) {
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 ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < std : : string > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <string> " < < endl ;
} else if ( typeid ( * * item ) = = typeid ( ThemeItem < Font > ) ) {
cerr < < ( * item ) - > name ( ) < < " : <font> " < < endl ;
} else {
cerr < < ( * item ) - > name ( ) < < " : " < < endl ;
}
}
}
2003-08-22 22:17:30 +00:00
2003-09-14 11:17:21 +00:00
}
2003-08-22 22:17:30 +00:00
*/
2002-12-02 19:34:54 +00:00
} ; // end namespace FbTk