gameui
diff src/theme.cc @ 5:5a84873185ff
rudimentary theme plugin system and other minor fixes
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 22 Mar 2014 01:50:01 +0200 |
parents | e0916bb20b7f |
children |
line diff
1.1 --- a/src/theme.cc Fri Mar 21 21:45:37 2014 +0200 1.2 +++ b/src/theme.cc Sat Mar 22 01:50:01 2014 +0200 1.3 @@ -1,10 +1,20 @@ 1.4 #include <stdio.h> 1.5 +#include <vector> 1.6 +#include <algorithm> 1.7 #include "theme.h" 1.8 #include "widget.h" 1.9 1.10 #ifdef WIN32 1.11 #include <windows.h> 1.12 + 1.13 +static void *dlopen(const char *name, int flags); 1.14 +static void dlclose(void *so); 1.15 +static void dlsym(void *so, const char *symbol); 1.16 +#else 1.17 +#include <unistd.h> 1.18 +#include <dlfcn.h> 1.19 #endif 1.20 + 1.21 #ifdef __APPLE__ 1.22 #include <OpenGL/gl.h> 1.23 #else 1.24 @@ -15,22 +25,89 @@ 1.25 namespace goatkit { 1.26 1.27 Theme *theme; 1.28 +static std::vector<std::string> search_paths; 1.29 + 1.30 + 1.31 +void add_theme_path(const char *path) 1.32 +{ 1.33 + if(!path || !*path) return; 1.34 + 1.35 + std::string s = path; 1.36 + int last = s.length() - 1; 1.37 + if(s[last] == '/' || s[last] == '\\') { 1.38 + s.erase(last); 1.39 + } 1.40 + 1.41 + if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) { 1.42 + return; 1.43 + } 1.44 + 1.45 + search_paths.push_back(s); 1.46 +} 1.47 1.48 Theme::Theme() 1.49 { 1.50 so = 0; 1.51 } 1.52 1.53 +Theme::~Theme() 1.54 +{ 1.55 + unload(); 1.56 +} 1.57 + 1.58 +typedef WidgetDrawFunc (*LookupFunc)(const char*); 1.59 + 1.60 bool Theme::load(const char *name) 1.61 { 1.62 - fprintf(stderr, "theme loading not implemented yet!\n"); 1.63 - return false; 1.64 + unload(); 1.65 + 1.66 + if(!(so = dlopen(name, RTLD_LAZY))) { 1.67 + for(size_t i=0; i<search_paths.size(); i++) { 1.68 + std::string path = search_paths[i] + std::string(name); 1.69 + 1.70 + if((so = dlopen(path.c_str(), RTLD_LAZY))) { 1.71 + break; 1.72 + } 1.73 + } 1.74 + 1.75 + if(!so) { 1.76 + fprintf(stderr, "%s: failed to load theme plugin: %s\n", __func__, name); 1.77 + return false; 1.78 + } 1.79 + } 1.80 + 1.81 + // loaded the shared object, now get the lookup function 1.82 + lookup_theme_draw_func = (LookupFunc)dlsym(so, "get_widget_count"); 1.83 + if(!lookup_theme_draw_func) { 1.84 + fprintf(stderr, "%s: invalid theme plugin %s\n", __func__, name); 1.85 + unload(); 1.86 + return false; 1.87 + } 1.88 + 1.89 + return true; 1.90 } 1.91 1.92 -widget_draw_func Theme::get_draw_func(const char *type) const 1.93 +void Theme::unload() 1.94 { 1.95 - std::map<std::string, widget_draw_func>::const_iterator it = draw_func.find(type); 1.96 - if(it == draw_func.end()) { 1.97 + if(so) { 1.98 + dlclose(so); 1.99 + so = 0; 1.100 + } 1.101 + func_cache.clear(); 1.102 +} 1.103 + 1.104 +WidgetDrawFunc Theme::get_draw_func(const char *type) const 1.105 +{ 1.106 + std::map<std::string, WidgetDrawFunc>::const_iterator it = func_cache.find(type); 1.107 + if(it == func_cache.end()) { 1.108 + // don't have it cached, try to look it up 1.109 + WidgetDrawFunc func; 1.110 + if(lookup_theme_draw_func && (func = lookup_theme_draw_func(type))) { 1.111 + func_cache[type] = func; 1.112 + return func; 1.113 + } 1.114 + 1.115 + // can't look it up, return the default 1.116 return default_draw_func; 1.117 } 1.118 return it->second; 1.119 @@ -98,3 +175,21 @@ 1.120 } 1.121 1.122 } // namespace goatkit 1.123 + 1.124 +#ifdef WIN32 1.125 +// XXX untested 1.126 +static void *dlopen(const char *name, int flags) 1.127 +{ 1.128 + return LoadLibrary(name); 1.129 +} 1.130 + 1.131 +static void dlclose(void *so) 1.132 +{ 1.133 + // TODO 1.134 +} 1.135 + 1.136 +static void dlsym(void *so, const char *symbol) 1.137 +{ 1.138 + return GetProcAddress(so, symbol); 1.139 +} 1.140 +#endif