gameui

diff src/widget.cc @ 3:f1014234dece

transitions in gui elements are awesome :)
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 21 Mar 2014 03:37:16 +0200
parents e5b1525084f7
children e0916bb20b7f
line diff
     1.1 --- a/src/widget.cc	Thu Mar 20 07:03:58 2014 +0200
     1.2 +++ b/src/widget.cc	Fri Mar 21 03:37:16 2014 +0200
     1.3 @@ -1,12 +1,15 @@
     1.4 +#include <stdio.h>
     1.5 +#include <math.h>
     1.6  #include <string>
     1.7  #include <sstream>
     1.8  #include "widget.h"
     1.9  #include "boolanm.h"
    1.10 +#include "theme.h"
    1.11  
    1.12 -using namespace gameui;
    1.13 +namespace gameui {
    1.14  
    1.15  struct WidgetImpl {
    1.16 -	std::string name_prefix;
    1.17 +	std::string type_str;
    1.18  	std::string name;
    1.19  	BBox box;
    1.20  
    1.21 @@ -15,96 +18,249 @@
    1.22  
    1.23  
    1.24  Widget::Widget()
    1.25 -	: name_prefix("widget")
    1.26  {
    1.27  	static int widget_count;
    1.28  
    1.29 +	widget = new WidgetImpl;
    1.30 +	set_type_string("widget");
    1.31 +
    1.32  	std::stringstream sstr;
    1.33 -	sstr << name_prefix << widget_count++;
    1.34 -	name = sstr.str();
    1.35 +	sstr << widget->type_str << widget_count++;
    1.36 +	widget->name = sstr.str();
    1.37  
    1.38 -	box.bmin = Vec2(0, 0);
    1.39 -	box.bmax = Vec2(1, 1);
    1.40 +	widget->box.bmin = Vec2(0, 0);
    1.41 +	widget->box.bmax = Vec2(1, 1);
    1.42  
    1.43 -	vis_st = VST_VISIBLE;
    1.44 -	act_st = AST_ACTIVE;
    1.45 +	widget->visible.set(true);
    1.46 +	widget->active.set(true);
    1.47  
    1.48 -	vis = act = 1.0;
    1.49 +	widget->hover.set_transition_duration(250);
    1.50 +	widget->press.set_transition_duration(50);
    1.51  }
    1.52  
    1.53  Widget::~Widget()
    1.54  {
    1.55 +	delete widget;
    1.56  }
    1.57  
    1.58  void Widget::show()
    1.59  {
    1.60 -	if(vis_st == VST_EASEVISIBLE || vis_st == VST_EASEIN) {
    1.61 -		return;
    1.62 -	}
    1.63 -
    1.64 -	vis_st = VST_EASEIN;
    1.65 -	vis_start_time = get_cur_time();
    1.66 +	widget->visible.change(true);
    1.67  }
    1.68  
    1.69  void Widget::hide()
    1.70  {
    1.71 -	if(vis_st == VST_EASEHIDDEN || vis_st == VST_EASEOUT) {
    1.72 -		return;
    1.73 -	}
    1.74 -
    1.75 -	vis_st = VST_EASEOUT;
    1.76 -	vis_start_time = get_cur_time();
    1.77 +	widget->visible.change(false);
    1.78  }
    1.79  
    1.80  float Widget::get_visibility() const
    1.81  {
    1.82 -	switch(vis_st) {
    1.83 -	case VST_EASEIN:
    1.84 -		vis = (get_cur_time() - vis_start_time) / gameui::ease_time;
    1.85 -		if(vis < 0.0) vis = 0.0;
    1.86 -		if(vis > 1.0) vis = 1.0;
    1.87 -		break;
    1.88 +	return widget->visible.get_value();
    1.89 +}
    1.90  
    1.91 -	case VST_EASEOUT:
    1.92 -		vis = 1.0 - (get_cur_time() - vis_start_time) / gameui::ease_time;
    1.93 -		if(vis < 0.0) vis = 0.0;
    1.94 -		if(vis > 1.0) vis = 1.0;
    1.95 -		break;
    1.96 -
    1.97 -	case VST_HIDDEN:
    1.98 -		vis = 0.0;
    1.99 -		break;
   1.100 -
   1.101 -	case VST_VISIBLE:
   1.102 -		vis = 1.0;
   1.103 -		break;
   1.104 -	}
   1.105 -
   1.106 -	return vis;
   1.107 +bool Widget::is_visible() const
   1.108 +{
   1.109 +	return widget->visible.get_state();
   1.110  }
   1.111  
   1.112  void Widget::activate()
   1.113  {
   1.114 +	widget->active.change(true);
   1.115  }
   1.116  
   1.117 -#ifdef WIN32
   1.118 -long gameui::get_cur_time()
   1.119 +void Widget::deactivate()
   1.120  {
   1.121 -	return GetTickCount();
   1.122 +	widget->active.change(false);
   1.123  }
   1.124 -#endif
   1.125  
   1.126 -#if defined(__unix__) || defined(__APPLE__)
   1.127 -long gameui::get_cur_time()
   1.128 +float Widget::get_active() const
   1.129  {
   1.130 -	struct timeval tv;
   1.131 -	static struct timeval tv0;
   1.132 +	return widget->active.get_value();
   1.133 +}
   1.134  
   1.135 -	gettimeofday(&tv, 0);
   1.136 -	if(tv0.tv_sec == 0 && tv0.tv_msec == 0) {
   1.137 -		tv0 = tv;
   1.138 -		return 0;
   1.139 +bool Widget::is_active() const
   1.140 +{
   1.141 +	return widget->active.get_state();
   1.142 +}
   1.143 +
   1.144 +void Widget::press()
   1.145 +{
   1.146 +	widget->press.change(true);
   1.147 +}
   1.148 +
   1.149 +void Widget::release()
   1.150 +{
   1.151 +	widget->press.change(false);
   1.152 +}
   1.153 +
   1.154 +float Widget::get_pressed() const
   1.155 +{
   1.156 +	return widget->press.get_value();
   1.157 +}
   1.158 +
   1.159 +bool Widget::is_pressed() const
   1.160 +{
   1.161 +	return widget->press.get_state();
   1.162 +}
   1.163 +
   1.164 +void Widget::mousein()
   1.165 +{
   1.166 +	widget->hover.change(true);
   1.167 +}
   1.168 +
   1.169 +void Widget::mouseout()
   1.170 +{
   1.171 +	widget->hover.change(false);
   1.172 +}
   1.173 +
   1.174 +float Widget::get_under_mouse() const
   1.175 +{
   1.176 +	return widget->hover.get_value();
   1.177 +}
   1.178 +
   1.179 +bool Widget::is_under_mouse() const
   1.180 +{
   1.181 +	return widget->hover.get_state();
   1.182 +}
   1.183 +
   1.184 +void Widget::set_position(float x, float y)
   1.185 +{
   1.186 +	set_position(Vec2(x, y));
   1.187 +}
   1.188 +
   1.189 +void Widget::set_position(const Vec2 &pos)
   1.190 +{
   1.191 +	Vec2 sz = get_size();
   1.192 +
   1.193 +	widget->box.bmin = pos;
   1.194 +	widget->box.bmax.x = pos.x + sz.x;
   1.195 +	widget->box.bmax.y = pos.y + sz.y;
   1.196 +}
   1.197 +
   1.198 +const Vec2 &Widget::get_position() const
   1.199 +{
   1.200 +	return widget->box.bmin;
   1.201 +}
   1.202 +
   1.203 +void Widget::set_size(float x, float y)
   1.204 +{
   1.205 +	set_size(Vec2(x, y));
   1.206 +}
   1.207 +
   1.208 +void Widget::set_size(const Vec2 &sz)
   1.209 +{
   1.210 +	widget->box.bmax.x = widget->box.bmin.x + sz.x;
   1.211 +	widget->box.bmax.y = widget->box.bmin.y + sz.y;
   1.212 +}
   1.213 +
   1.214 +const Vec2 Widget::get_size() const
   1.215 +{
   1.216 +	return Vec2(widget->box.bmax.x - widget->box.bmin.x,
   1.217 +			widget->box.bmax.y - widget->box.bmin.y);
   1.218 +}
   1.219 +
   1.220 +
   1.221 +const BBox &Widget::get_box() const
   1.222 +{
   1.223 +	return widget->box;
   1.224 +}
   1.225 +
   1.226 +bool Widget::hit_test(const Vec2 &pt) const
   1.227 +{
   1.228 +	return pt.x >= widget->box.bmin.x && pt.x < widget->box.bmax.x &&
   1.229 +		pt.y >= widget->box.bmin.y && pt.y < widget->box.bmax.y;
   1.230 +}
   1.231 +
   1.232 +void Widget::draw() const
   1.233 +{
   1.234 +	widget_draw_func draw_func = default_draw_func;
   1.235 +
   1.236 +	if(theme) {
   1.237 +		draw_func = theme->get_draw_func(widget->type_str.c_str());
   1.238  	}
   1.239 -	return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
   1.240 +
   1.241 +	draw_func(this);
   1.242  }
   1.243 -#endif
   1.244 +
   1.245 +// dummy event handlers
   1.246 +void Widget::on_mouse_button(const ButtonEvent &ev)
   1.247 +{
   1.248 +}
   1.249 +
   1.250 +void Widget::on_mouse_motion(const MotionEvent &ev)
   1.251 +{
   1.252 +}
   1.253 +
   1.254 +void Widget::on_mouse_focus(const FocusEvent &ev)
   1.255 +{
   1.256 +}
   1.257 +
   1.258 +void Widget::on_key(const KeyEvent &ev)
   1.259 +{
   1.260 +}
   1.261 +
   1.262 +void Widget::on_click()
   1.263 +{
   1.264 +}
   1.265 +
   1.266 +void Widget::on_double_click()
   1.267 +{
   1.268 +}
   1.269 +
   1.270 +void Widget::on_change()
   1.271 +{
   1.272 +}
   1.273 +
   1.274 +
   1.275 +void Widget::set_type_string(const char *type_str)
   1.276 +{
   1.277 +	widget->type_str = type_str;
   1.278 +}
   1.279 +
   1.280 +/* the event dispatcher generates high-level events (click, etc)
   1.281 + * and calls the on_whatever() functions for both low and high-level
   1.282 + * events.
   1.283 + * The on_whatever functions are called *after* any other actions performed
   1.284 + * here, to give subclasses the opportunity to override them easily, by
   1.285 + * overriding the on_ functions, without having to override handle_event itself
   1.286 + */
   1.287 +// TODO also call callbacks here I guess...
   1.288 +void Widget::handle_event(const Event &ev)
   1.289 +{
   1.290 +	switch(ev.type) {
   1.291 +	case EV_MOUSE_BUTTON:
   1.292 +		if(ev.button.press) {
   1.293 +			press();
   1.294 +		} else {
   1.295 +			if(is_pressed()) {
   1.296 +				on_click();
   1.297 +			}
   1.298 +			release();
   1.299 +		}
   1.300 +		on_mouse_button(ev.button);
   1.301 +		break;
   1.302 +
   1.303 +	case EV_MOUSE_MOTION:
   1.304 +		on_mouse_motion(ev.motion);
   1.305 +		break;
   1.306 +
   1.307 +	case EV_MOUSE_FOCUS:
   1.308 +		if(ev.focus.enter) {
   1.309 +			mousein();
   1.310 +		} else {
   1.311 +			mouseout();
   1.312 +		}
   1.313 +		on_mouse_focus(ev.focus);
   1.314 +		break;
   1.315 +
   1.316 +	case EV_KEY:
   1.317 +		on_key(ev.key);
   1.318 +		break;
   1.319 +
   1.320 +	default:
   1.321 +		fprintf(stderr, "%s: unknown event id: %d\n", __func__, ev.type);
   1.322 +	}
   1.323 +}
   1.324 +
   1.325 +
   1.326 +}	// namespace gameui