00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Theme.hh"
00025
00026 #include "XrmDatabaseHelper.hh"
00027 #include "App.hh"
00028 #include "StringUtil.hh"
00029 #include "ThemeItems.hh"
00030 #include "Directory.hh"
00031
00032 #include <cstdio>
00033 #include <memory>
00034 #include <iostream>
00035
00036 using namespace std;
00037
00038 namespace FbTk {
00039
00040 Theme::Theme(int screen_num):m_screen_num(screen_num) {
00041 ThemeManager::instance().registerTheme(*this);
00042 }
00043
00044 Theme::~Theme() {
00045 ThemeManager::instance().unregisterTheme(*this);
00046 }
00047
00048 ThemeManager &ThemeManager::instance() {
00049 static ThemeManager tm;
00050 return tm;
00051 }
00052
00053 ThemeManager::ThemeManager():
00054
00055
00056 m_max_screens(-1),
00057 m_verbose(false),
00058 m_themelocation("") {
00059
00060 }
00061
00062 bool ThemeManager::registerTheme(Theme &tm) {
00063 if (m_max_screens < 0)
00064 m_max_screens = ScreenCount(FbTk::App::instance()->display());
00065
00066
00067 if (m_max_screens < tm.screenNum() || tm.screenNum() < 0)
00068 return false;
00069
00070
00071 m_themelist.push_back(&tm);
00072 m_themelist.unique();
00073 return true;
00074 }
00075
00076 bool ThemeManager::unregisterTheme(Theme &tm) {
00077 m_themelist.remove(&tm);
00078 return true;
00079 }
00080
00081 bool ThemeManager::load(const std::string &filename, int screen_num) {
00082 std::string location = FbTk::StringUtil::expandFilename(filename);
00083 std::string prefix = "";
00084
00085 if (Directory::isDirectory(filename)) {
00086 prefix = location;
00087
00088 location.append("/theme.cfg");
00089 if (!Directory::isRegularFile(location)) {
00090 cerr<<"Error loading theme file "<<location<<": not a regular file"<<endl;
00091 return false;
00092 }
00093 } else {
00094
00095 prefix = location.substr(0, location.find_last_of('/'));
00096 }
00097
00098 if (!m_database.load(location.c_str()))
00099 return false;
00100
00101
00102 if (m_themelocation != "") {
00103 Image::removeSearchPath(m_themelocation);
00104 m_themelocation.append("/pixmaps");
00105 Image::removeSearchPath(m_themelocation);
00106 }
00107
00108 m_themelocation = prefix;
00109
00110 location = prefix;
00111 Image::addSearchPath(location);
00112 location.append("/pixmaps");
00113 Image::addSearchPath(location);
00114
00115
00116 ThemeList::iterator theme_it = m_themelist.begin();
00117 const ThemeList::iterator theme_it_end = m_themelist.end();
00118 for (; theme_it != theme_it_end; ++theme_it) {
00119 if (screen_num < 0)
00120 loadTheme(**theme_it);
00121 else if (screen_num == (*theme_it)->screenNum())
00122 loadTheme(**theme_it);
00123
00124 }
00125
00126 theme_it = m_themelist.begin();
00127 for (; theme_it != theme_it_end; ++theme_it) {
00128
00129 (*theme_it)->reconfigTheme();
00130 (*theme_it)->reconfigSig().notify();
00131 }
00132 return true;
00133 }
00134
00135 void ThemeManager::loadTheme(Theme &tm) {
00136 std::list<ThemeItem_base *>::iterator i = tm.itemList().begin();
00137 std::list<ThemeItem_base *>::iterator i_end = tm.itemList().end();
00138 for (; i != i_end; ++i) {
00139 ThemeItem_base *resource = *i;
00140 if (!loadItem(*resource)) {
00141
00142 if (!tm.fallback(*resource)) {
00143 if (verbose())
00144 cerr<<"Failed to read theme item: "<<resource->name()<<endl;
00145 resource->setDefaultValue();
00146 }
00147 }
00148 }
00149
00150 }
00151
00152 bool ThemeManager::loadItem(ThemeItem_base &resource) {
00153 return loadItem(resource, resource.name(), resource.altName());
00154 }
00155
00157 bool ThemeManager::loadItem(ThemeItem_base &resource, const std::string &name, const std::string &alt_name) {
00158 XrmValue value;
00159 char *value_type;
00160
00161 if (XrmGetResource(*m_database, name.c_str(),
00162 alt_name.c_str(), &value_type, &value)) {
00163 resource.setFromString(value.addr);
00164 resource.load();
00165 } else
00166 return false;
00167
00168 return true;
00169 }
00170
00171 std::string ThemeManager::resourceValue(const std::string &name, const std::string &altname) {
00172 XrmValue value;
00173 char *value_type;
00174
00175 if (*m_database != 0 && XrmGetResource(*m_database, name.c_str(),
00176 altname.c_str(), &value_type, &value) && value.addr != 0) {
00177 return string(value.addr);
00178 }
00179 return "";
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 };