istereo2

diff libs/goatkit/widget.cc @ 6:3bccfc7d10fe

goatkit is drawing
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 23 Sep 2015 05:44:58 +0300
parents
children 018f997dc646
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/goatkit/widget.cc	Wed Sep 23 05:44:58 2015 +0300
     1.3 @@ -0,0 +1,379 @@
     1.4 +/*
     1.5 +GoatKit - a themable/animated widget toolkit for games
     1.6 +Copyright (C) 2014  John Tsiombikas <nuclear@member.fsf.org>
     1.7 +
     1.8 +This program is free software: you can redistribute it and/or modify
     1.9 +it under the terms of the GNU Lesser General Public License as published by
    1.10 +the Free Software Foundation, either version 3 of the License, or
    1.11 +(at your option) any later version.
    1.12 +
    1.13 +This program is distributed in the hope that it will be useful,
    1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +GNU Lesser General Public License for more details.
    1.17 +
    1.18 +You should have received a copy of the GNU Lesser General Public License
    1.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.20 +*/
    1.21 +#include <stdio.h>
    1.22 +#include <string.h>
    1.23 +#include <math.h>
    1.24 +#include <string>
    1.25 +#include <sstream>
    1.26 +#include "widget.h"
    1.27 +#include "boolanm.h"
    1.28 +#include "theme.h"
    1.29 +#include "screen.h"
    1.30 +
    1.31 +namespace goatkit {
    1.32 +
    1.33 +struct WidgetImpl {
    1.34 +	Screen *scr;
    1.35 +	std::string name, text;
    1.36 +	BBox box;
    1.37 +
    1.38 +	BoolAnim visible, active, press, hover, focus;
    1.39 +
    1.40 +	struct {
    1.41 +		EventCallback func;
    1.42 +		void *cls;
    1.43 +	} cb[NUM_EVENTS];
    1.44 +};
    1.45 +
    1.46 +
    1.47 +Widget::Widget()
    1.48 +{
    1.49 +	static int widget_count;
    1.50 +
    1.51 +	widget = new WidgetImpl;
    1.52 +	widget->scr = 0;
    1.53 +
    1.54 +	std::stringstream sstr;
    1.55 +	sstr << get_type_name() << widget_count++;
    1.56 +	widget->name = sstr.str();
    1.57 +
    1.58 +	widget->box.bmin = Vec2(0, 0);
    1.59 +	widget->box.bmax = Vec2(1, 1);
    1.60 +
    1.61 +	widget->visible.set(true);
    1.62 +	widget->active.set(true);
    1.63 +
    1.64 +	widget->hover.set_transition_duration(250);
    1.65 +	widget->press.set_transition_duration(50);
    1.66 +
    1.67 +	memset(widget->cb, 0, sizeof widget->cb);
    1.68 +}
    1.69 +
    1.70 +Widget::~Widget()
    1.71 +{
    1.72 +	delete widget;
    1.73 +}
    1.74 +
    1.75 +void Widget::set_screen(Screen *scr)
    1.76 +{
    1.77 +	widget->scr = scr;
    1.78 +}
    1.79 +
    1.80 +Screen *Widget::get_screen() const
    1.81 +{
    1.82 +	return widget->scr;
    1.83 +}
    1.84 +
    1.85 +const char *Widget::get_type_name() const
    1.86 +{
    1.87 +	return "widget";
    1.88 +}
    1.89 +
    1.90 +void Widget::set_name(const char *name)
    1.91 +{
    1.92 +	widget->name = std::string(name);
    1.93 +}
    1.94 +
    1.95 +const char *Widget::get_name() const
    1.96 +{
    1.97 +	return widget->name.c_str();
    1.98 +}
    1.99 +
   1.100 +void Widget::set_text(const char *text)
   1.101 +{
   1.102 +	widget->text = std::string(text);
   1.103 +}
   1.104 +
   1.105 +const char *Widget::get_text() const
   1.106 +{
   1.107 +	return widget->text.c_str();
   1.108 +}
   1.109 +
   1.110 +void Widget::show()
   1.111 +{
   1.112 +	widget->visible.change(true);
   1.113 +}
   1.114 +
   1.115 +void Widget::hide()
   1.116 +{
   1.117 +	widget->visible.change(false);
   1.118 +}
   1.119 +
   1.120 +float Widget::get_visibility() const
   1.121 +{
   1.122 +	return widget->visible.get_value();
   1.123 +}
   1.124 +
   1.125 +bool Widget::is_visible() const
   1.126 +{
   1.127 +	return widget->visible.get_state();
   1.128 +}
   1.129 +
   1.130 +void Widget::activate()
   1.131 +{
   1.132 +	widget->active.change(true);
   1.133 +}
   1.134 +
   1.135 +void Widget::deactivate()
   1.136 +{
   1.137 +	widget->active.change(false);
   1.138 +}
   1.139 +
   1.140 +float Widget::get_active() const
   1.141 +{
   1.142 +	return widget->active.get_value();
   1.143 +}
   1.144 +
   1.145 +bool Widget::is_active() const
   1.146 +{
   1.147 +	return widget->active.get_state();
   1.148 +}
   1.149 +
   1.150 +void Widget::press()
   1.151 +{
   1.152 +	widget->press.change(true);
   1.153 +}
   1.154 +
   1.155 +void Widget::release()
   1.156 +{
   1.157 +	widget->press.change(false);
   1.158 +}
   1.159 +
   1.160 +float Widget::get_pressed() const
   1.161 +{
   1.162 +	return widget->press.get_value();
   1.163 +}
   1.164 +
   1.165 +bool Widget::is_pressed() const
   1.166 +{
   1.167 +	return widget->press.get_state();
   1.168 +}
   1.169 +
   1.170 +void Widget::mousein()
   1.171 +{
   1.172 +	widget->hover.change(true);
   1.173 +}
   1.174 +
   1.175 +void Widget::mouseout()
   1.176 +{
   1.177 +	widget->hover.change(false);
   1.178 +	if(widget->press) {
   1.179 +		widget->press.change(false);
   1.180 +	}
   1.181 +}
   1.182 +
   1.183 +float Widget::get_under_mouse() const
   1.184 +{
   1.185 +	return widget->hover.get_value();
   1.186 +}
   1.187 +
   1.188 +bool Widget::is_under_mouse() const
   1.189 +{
   1.190 +	return widget->hover.get_state();
   1.191 +}
   1.192 +
   1.193 +bool Widget::can_focus() const
   1.194 +{
   1.195 +	return false;
   1.196 +}
   1.197 +
   1.198 +void Widget::focusin()
   1.199 +{
   1.200 +	widget->focus.change(true);
   1.201 +}
   1.202 +
   1.203 +void Widget::focusout()
   1.204 +{
   1.205 +	widget->focus.change(false);
   1.206 +}
   1.207 +
   1.208 +float Widget::get_focus() const
   1.209 +{
   1.210 +	return widget->focus.get_value();
   1.211 +}
   1.212 +
   1.213 +bool Widget::is_focused() const
   1.214 +{
   1.215 +	return widget->focus.get_state();
   1.216 +}
   1.217 +
   1.218 +void Widget::set_position(float x, float y)
   1.219 +{
   1.220 +	set_position(Vec2(x, y));
   1.221 +}
   1.222 +
   1.223 +void Widget::set_position(const Vec2 &pos)
   1.224 +{
   1.225 +	Vec2 sz = get_size();
   1.226 +
   1.227 +	widget->box.bmin = pos;
   1.228 +	widget->box.bmax.x = pos.x + sz.x;
   1.229 +	widget->box.bmax.y = pos.y + sz.y;
   1.230 +}
   1.231 +
   1.232 +const Vec2 &Widget::get_position() const
   1.233 +{
   1.234 +	return widget->box.bmin;
   1.235 +}
   1.236 +
   1.237 +void Widget::set_size(float x, float y)
   1.238 +{
   1.239 +	set_size(Vec2(x, y));
   1.240 +}
   1.241 +
   1.242 +void Widget::set_size(const Vec2 &sz)
   1.243 +{
   1.244 +	widget->box.bmax.x = widget->box.bmin.x + sz.x;
   1.245 +	widget->box.bmax.y = widget->box.bmin.y + sz.y;
   1.246 +}
   1.247 +
   1.248 +const Vec2 Widget::get_size() const
   1.249 +{
   1.250 +	return Vec2(widget->box.bmax.x - widget->box.bmin.x,
   1.251 +			widget->box.bmax.y - widget->box.bmin.y);
   1.252 +}
   1.253 +
   1.254 +
   1.255 +const BBox &Widget::get_box() const
   1.256 +{
   1.257 +	return widget->box;
   1.258 +}
   1.259 +
   1.260 +bool Widget::hit_test(const Vec2 &pt) const
   1.261 +{
   1.262 +	return pt.x >= widget->box.bmin.x && pt.x < widget->box.bmax.x &&
   1.263 +		pt.y >= widget->box.bmin.y && pt.y < widget->box.bmax.y;
   1.264 +}
   1.265 +
   1.266 +void Widget::draw() const
   1.267 +{
   1.268 +	WidgetDrawFunc draw_func = default_draw_func;
   1.269 +
   1.270 +	if(theme) {
   1.271 +		draw_func = theme->get_draw_func(get_type_name());
   1.272 +	}
   1.273 +
   1.274 +	draw_func(this);
   1.275 +}
   1.276 +
   1.277 +// dummy event handlers
   1.278 +void Widget::on_mouse_button(const ButtonEvent &ev)
   1.279 +{
   1.280 +}
   1.281 +
   1.282 +void Widget::on_mouse_motion(const MotionEvent &ev)
   1.283 +{
   1.284 +}
   1.285 +
   1.286 +void Widget::on_mouse_focus(const FocusEvent &ev)
   1.287 +{
   1.288 +}
   1.289 +
   1.290 +void Widget::on_key(const KeyEvent &ev)
   1.291 +{
   1.292 +}
   1.293 +
   1.294 +void Widget::on_click()
   1.295 +{
   1.296 +}
   1.297 +
   1.298 +void Widget::on_double_click()
   1.299 +{
   1.300 +}
   1.301 +
   1.302 +void Widget::on_change()
   1.303 +{
   1.304 +}
   1.305 +
   1.306 +
   1.307 +#define CALL_CB(w, ev) \
   1.308 +	do { \
   1.309 +		if((w)->widget->cb[ev.type].func) { \
   1.310 +			(w)->widget->cb[ev.type].func((w), ev, (w)->widget->cb[ev.type].cls); \
   1.311 +		} \
   1.312 +	} while(0)
   1.313 +
   1.314 +#define CALL_CB_TYPE(w, t) \
   1.315 +	do { \
   1.316 +		Event ev; \
   1.317 +		ev.type = (t); \
   1.318 +		CALL_CB(w, ev); \
   1.319 +	} while(0)
   1.320 +
   1.321 +/* the event dispatcher generates high-level events (click, etc)
   1.322 + * and calls the on_whatever() functions for both low and high-level
   1.323 + * events.
   1.324 + * The on_whatever functions are called *after* any other actions performed
   1.325 + * here, to give subclasses the opportunity to override them easily, by
   1.326 + * overriding the on_ functions, without having to override handle_event itself
   1.327 + */
   1.328 +// TODO also call callbacks here I guess...
   1.329 +void Widget::handle_event(const Event &ev)
   1.330 +{
   1.331 +	switch(ev.type) {
   1.332 +	case EV_MOUSE_BUTTON:
   1.333 +		if(ev.button.press) {
   1.334 +			press();
   1.335 +		} else {
   1.336 +			if(is_pressed()) {
   1.337 +				CALL_CB_TYPE(this, EV_CLICK);
   1.338 +				on_click();
   1.339 +			}
   1.340 +			release();
   1.341 +		}
   1.342 +
   1.343 +		on_mouse_button(ev.button);
   1.344 +		break;
   1.345 +
   1.346 +	case EV_MOUSE_MOTION:
   1.347 +		on_mouse_motion(ev.motion);
   1.348 +		break;
   1.349 +
   1.350 +	case EV_MOUSE_FOCUS:
   1.351 +		if(ev.focus.enter) {
   1.352 +			mousein();
   1.353 +		} else {
   1.354 +			mouseout();
   1.355 +		}
   1.356 +		on_mouse_focus(ev.focus);
   1.357 +		break;
   1.358 +
   1.359 +	case EV_KEY:
   1.360 +		on_key(ev.key);
   1.361 +		break;
   1.362 +
   1.363 +	case EV_CHANGE:
   1.364 +		on_change();
   1.365 +		break;
   1.366 +
   1.367 +	default:
   1.368 +		break;
   1.369 +	}
   1.370 +
   1.371 +	CALL_CB(this, ev);
   1.372 +}
   1.373 +
   1.374 +
   1.375 +void Widget::set_callback(EventType evtype, EventCallback func, void *cls)
   1.376 +{
   1.377 +	widget->cb[evtype].func = func;
   1.378 +	widget->cb[evtype].cls = cls;
   1.379 +}
   1.380 +
   1.381 +
   1.382 +}	// namespace goatkit