istereo2
diff libs/goatkit/screen.cc @ 6:3bccfc7d10fe
goatkit is drawing
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 23 Sep 2015 05:44:58 +0300 |
parents | |
children | 7bd4264bf74a |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/goatkit/screen.cc Wed Sep 23 05:44:58 2015 +0300 1.3 @@ -0,0 +1,299 @@ 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 <stdlib.h> 1.23 +#include <string.h> 1.24 +#include <vector> 1.25 +#include "screen.h" 1.26 +#include "widget.h" 1.27 + 1.28 +#define MAX_BUTTONS 16 1.29 + 1.30 +namespace goatkit { 1.31 + 1.32 +struct ScreenImpl { 1.33 + bool visible; 1.34 + std::vector<Widget*> widgets; 1.35 + BBox box; 1.36 + 1.37 + Widget *inp_focused, *over, *pressed[MAX_BUTTONS]; 1.38 + Widget *mgrab; 1.39 +}; 1.40 + 1.41 +static Vec2 world_to_scr(const ScreenImpl *scr, const Vec2 &v); 1.42 +//static Vec2 scr_to_world(const ScreenImpl *scr, const Vec2 &v) 1.43 + 1.44 +Screen::Screen() 1.45 +{ 1.46 + scr = new ScreenImpl; 1.47 + 1.48 + scr->box.bmin = Vec2(0, 0); 1.49 + scr->box.bmax = Vec2(1, 1); 1.50 + 1.51 + scr->inp_focused = scr->over = 0; 1.52 + for(int i=0; i<MAX_BUTTONS; i++) { 1.53 + scr->pressed[i] = 0; 1.54 + } 1.55 + 1.56 + scr->visible = true; 1.57 + scr->mgrab = 0; 1.58 +} 1.59 + 1.60 +Screen::~Screen() 1.61 +{ 1.62 + delete scr; 1.63 +} 1.64 + 1.65 +void Screen::set_position(float x, float y) 1.66 +{ 1.67 + set_position(Vec2(x, y)); 1.68 +} 1.69 + 1.70 +void Screen::set_position(const Vec2 &pos) 1.71 +{ 1.72 + Vec2 sz = get_size(); 1.73 + 1.74 + scr->box.bmin = pos; 1.75 + scr->box.bmax.x = pos.x + sz.x; 1.76 + scr->box.bmax.y = pos.y + sz.y; 1.77 +} 1.78 + 1.79 +const Vec2 &Screen::get_position() const 1.80 +{ 1.81 + return scr->box.bmin; 1.82 +} 1.83 + 1.84 +void Screen::set_size(float x, float y) 1.85 +{ 1.86 + set_size(Vec2(x, y)); 1.87 +} 1.88 + 1.89 +void Screen::set_size(const Vec2 &sz) 1.90 +{ 1.91 + scr->box.bmax.x = scr->box.bmin.x + sz.x; 1.92 + scr->box.bmax.y = scr->box.bmin.y + sz.y; 1.93 +} 1.94 + 1.95 +const Vec2 Screen::get_size() const 1.96 +{ 1.97 + return Vec2(scr->box.bmax.x - scr->box.bmin.x, 1.98 + scr->box.bmax.y - scr->box.bmin.y); 1.99 +} 1.100 + 1.101 +const BBox &Screen::get_box() const 1.102 +{ 1.103 + return scr->box; 1.104 +} 1.105 + 1.106 +void Screen::add_widget(Widget *w) 1.107 +{ 1.108 + scr->widgets.push_back(w); 1.109 + if(scr->visible) { 1.110 + w->show(); 1.111 + } else { 1.112 + w->hide(); 1.113 + } 1.114 + 1.115 + w->set_screen(this); 1.116 +} 1.117 + 1.118 +int Screen::get_widget_count() const 1.119 +{ 1.120 + return (int)scr->widgets.size(); 1.121 +} 1.122 + 1.123 +Widget *Screen::get_widget(int idx) const 1.124 +{ 1.125 + if(idx < 0 || idx >= (int)scr->widgets.size()) { 1.126 + return 0; 1.127 + } 1.128 + return scr->widgets[idx]; 1.129 +} 1.130 + 1.131 +Widget *Screen::get_widget(const char *name) const 1.132 +{ 1.133 + for(size_t i=0; i<scr->widgets.size(); i++) { 1.134 + if(strcmp(scr->widgets[i]->get_name(), name) == 0) { 1.135 + return scr->widgets[i]; 1.136 + } 1.137 + } 1.138 + return 0; 1.139 +} 1.140 + 1.141 +void Screen::show() 1.142 +{ 1.143 + scr->visible = true; 1.144 + 1.145 + for(size_t i=0; i<scr->widgets.size(); i++) { 1.146 + scr->widgets[i]->show(); 1.147 + } 1.148 +} 1.149 + 1.150 +void Screen::hide() 1.151 +{ 1.152 + scr->visible = false; 1.153 + 1.154 + for(size_t i=0; i<scr->widgets.size(); i++) { 1.155 + scr->widgets[i]->hide(); 1.156 + } 1.157 +} 1.158 + 1.159 +bool Screen::is_visible() const 1.160 +{ 1.161 + return scr->visible; 1.162 +} 1.163 + 1.164 +bool Screen::grab_mouse(Widget *w) 1.165 +{ 1.166 + if(!scr->mgrab || !w) { 1.167 + scr->mgrab = w; 1.168 + return true; 1.169 + } 1.170 + return false; 1.171 +} 1.172 + 1.173 +void Screen::draw() const 1.174 +{ 1.175 + for(size_t i=0; i<scr->widgets.size(); i++) { 1.176 + scr->widgets[i]->draw(); 1.177 + } 1.178 +} 1.179 + 1.180 +static Widget *find_widget_at(const ScreenImpl *scr, const Vec2 &pt) 1.181 +{ 1.182 + for(size_t i=0; i<scr->widgets.size(); i++) { 1.183 + Widget *w = scr->widgets[i]; 1.184 + 1.185 + if(w->hit_test(pt)) { 1.186 + return w; 1.187 + } 1.188 + } 1.189 + return 0; 1.190 +} 1.191 + 1.192 +void Screen::sysev_keyboard(int key, bool press) 1.193 +{ 1.194 + Event ev; 1.195 + 1.196 + if(scr->inp_focused) { 1.197 + ev.type = EV_KEY; 1.198 + ev.key.key = key; 1.199 + ev.key.press = press; 1.200 + scr->inp_focused->handle_event(ev); 1.201 + } 1.202 +} 1.203 + 1.204 +void Screen::sysev_mouse_button(int bn, bool press, float x, float y) 1.205 +{ 1.206 + Event ev; 1.207 + Vec2 pt = world_to_scr(scr, Vec2(x, y)); 1.208 + Widget *new_over = scr->mgrab ? scr->mgrab : find_widget_at(scr, pt); 1.209 + 1.210 + ev.type = EV_MOUSE_BUTTON; 1.211 + ev.button.button = bn; 1.212 + ev.button.pos = pt; 1.213 + ev.button.press = press; 1.214 + 1.215 + if(press) { 1.216 + if(bn == 0) { 1.217 + // left click gives input focus 1.218 + // TODO: add input focus event in widget 1.219 + if(new_over && new_over != scr->inp_focused && new_over->can_focus()) { 1.220 + printf("input focus %p -> %p\n", (void*)scr->inp_focused, (void*)new_over); 1.221 + new_over->focusin(); 1.222 + 1.223 + if(scr->inp_focused) { 1.224 + scr->inp_focused->focusout(); 1.225 + } 1.226 + scr->inp_focused = new_over; 1.227 + } 1.228 + } 1.229 + 1.230 + scr->pressed[bn] = new_over; 1.231 + scr->over = new_over; 1.232 + 1.233 + if(new_over) { 1.234 + new_over->handle_event(ev); 1.235 + } 1.236 + 1.237 + } else { 1.238 + // send the mouse release event to the widget that got the matching press 1.239 + if(scr->pressed[bn]) { 1.240 + scr->pressed[bn]->handle_event(ev); 1.241 + scr->pressed[bn] = 0; 1.242 + } 1.243 + } 1.244 + 1.245 + // if we're not over the same widget any more send the leave/enter events 1.246 + // TODO also add drag/drop events 1.247 + if(scr->over != new_over) { 1.248 + ev.type = EV_MOUSE_FOCUS; 1.249 + if(scr->over) { 1.250 + ev.focus.enter = false; 1.251 + scr->over->handle_event(ev); 1.252 + } 1.253 + if(new_over) { 1.254 + ev.focus.enter = true; 1.255 + new_over->handle_event(ev); 1.256 + } 1.257 + scr->over = new_over; 1.258 + } 1.259 +} 1.260 + 1.261 +void Screen::sysev_mouse_motion(float x, float y) 1.262 +{ 1.263 + Event ev; 1.264 + Vec2 pt = world_to_scr(scr, Vec2(x, y)); 1.265 + Widget *new_over = scr->mgrab ? scr->mgrab : find_widget_at(scr, pt); 1.266 + 1.267 + // if we're not over the same widget any more send the leave/enter events 1.268 + if(scr->over != new_over) { 1.269 + ev.type = EV_MOUSE_FOCUS; 1.270 + if(scr->over) { 1.271 + ev.focus.enter = false; 1.272 + scr->over->handle_event(ev); 1.273 + } 1.274 + if(new_over) { 1.275 + ev.focus.enter = true; 1.276 + new_over->handle_event(ev); 1.277 + } 1.278 + scr->over = new_over; 1.279 + } 1.280 + 1.281 + if(new_over) { 1.282 + // send motion event 1.283 + ev.type = EV_MOUSE_MOTION; 1.284 + ev.motion.pos = pt; 1.285 + new_over->handle_event(ev); 1.286 + } 1.287 +} 1.288 + 1.289 +static Vec2 world_to_scr(const ScreenImpl *scr, const Vec2 &v) 1.290 +{ 1.291 + return Vec2(v.x - scr->box.bmin.x, v.y - scr->box.bmin.y); 1.292 +} 1.293 + 1.294 +/* 1.295 +static Vec2 scr_to_world(const ScreenImpl *scr, const Vec2 &v) 1.296 +{ 1.297 + return Vec2(v.x + scr->box.bmin.x, v.y + scr->box.bmin.y); 1.298 +} 1.299 +*/ 1.300 + 1.301 + 1.302 +} // namespace goatkit