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