gameui

changeset 5:5a84873185ff tip

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
files Makefile include/button.h include/event.h include/goatkit.h include/label.h include/vec.h include/widget.h src/button.cc src/event.h src/label.cc src/theme.cc src/theme.h src/vec.h src/widget.cc themes/simple/Makefile themes/simple/simple.cc
diffstat 16 files changed, 248 insertions(+), 86 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Fri Mar 21 21:45:37 2014 +0200
     1.2 +++ b/Makefile	Sat Mar 22 01:50:01 2014 +0200
     1.3 @@ -1,15 +1,25 @@
     1.4  src = test.cc $(wildcard src/*.cc)
     1.5  obj = $(src:.cc=.o)
     1.6 +dep = $(obj:.o=.d)
     1.7  
     1.8  bin = test
     1.9  
    1.10  CFLAGS = -pedantic -Wall -g -Iinclude -Isrc
    1.11  CXXFLAGS = $(CFLAGS)
    1.12 -LDFLAGS = -lGL -lGLU -lglut -lpthread
    1.13 +LDFLAGS = -lGL -lGLU -lglut -lpthread -ldl
    1.14  
    1.15  $(bin): $(obj)
    1.16  	$(CXX) -o $@ $(obj) $(LDFLAGS)
    1.17  
    1.18 +-include $(dep)
    1.19 +
    1.20 +
    1.21 +%.d: %.c
    1.22 +	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    1.23 +
    1.24 +%.d: %.cc
    1.25 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    1.26 +
    1.27  .PHONY: clean
    1.28  clean:
    1.29 -	rm -f $(obj) $(bin)
    1.30 +	rm -f $(obj) $(bin) $(dep)
     2.1 --- a/include/button.h	Fri Mar 21 21:45:37 2014 +0200
     2.2 +++ b/include/button.h	Sat Mar 22 01:50:01 2014 +0200
     2.3 @@ -14,6 +14,8 @@
     2.4  public:
     2.5  	Button();
     2.6  	virtual ~Button();
     2.7 +
     2.8 +	virtual const char *get_type_name() const;
     2.9  };
    2.10  
    2.11  }	// namespace goatkit
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/include/event.h	Sat Mar 22 01:50:01 2014 +0200
     3.3 @@ -0,0 +1,45 @@
     3.4 +#ifndef EVENT_H_
     3.5 +#define EVENT_H_
     3.6 +
     3.7 +#include "vec.h"
     3.8 +
     3.9 +namespace goatkit {
    3.10 +
    3.11 +enum EventType {
    3.12 +	EV_MOUSE_BUTTON,
    3.13 +	EV_MOUSE_MOTION,
    3.14 +	EV_MOUSE_FOCUS,
    3.15 +	EV_KEY
    3.16 +};
    3.17 +
    3.18 +struct ButtonEvent {
    3.19 +	Vec2 pos;
    3.20 +	int button;
    3.21 +	bool press;
    3.22 +};
    3.23 +
    3.24 +struct MotionEvent {
    3.25 +	Vec2 pos;
    3.26 +};
    3.27 +
    3.28 +struct FocusEvent {
    3.29 +	bool enter;
    3.30 +};
    3.31 +
    3.32 +struct KeyEvent {
    3.33 +	int key;
    3.34 +	bool press;
    3.35 +};
    3.36 +
    3.37 +struct Event {
    3.38 +	EventType type;
    3.39 +
    3.40 +	ButtonEvent button;
    3.41 +	MotionEvent motion;
    3.42 +	FocusEvent focus;
    3.43 +	KeyEvent key;
    3.44 +};
    3.45 +
    3.46 +}	// namespace goatkit
    3.47 +
    3.48 +#endif	// EVENT_H_
     4.1 --- a/include/goatkit.h	Fri Mar 21 21:45:37 2014 +0200
     4.2 +++ b/include/goatkit.h	Sat Mar 22 01:50:01 2014 +0200
     4.3 @@ -4,5 +4,10 @@
     4.4  #include "widget.h"
     4.5  #include "button.h"
     4.6  #include "label.h"
     4.7 +#include "event.h"
     4.8 +
     4.9 +namespace goatkit {
    4.10 +	typedef void (*WidgetDrawFunc)(const Widget*);
    4.11 +}
    4.12  
    4.13  #endif	// GOATKIT_H_
     5.1 --- a/include/label.h	Fri Mar 21 21:45:37 2014 +0200
     5.2 +++ b/include/label.h	Sat Mar 22 01:50:01 2014 +0200
     5.3 @@ -1,17 +1,21 @@
     5.4  #ifndef GOATKIT_LABEL_H_
     5.5  #define GOATKIT_LABEL_H_
     5.6  
     5.7 +#include "widget.h"
     5.8 +
     5.9  namespace goatkit {
    5.10  
    5.11  class LabelImpl;
    5.12  
    5.13 -class Label {
    5.14 +class Label : public Widget {
    5.15  private:
    5.16 -	LabelImpl *impl;
    5.17 +	LabelImpl *label;
    5.18  
    5.19  public:
    5.20  	Label();
    5.21  	virtual ~Label();
    5.22 +
    5.23 +	virtual const char *get_type_name() const;
    5.24  };
    5.25  
    5.26  }	// namespace goatkit
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/include/vec.h	Sat Mar 22 01:50:01 2014 +0200
     6.3 @@ -0,0 +1,16 @@
     6.4 +#ifndef VEC_H_
     6.5 +#define VEC_H_
     6.6 +
     6.7 +namespace goatkit {
     6.8 +
     6.9 +class Vec2 {
    6.10 +public:
    6.11 +	float x, y;
    6.12 +
    6.13 +	Vec2() : x(0), y(0) {}
    6.14 +	Vec2(float xx, float yy) : x(xx), y(yy) {}
    6.15 +};
    6.16 +
    6.17 +}	// namespace goatkit
    6.18 +
    6.19 +#endif	// VEC_H_
     7.1 --- a/include/widget.h	Fri Mar 21 21:45:37 2014 +0200
     7.2 +++ b/include/widget.h	Sat Mar 22 01:50:01 2014 +0200
     7.3 @@ -16,12 +16,12 @@
     7.4  private:
     7.5  	WidgetImpl *widget;
     7.6  
     7.7 -	void set_type_string(const char *type_str);
     7.8 -
     7.9  public:
    7.10  	Widget();
    7.11  	virtual ~Widget();
    7.12  
    7.13 +	virtual const char *get_type_name() const;
    7.14 +
    7.15  	virtual void show();
    7.16  	virtual void hide();
    7.17  	virtual float get_visibility() const;
     8.1 --- a/src/button.cc	Fri Mar 21 21:45:37 2014 +0200
     8.2 +++ b/src/button.cc	Sat Mar 22 01:50:01 2014 +0200
     8.3 @@ -15,4 +15,9 @@
     8.4  	delete button;
     8.5  }
     8.6  
     8.7 +const char *Button::get_type_name() const
     8.8 +{
     8.9 +	return "button";
    8.10 +}
    8.11 +
    8.12  }	// namespace goatkit
     9.1 --- a/src/event.h	Fri Mar 21 21:45:37 2014 +0200
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,45 +0,0 @@
     9.4 -#ifndef EVENT_H_
     9.5 -#define EVENT_H_
     9.6 -
     9.7 -#include "vec.h"
     9.8 -
     9.9 -namespace goatkit {
    9.10 -
    9.11 -enum EventType {
    9.12 -	EV_MOUSE_BUTTON,
    9.13 -	EV_MOUSE_MOTION,
    9.14 -	EV_MOUSE_FOCUS,
    9.15 -	EV_KEY
    9.16 -};
    9.17 -
    9.18 -struct ButtonEvent {
    9.19 -	Vec2 pos;
    9.20 -	int button;
    9.21 -	bool press;
    9.22 -};
    9.23 -
    9.24 -struct MotionEvent {
    9.25 -	Vec2 pos;
    9.26 -};
    9.27 -
    9.28 -struct FocusEvent {
    9.29 -	bool enter;
    9.30 -};
    9.31 -
    9.32 -struct KeyEvent {
    9.33 -	int key;
    9.34 -	bool press;
    9.35 -};
    9.36 -
    9.37 -struct Event {
    9.38 -	EventType type;
    9.39 -
    9.40 -	ButtonEvent button;
    9.41 -	MotionEvent motion;
    9.42 -	FocusEvent focus;
    9.43 -	KeyEvent key;
    9.44 -};
    9.45 -
    9.46 -}	// namespace goatkit
    9.47 -
    9.48 -#endif	// EVENT_H_
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/label.cc	Sat Mar 22 01:50:01 2014 +0200
    10.3 @@ -0,0 +1,23 @@
    10.4 +#include "label.h"
    10.5 +
    10.6 +namespace goatkit {
    10.7 +
    10.8 +struct LabelImpl {
    10.9 +};
   10.10 +
   10.11 +Label::Label()
   10.12 +{
   10.13 +	label = new LabelImpl;
   10.14 +}
   10.15 +
   10.16 +Label::~Label()
   10.17 +{
   10.18 +	delete label;
   10.19 +}
   10.20 +
   10.21 +const char *Label::get_type_name() const
   10.22 +{
   10.23 +	return "label";
   10.24 +}
   10.25 +
   10.26 +}	// namespace goatkit
    11.1 --- a/src/theme.cc	Fri Mar 21 21:45:37 2014 +0200
    11.2 +++ b/src/theme.cc	Sat Mar 22 01:50:01 2014 +0200
    11.3 @@ -1,10 +1,20 @@
    11.4  #include <stdio.h>
    11.5 +#include <vector>
    11.6 +#include <algorithm>
    11.7  #include "theme.h"
    11.8  #include "widget.h"
    11.9  
   11.10  #ifdef WIN32
   11.11  #include <windows.h>
   11.12 +
   11.13 +static void *dlopen(const char *name, int flags);
   11.14 +static void dlclose(void *so);
   11.15 +static void dlsym(void *so, const char *symbol);
   11.16 +#else
   11.17 +#include <unistd.h>
   11.18 +#include <dlfcn.h>
   11.19  #endif
   11.20 +
   11.21  #ifdef __APPLE__
   11.22  #include <OpenGL/gl.h>
   11.23  #else
   11.24 @@ -15,22 +25,89 @@
   11.25  namespace goatkit {
   11.26  
   11.27  Theme *theme;
   11.28 +static std::vector<std::string> search_paths;
   11.29 +
   11.30 +
   11.31 +void add_theme_path(const char *path)
   11.32 +{
   11.33 +	if(!path || !*path) return;
   11.34 +
   11.35 +	std::string s = path;
   11.36 +	int last = s.length() - 1;
   11.37 +	if(s[last] == '/' || s[last] == '\\') {
   11.38 +		s.erase(last);
   11.39 +	}
   11.40 +
   11.41 +	if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) {
   11.42 +		return;
   11.43 +	}
   11.44 +
   11.45 +	search_paths.push_back(s);
   11.46 +}
   11.47  
   11.48  Theme::Theme()
   11.49  {
   11.50  	so = 0;
   11.51  }
   11.52  
   11.53 +Theme::~Theme()
   11.54 +{
   11.55 +	unload();
   11.56 +}
   11.57 +
   11.58 +typedef WidgetDrawFunc (*LookupFunc)(const char*);
   11.59 +
   11.60  bool Theme::load(const char *name)
   11.61  {
   11.62 -	fprintf(stderr, "theme loading not implemented yet!\n");
   11.63 -	return false;
   11.64 +	unload();
   11.65 +
   11.66 +	if(!(so = dlopen(name, RTLD_LAZY))) {
   11.67 +		for(size_t i=0; i<search_paths.size(); i++) {
   11.68 +			std::string path = search_paths[i] + std::string(name);
   11.69 +
   11.70 +			if((so = dlopen(path.c_str(), RTLD_LAZY))) {
   11.71 +				break;
   11.72 +			}
   11.73 +		}
   11.74 +
   11.75 +		if(!so) {
   11.76 +			fprintf(stderr, "%s: failed to load theme plugin: %s\n", __func__, name);
   11.77 +			return false;
   11.78 +		}
   11.79 +	}
   11.80 +
   11.81 +	// loaded the shared object, now get the lookup function
   11.82 +	lookup_theme_draw_func = (LookupFunc)dlsym(so, "get_widget_count");
   11.83 +	if(!lookup_theme_draw_func) {
   11.84 +		fprintf(stderr, "%s: invalid theme plugin %s\n", __func__, name);
   11.85 +		unload();
   11.86 +		return false;
   11.87 +	}
   11.88 +
   11.89 +	return true;
   11.90  }
   11.91  
   11.92 -widget_draw_func Theme::get_draw_func(const char *type) const
   11.93 +void Theme::unload()
   11.94  {
   11.95 -	std::map<std::string, widget_draw_func>::const_iterator it = draw_func.find(type);
   11.96 -	if(it == draw_func.end()) {
   11.97 +	if(so) {
   11.98 +		dlclose(so);
   11.99 +		so = 0;
  11.100 +	}
  11.101 +	func_cache.clear();
  11.102 +}
  11.103 +
  11.104 +WidgetDrawFunc Theme::get_draw_func(const char *type) const
  11.105 +{
  11.106 +	std::map<std::string, WidgetDrawFunc>::const_iterator it = func_cache.find(type);
  11.107 +	if(it == func_cache.end()) {
  11.108 +		// don't have it cached, try to look it up
  11.109 +		WidgetDrawFunc func;
  11.110 +		if(lookup_theme_draw_func && (func = lookup_theme_draw_func(type))) {
  11.111 +			func_cache[type] = func;
  11.112 +			return func;
  11.113 +		}
  11.114 +
  11.115 +		// can't look it up, return the default
  11.116  		return default_draw_func;
  11.117  	}
  11.118  	return it->second;
  11.119 @@ -98,3 +175,21 @@
  11.120  }
  11.121  
  11.122  }	// namespace goatkit
  11.123 +
  11.124 +#ifdef WIN32
  11.125 +// XXX untested
  11.126 +static void *dlopen(const char *name, int flags)
  11.127 +{
  11.128 +	return LoadLibrary(name);
  11.129 +}
  11.130 +
  11.131 +static void dlclose(void *so)
  11.132 +{
  11.133 +	// TODO
  11.134 +}
  11.135 +
  11.136 +static void dlsym(void *so, const char *symbol)
  11.137 +{
  11.138 +	return GetProcAddress(so, symbol);
  11.139 +}
  11.140 +#endif
    12.1 --- a/src/theme.h	Fri Mar 21 21:45:37 2014 +0200
    12.2 +++ b/src/theme.h	Sat Mar 22 01:50:01 2014 +0200
    12.3 @@ -3,27 +3,29 @@
    12.4  
    12.5  #include <string>
    12.6  #include <map>
    12.7 +#include "goatkit.h"
    12.8  
    12.9  namespace goatkit {
   12.10  
   12.11  class Widget;
   12.12  
   12.13 -typedef void (*widget_draw_func)(const Widget*);
   12.14 -
   12.15 +void add_theme_path(const char *path);
   12.16  void default_draw_func(const Widget *w);
   12.17  
   12.18  class Theme {
   12.19  private:
   12.20  	void *so;
   12.21 -	std::map<std::string, widget_draw_func> draw_func;
   12.22 +	WidgetDrawFunc (*lookup_theme_draw_func)(const char*);
   12.23 +	mutable std::map<std::string, WidgetDrawFunc> func_cache;
   12.24  
   12.25  public:
   12.26  	Theme();
   12.27  	~Theme();
   12.28  
   12.29  	bool load(const char *name);
   12.30 +	void unload();
   12.31  
   12.32 -	widget_draw_func get_draw_func(const char *type) const;
   12.33 +	WidgetDrawFunc get_draw_func(const char *type) const;
   12.34  };
   12.35  
   12.36  extern Theme *theme;	// the current theme
    13.1 --- a/src/vec.h	Fri Mar 21 21:45:37 2014 +0200
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,16 +0,0 @@
    13.4 -#ifndef VEC_H_
    13.5 -#define VEC_H_
    13.6 -
    13.7 -namespace goatkit {
    13.8 -
    13.9 -class Vec2 {
   13.10 -public:
   13.11 -	float x, y;
   13.12 -
   13.13 -	Vec2() : x(0), y(0) {}
   13.14 -	Vec2(float xx, float yy) : x(xx), y(yy) {}
   13.15 -};
   13.16 -
   13.17 -}	// namespace goatkit
   13.18 -
   13.19 -#endif	// VEC_H_
    14.1 --- a/src/widget.cc	Fri Mar 21 21:45:37 2014 +0200
    14.2 +++ b/src/widget.cc	Sat Mar 22 01:50:01 2014 +0200
    14.3 @@ -9,7 +9,6 @@
    14.4  namespace goatkit {
    14.5  
    14.6  struct WidgetImpl {
    14.7 -	std::string type_str;
    14.8  	std::string name;
    14.9  	BBox box;
   14.10  
   14.11 @@ -22,10 +21,9 @@
   14.12  	static int widget_count;
   14.13  
   14.14  	widget = new WidgetImpl;
   14.15 -	set_type_string("widget");
   14.16  
   14.17  	std::stringstream sstr;
   14.18 -	sstr << widget->type_str << widget_count++;
   14.19 +	sstr << get_type_name() << widget_count++;
   14.20  	widget->name = sstr.str();
   14.21  
   14.22  	widget->box.bmin = Vec2(0, 0);
   14.23 @@ -43,6 +41,11 @@
   14.24  	delete widget;
   14.25  }
   14.26  
   14.27 +const char *Widget::get_type_name() const
   14.28 +{
   14.29 +	return "widget";
   14.30 +}
   14.31 +
   14.32  void Widget::show()
   14.33  {
   14.34  	widget->visible.change(true);
   14.35 @@ -173,10 +176,10 @@
   14.36  
   14.37  void Widget::draw() const
   14.38  {
   14.39 -	widget_draw_func draw_func = default_draw_func;
   14.40 +	WidgetDrawFunc draw_func = default_draw_func;
   14.41  
   14.42  	if(theme) {
   14.43 -		draw_func = theme->get_draw_func(widget->type_str.c_str());
   14.44 +		draw_func = theme->get_draw_func(get_type_name());
   14.45  	}
   14.46  
   14.47  	draw_func(this);
   14.48 @@ -212,11 +215,6 @@
   14.49  }
   14.50  
   14.51  
   14.52 -void Widget::set_type_string(const char *type_str)
   14.53 -{
   14.54 -	widget->type_str = type_str;
   14.55 -}
   14.56 -
   14.57  /* the event dispatcher generates high-level events (click, etc)
   14.58   * and calls the on_whatever() functions for both low and high-level
   14.59   * events.
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/themes/simple/Makefile	Sat Mar 22 01:50:01 2014 +0200
    15.3 @@ -0,0 +1,12 @@
    15.4 +src = $(wildcard *.cc)
    15.5 +obj = $(src:.cc=.o)
    15.6 +lib_so = simple.so
    15.7 +
    15.8 +CXXFLAGS = -pedantic -Wall -g -I../../include
    15.9 +
   15.10 +$(lib_so): $(obj)
   15.11 +	$(CXX) -o $@ -shared $(obj) $(LDFLAGS)
   15.12 +
   15.13 +.PHONY: clean
   15.14 +clean:
   15.15 +	rm -f $(obj) $(bin)
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/themes/simple/simple.cc	Sat Mar 22 01:50:01 2014 +0200
    16.3 @@ -0,0 +1,6 @@
    16.4 +#include "goatkit.h"
    16.5 +
    16.6 +extern "C" goatkit::WidgetDrawFunc get_widget_func(const char *name)
    16.7 +{
    16.8 +	return 0;
    16.9 +}