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