# HG changeset patch # User John Tsiombikas # Date 1395445801 -7200 # Node ID 5a84873185ff87da28c3a71d9244d34e4e749af2 # Parent e0916bb20b7f3ad4eb3896c0f794c7d1d5acc390 rudimentary theme plugin system and other minor fixes diff -r e0916bb20b7f -r 5a84873185ff Makefile --- a/Makefile Fri Mar 21 21:45:37 2014 +0200 +++ b/Makefile Sat Mar 22 01:50:01 2014 +0200 @@ -1,15 +1,25 @@ src = test.cc $(wildcard src/*.cc) obj = $(src:.cc=.o) +dep = $(obj:.o=.d) bin = test CFLAGS = -pedantic -Wall -g -Iinclude -Isrc CXXFLAGS = $(CFLAGS) -LDFLAGS = -lGL -lGLU -lglut -lpthread +LDFLAGS = -lGL -lGLU -lglut -lpthread -ldl $(bin): $(obj) $(CXX) -o $@ $(obj) $(LDFLAGS) +-include $(dep) + + +%.d: %.c + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +%.d: %.cc + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ + .PHONY: clean clean: - rm -f $(obj) $(bin) + rm -f $(obj) $(bin) $(dep) diff -r e0916bb20b7f -r 5a84873185ff include/button.h --- a/include/button.h Fri Mar 21 21:45:37 2014 +0200 +++ b/include/button.h Sat Mar 22 01:50:01 2014 +0200 @@ -14,6 +14,8 @@ public: Button(); virtual ~Button(); + + virtual const char *get_type_name() const; }; } // namespace goatkit diff -r e0916bb20b7f -r 5a84873185ff include/event.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/event.h Sat Mar 22 01:50:01 2014 +0200 @@ -0,0 +1,45 @@ +#ifndef EVENT_H_ +#define EVENT_H_ + +#include "vec.h" + +namespace goatkit { + +enum EventType { + EV_MOUSE_BUTTON, + EV_MOUSE_MOTION, + EV_MOUSE_FOCUS, + EV_KEY +}; + +struct ButtonEvent { + Vec2 pos; + int button; + bool press; +}; + +struct MotionEvent { + Vec2 pos; +}; + +struct FocusEvent { + bool enter; +}; + +struct KeyEvent { + int key; + bool press; +}; + +struct Event { + EventType type; + + ButtonEvent button; + MotionEvent motion; + FocusEvent focus; + KeyEvent key; +}; + +} // namespace goatkit + +#endif // EVENT_H_ diff -r e0916bb20b7f -r 5a84873185ff include/goatkit.h --- a/include/goatkit.h Fri Mar 21 21:45:37 2014 +0200 +++ b/include/goatkit.h Sat Mar 22 01:50:01 2014 +0200 @@ -4,5 +4,10 @@ #include "widget.h" #include "button.h" #include "label.h" +#include "event.h" + +namespace goatkit { + typedef void (*WidgetDrawFunc)(const Widget*); +} #endif // GOATKIT_H_ diff -r e0916bb20b7f -r 5a84873185ff include/label.h --- a/include/label.h Fri Mar 21 21:45:37 2014 +0200 +++ b/include/label.h Sat Mar 22 01:50:01 2014 +0200 @@ -1,17 +1,21 @@ #ifndef GOATKIT_LABEL_H_ #define GOATKIT_LABEL_H_ +#include "widget.h" + namespace goatkit { class LabelImpl; -class Label { +class Label : public Widget { private: - LabelImpl *impl; + LabelImpl *label; public: Label(); virtual ~Label(); + + virtual const char *get_type_name() const; }; } // namespace goatkit diff -r e0916bb20b7f -r 5a84873185ff include/vec.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vec.h Sat Mar 22 01:50:01 2014 +0200 @@ -0,0 +1,16 @@ +#ifndef VEC_H_ +#define VEC_H_ + +namespace goatkit { + +class Vec2 { +public: + float x, y; + + Vec2() : x(0), y(0) {} + Vec2(float xx, float yy) : x(xx), y(yy) {} +}; + +} // namespace goatkit + +#endif // VEC_H_ diff -r e0916bb20b7f -r 5a84873185ff include/widget.h --- a/include/widget.h Fri Mar 21 21:45:37 2014 +0200 +++ b/include/widget.h Sat Mar 22 01:50:01 2014 +0200 @@ -16,12 +16,12 @@ private: WidgetImpl *widget; - void set_type_string(const char *type_str); - public: Widget(); virtual ~Widget(); + virtual const char *get_type_name() const; + virtual void show(); virtual void hide(); virtual float get_visibility() const; diff -r e0916bb20b7f -r 5a84873185ff src/button.cc --- a/src/button.cc Fri Mar 21 21:45:37 2014 +0200 +++ b/src/button.cc Sat Mar 22 01:50:01 2014 +0200 @@ -15,4 +15,9 @@ delete button; } +const char *Button::get_type_name() const +{ + return "button"; +} + } // namespace goatkit diff -r e0916bb20b7f -r 5a84873185ff src/event.h --- a/src/event.h Fri Mar 21 21:45:37 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#ifndef EVENT_H_ -#define EVENT_H_ - -#include "vec.h" - -namespace goatkit { - -enum EventType { - EV_MOUSE_BUTTON, - EV_MOUSE_MOTION, - EV_MOUSE_FOCUS, - EV_KEY -}; - -struct ButtonEvent { - Vec2 pos; - int button; - bool press; -}; - -struct MotionEvent { - Vec2 pos; -}; - -struct FocusEvent { - bool enter; -}; - -struct KeyEvent { - int key; - bool press; -}; - -struct Event { - EventType type; - - ButtonEvent button; - MotionEvent motion; - FocusEvent focus; - KeyEvent key; -}; - -} // namespace goatkit - -#endif // EVENT_H_ diff -r e0916bb20b7f -r 5a84873185ff src/label.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/label.cc Sat Mar 22 01:50:01 2014 +0200 @@ -0,0 +1,23 @@ +#include "label.h" + +namespace goatkit { + +struct LabelImpl { +}; + +Label::Label() +{ + label = new LabelImpl; +} + +Label::~Label() +{ + delete label; +} + +const char *Label::get_type_name() const +{ + return "label"; +} + +} // namespace goatkit diff -r e0916bb20b7f -r 5a84873185ff src/theme.cc --- a/src/theme.cc Fri Mar 21 21:45:37 2014 +0200 +++ b/src/theme.cc Sat Mar 22 01:50:01 2014 +0200 @@ -1,10 +1,20 @@ #include +#include +#include #include "theme.h" #include "widget.h" #ifdef WIN32 #include + +static void *dlopen(const char *name, int flags); +static void dlclose(void *so); +static void dlsym(void *so, const char *symbol); +#else +#include +#include #endif + #ifdef __APPLE__ #include #else @@ -15,22 +25,89 @@ namespace goatkit { Theme *theme; +static std::vector search_paths; + + +void add_theme_path(const char *path) +{ + if(!path || !*path) return; + + std::string s = path; + int last = s.length() - 1; + if(s[last] == '/' || s[last] == '\\') { + s.erase(last); + } + + if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) { + return; + } + + search_paths.push_back(s); +} Theme::Theme() { so = 0; } +Theme::~Theme() +{ + unload(); +} + +typedef WidgetDrawFunc (*LookupFunc)(const char*); + bool Theme::load(const char *name) { - fprintf(stderr, "theme loading not implemented yet!\n"); - return false; + unload(); + + if(!(so = dlopen(name, RTLD_LAZY))) { + for(size_t i=0; i::const_iterator it = draw_func.find(type); - if(it == draw_func.end()) { + if(so) { + dlclose(so); + so = 0; + } + func_cache.clear(); +} + +WidgetDrawFunc Theme::get_draw_func(const char *type) const +{ + std::map::const_iterator it = func_cache.find(type); + if(it == func_cache.end()) { + // don't have it cached, try to look it up + WidgetDrawFunc func; + if(lookup_theme_draw_func && (func = lookup_theme_draw_func(type))) { + func_cache[type] = func; + return func; + } + + // can't look it up, return the default return default_draw_func; } return it->second; @@ -98,3 +175,21 @@ } } // namespace goatkit + +#ifdef WIN32 +// XXX untested +static void *dlopen(const char *name, int flags) +{ + return LoadLibrary(name); +} + +static void dlclose(void *so) +{ + // TODO +} + +static void dlsym(void *so, const char *symbol) +{ + return GetProcAddress(so, symbol); +} +#endif diff -r e0916bb20b7f -r 5a84873185ff src/theme.h --- a/src/theme.h Fri Mar 21 21:45:37 2014 +0200 +++ b/src/theme.h Sat Mar 22 01:50:01 2014 +0200 @@ -3,27 +3,29 @@ #include #include +#include "goatkit.h" namespace goatkit { class Widget; -typedef void (*widget_draw_func)(const Widget*); - +void add_theme_path(const char *path); void default_draw_func(const Widget *w); class Theme { private: void *so; - std::map draw_func; + WidgetDrawFunc (*lookup_theme_draw_func)(const char*); + mutable std::map func_cache; public: Theme(); ~Theme(); bool load(const char *name); + void unload(); - widget_draw_func get_draw_func(const char *type) const; + WidgetDrawFunc get_draw_func(const char *type) const; }; extern Theme *theme; // the current theme diff -r e0916bb20b7f -r 5a84873185ff src/vec.h --- a/src/vec.h Fri Mar 21 21:45:37 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#ifndef VEC_H_ -#define VEC_H_ - -namespace goatkit { - -class Vec2 { -public: - float x, y; - - Vec2() : x(0), y(0) {} - Vec2(float xx, float yy) : x(xx), y(yy) {} -}; - -} // namespace goatkit - -#endif // VEC_H_ diff -r e0916bb20b7f -r 5a84873185ff src/widget.cc --- a/src/widget.cc Fri Mar 21 21:45:37 2014 +0200 +++ b/src/widget.cc Sat Mar 22 01:50:01 2014 +0200 @@ -9,7 +9,6 @@ namespace goatkit { struct WidgetImpl { - std::string type_str; std::string name; BBox box; @@ -22,10 +21,9 @@ static int widget_count; widget = new WidgetImpl; - set_type_string("widget"); std::stringstream sstr; - sstr << widget->type_str << widget_count++; + sstr << get_type_name() << widget_count++; widget->name = sstr.str(); widget->box.bmin = Vec2(0, 0); @@ -43,6 +41,11 @@ delete widget; } +const char *Widget::get_type_name() const +{ + return "widget"; +} + void Widget::show() { widget->visible.change(true); @@ -173,10 +176,10 @@ void Widget::draw() const { - widget_draw_func draw_func = default_draw_func; + WidgetDrawFunc draw_func = default_draw_func; if(theme) { - draw_func = theme->get_draw_func(widget->type_str.c_str()); + draw_func = theme->get_draw_func(get_type_name()); } draw_func(this); @@ -212,11 +215,6 @@ } -void Widget::set_type_string(const char *type_str) -{ - widget->type_str = type_str; -} - /* the event dispatcher generates high-level events (click, etc) * and calls the on_whatever() functions for both low and high-level * events. diff -r e0916bb20b7f -r 5a84873185ff themes/simple/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/simple/Makefile Sat Mar 22 01:50:01 2014 +0200 @@ -0,0 +1,12 @@ +src = $(wildcard *.cc) +obj = $(src:.cc=.o) +lib_so = simple.so + +CXXFLAGS = -pedantic -Wall -g -I../../include + +$(lib_so): $(obj) + $(CXX) -o $@ -shared $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) diff -r e0916bb20b7f -r 5a84873185ff themes/simple/simple.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/simple/simple.cc Sat Mar 22 01:50:01 2014 +0200 @@ -0,0 +1,6 @@ +#include "goatkit.h" + +extern "C" goatkit::WidgetDrawFunc get_widget_func(const char *name) +{ + return 0; +}