istereo2

annotate libs/goatkit/widget.cc @ 20:2b85d05df3f2

animation controls for easier screenshot grabbing
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 02 Oct 2015 04:54:55 +0300
parents 018f997dc646
children
rev   line source
nuclear@6 1 /*
nuclear@6 2 GoatKit - a themable/animated widget toolkit for games
nuclear@6 3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>
nuclear@6 4
nuclear@6 5 This program is free software: you can redistribute it and/or modify
nuclear@6 6 it under the terms of the GNU Lesser General Public License as published by
nuclear@6 7 the Free Software Foundation, either version 3 of the License, or
nuclear@6 8 (at your option) any later version.
nuclear@6 9
nuclear@6 10 This program is distributed in the hope that it will be useful,
nuclear@6 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@6 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@6 13 GNU Lesser General Public License for more details.
nuclear@6 14
nuclear@6 15 You should have received a copy of the GNU Lesser General Public License
nuclear@6 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@6 17 */
nuclear@6 18 #include <stdio.h>
nuclear@6 19 #include <string.h>
nuclear@6 20 #include <math.h>
nuclear@6 21 #include <string>
nuclear@6 22 #include <sstream>
nuclear@6 23 #include "widget.h"
nuclear@6 24 #include "boolanm.h"
nuclear@6 25 #include "theme.h"
nuclear@6 26 #include "screen.h"
nuclear@6 27
nuclear@6 28 namespace goatkit {
nuclear@6 29
nuclear@6 30 struct WidgetImpl {
nuclear@6 31 Screen *scr;
nuclear@6 32 std::string name, text;
nuclear@6 33 BBox box;
nuclear@6 34
nuclear@6 35 BoolAnim visible, active, press, hover, focus;
nuclear@6 36
nuclear@6 37 struct {
nuclear@6 38 EventCallback func;
nuclear@6 39 void *cls;
nuclear@6 40 } cb[NUM_EVENTS];
nuclear@6 41 };
nuclear@6 42
nuclear@6 43
nuclear@6 44 Widget::Widget()
nuclear@6 45 {
nuclear@6 46 static int widget_count;
nuclear@6 47
nuclear@6 48 widget = new WidgetImpl;
nuclear@6 49 widget->scr = 0;
nuclear@6 50
nuclear@6 51 std::stringstream sstr;
nuclear@6 52 sstr << get_type_name() << widget_count++;
nuclear@6 53 widget->name = sstr.str();
nuclear@6 54
nuclear@6 55 widget->box.bmin = Vec2(0, 0);
nuclear@6 56 widget->box.bmax = Vec2(1, 1);
nuclear@6 57
nuclear@6 58 widget->visible.set(true);
nuclear@6 59 widget->active.set(true);
nuclear@6 60
nuclear@6 61 widget->hover.set_transition_duration(250);
nuclear@6 62 widget->press.set_transition_duration(50);
nuclear@6 63
nuclear@6 64 memset(widget->cb, 0, sizeof widget->cb);
nuclear@6 65 }
nuclear@6 66
nuclear@6 67 Widget::~Widget()
nuclear@6 68 {
nuclear@6 69 delete widget;
nuclear@6 70 }
nuclear@6 71
nuclear@6 72 void Widget::set_screen(Screen *scr)
nuclear@6 73 {
nuclear@6 74 widget->scr = scr;
nuclear@6 75 }
nuclear@6 76
nuclear@6 77 Screen *Widget::get_screen() const
nuclear@6 78 {
nuclear@6 79 return widget->scr;
nuclear@6 80 }
nuclear@6 81
nuclear@6 82 const char *Widget::get_type_name() const
nuclear@6 83 {
nuclear@6 84 return "widget";
nuclear@6 85 }
nuclear@6 86
nuclear@6 87 void Widget::set_name(const char *name)
nuclear@6 88 {
nuclear@6 89 widget->name = std::string(name);
nuclear@6 90 }
nuclear@6 91
nuclear@6 92 const char *Widget::get_name() const
nuclear@6 93 {
nuclear@6 94 return widget->name.c_str();
nuclear@6 95 }
nuclear@6 96
nuclear@6 97 void Widget::set_text(const char *text)
nuclear@6 98 {
nuclear@6 99 widget->text = std::string(text);
nuclear@6 100 }
nuclear@6 101
nuclear@6 102 const char *Widget::get_text() const
nuclear@6 103 {
nuclear@6 104 return widget->text.c_str();
nuclear@6 105 }
nuclear@6 106
nuclear@6 107 void Widget::show()
nuclear@6 108 {
nuclear@6 109 widget->visible.change(true);
nuclear@6 110 }
nuclear@6 111
nuclear@6 112 void Widget::hide()
nuclear@6 113 {
nuclear@6 114 widget->visible.change(false);
nuclear@6 115 }
nuclear@6 116
nuclear@6 117 float Widget::get_visibility() const
nuclear@6 118 {
nuclear@6 119 return widget->visible.get_value();
nuclear@6 120 }
nuclear@6 121
nuclear@6 122 bool Widget::is_visible() const
nuclear@6 123 {
nuclear@6 124 return widget->visible.get_state();
nuclear@6 125 }
nuclear@6 126
nuclear@14 127 void Widget::set_visibility_transition(long msec)
nuclear@14 128 {
nuclear@14 129 widget->visible.set_transition_duration(msec);
nuclear@14 130 }
nuclear@14 131
nuclear@14 132 long Widget::get_visibility_transition() const
nuclear@14 133 {
nuclear@14 134 return widget->visible.get_transition_duration();
nuclear@14 135 }
nuclear@14 136
nuclear@6 137 void Widget::activate()
nuclear@6 138 {
nuclear@6 139 widget->active.change(true);
nuclear@6 140 }
nuclear@6 141
nuclear@6 142 void Widget::deactivate()
nuclear@6 143 {
nuclear@6 144 widget->active.change(false);
nuclear@6 145 }
nuclear@6 146
nuclear@6 147 float Widget::get_active() const
nuclear@6 148 {
nuclear@6 149 return widget->active.get_value();
nuclear@6 150 }
nuclear@6 151
nuclear@6 152 bool Widget::is_active() const
nuclear@6 153 {
nuclear@6 154 return widget->active.get_state();
nuclear@6 155 }
nuclear@6 156
nuclear@14 157 void Widget::set_active_transition(long msec)
nuclear@14 158 {
nuclear@14 159 widget->active.set_transition_duration(msec);
nuclear@14 160 }
nuclear@14 161
nuclear@14 162 long Widget::get_active_transition() const
nuclear@14 163 {
nuclear@15 164 return widget->active.get_transition_duration();
nuclear@14 165 }
nuclear@14 166
nuclear@6 167 void Widget::press()
nuclear@6 168 {
nuclear@6 169 widget->press.change(true);
nuclear@6 170 }
nuclear@6 171
nuclear@6 172 void Widget::release()
nuclear@6 173 {
nuclear@6 174 widget->press.change(false);
nuclear@6 175 }
nuclear@6 176
nuclear@6 177 float Widget::get_pressed() const
nuclear@6 178 {
nuclear@6 179 return widget->press.get_value();
nuclear@6 180 }
nuclear@6 181
nuclear@6 182 bool Widget::is_pressed() const
nuclear@6 183 {
nuclear@6 184 return widget->press.get_state();
nuclear@6 185 }
nuclear@6 186
nuclear@14 187 void Widget::set_press_transition(long msec)
nuclear@14 188 {
nuclear@14 189 widget->press.set_transition_duration(msec);
nuclear@14 190 }
nuclear@14 191
nuclear@14 192 long Widget::get_press_transition() const
nuclear@14 193 {
nuclear@14 194 return widget->press.get_transition_duration();
nuclear@14 195 }
nuclear@14 196
nuclear@6 197 void Widget::mousein()
nuclear@6 198 {
nuclear@6 199 widget->hover.change(true);
nuclear@6 200 }
nuclear@6 201
nuclear@6 202 void Widget::mouseout()
nuclear@6 203 {
nuclear@6 204 widget->hover.change(false);
nuclear@6 205 if(widget->press) {
nuclear@6 206 widget->press.change(false);
nuclear@6 207 }
nuclear@6 208 }
nuclear@6 209
nuclear@6 210 float Widget::get_under_mouse() const
nuclear@6 211 {
nuclear@6 212 return widget->hover.get_value();
nuclear@6 213 }
nuclear@6 214
nuclear@6 215 bool Widget::is_under_mouse() const
nuclear@6 216 {
nuclear@6 217 return widget->hover.get_state();
nuclear@6 218 }
nuclear@6 219
nuclear@14 220 void Widget::set_hover_transition(long msec)
nuclear@14 221 {
nuclear@14 222 widget->hover.set_transition_duration(msec);
nuclear@14 223 }
nuclear@14 224
nuclear@14 225 long Widget::get_hover_transition() const
nuclear@14 226 {
nuclear@14 227 return widget->hover.get_transition_duration();
nuclear@14 228 }
nuclear@14 229
nuclear@6 230 bool Widget::can_focus() const
nuclear@6 231 {
nuclear@6 232 return false;
nuclear@6 233 }
nuclear@6 234
nuclear@6 235 void Widget::focusin()
nuclear@6 236 {
nuclear@6 237 widget->focus.change(true);
nuclear@6 238 }
nuclear@6 239
nuclear@6 240 void Widget::focusout()
nuclear@6 241 {
nuclear@6 242 widget->focus.change(false);
nuclear@6 243 }
nuclear@6 244
nuclear@6 245 float Widget::get_focus() const
nuclear@6 246 {
nuclear@6 247 return widget->focus.get_value();
nuclear@6 248 }
nuclear@6 249
nuclear@6 250 bool Widget::is_focused() const
nuclear@6 251 {
nuclear@6 252 return widget->focus.get_state();
nuclear@6 253 }
nuclear@6 254
nuclear@14 255 void Widget::set_focus_transition(long msec)
nuclear@14 256 {
nuclear@14 257 widget->focus.set_transition_duration(msec);
nuclear@14 258 }
nuclear@14 259
nuclear@14 260 long Widget::get_focus_transition() const
nuclear@14 261 {
nuclear@14 262 return widget->focus.get_transition_duration();
nuclear@14 263 }
nuclear@14 264
nuclear@6 265 void Widget::set_position(float x, float y)
nuclear@6 266 {
nuclear@6 267 set_position(Vec2(x, y));
nuclear@6 268 }
nuclear@6 269
nuclear@6 270 void Widget::set_position(const Vec2 &pos)
nuclear@6 271 {
nuclear@6 272 Vec2 sz = get_size();
nuclear@6 273
nuclear@6 274 widget->box.bmin = pos;
nuclear@6 275 widget->box.bmax.x = pos.x + sz.x;
nuclear@6 276 widget->box.bmax.y = pos.y + sz.y;
nuclear@6 277 }
nuclear@6 278
nuclear@6 279 const Vec2 &Widget::get_position() const
nuclear@6 280 {
nuclear@6 281 return widget->box.bmin;
nuclear@6 282 }
nuclear@6 283
nuclear@6 284 void Widget::set_size(float x, float y)
nuclear@6 285 {
nuclear@6 286 set_size(Vec2(x, y));
nuclear@6 287 }
nuclear@6 288
nuclear@6 289 void Widget::set_size(const Vec2 &sz)
nuclear@6 290 {
nuclear@6 291 widget->box.bmax.x = widget->box.bmin.x + sz.x;
nuclear@6 292 widget->box.bmax.y = widget->box.bmin.y + sz.y;
nuclear@6 293 }
nuclear@6 294
nuclear@6 295 const Vec2 Widget::get_size() const
nuclear@6 296 {
nuclear@6 297 return Vec2(widget->box.bmax.x - widget->box.bmin.x,
nuclear@6 298 widget->box.bmax.y - widget->box.bmin.y);
nuclear@6 299 }
nuclear@6 300
nuclear@6 301
nuclear@6 302 const BBox &Widget::get_box() const
nuclear@6 303 {
nuclear@6 304 return widget->box;
nuclear@6 305 }
nuclear@6 306
nuclear@6 307 bool Widget::hit_test(const Vec2 &pt) const
nuclear@6 308 {
nuclear@6 309 return pt.x >= widget->box.bmin.x && pt.x < widget->box.bmax.x &&
nuclear@6 310 pt.y >= widget->box.bmin.y && pt.y < widget->box.bmax.y;
nuclear@6 311 }
nuclear@6 312
nuclear@6 313 void Widget::draw() const
nuclear@6 314 {
nuclear@6 315 WidgetDrawFunc draw_func = default_draw_func;
nuclear@6 316
nuclear@6 317 if(theme) {
nuclear@6 318 draw_func = theme->get_draw_func(get_type_name());
nuclear@6 319 }
nuclear@6 320
nuclear@6 321 draw_func(this);
nuclear@6 322 }
nuclear@6 323
nuclear@6 324 // dummy event handlers
nuclear@6 325 void Widget::on_mouse_button(const ButtonEvent &ev)
nuclear@6 326 {
nuclear@6 327 }
nuclear@6 328
nuclear@6 329 void Widget::on_mouse_motion(const MotionEvent &ev)
nuclear@6 330 {
nuclear@6 331 }
nuclear@6 332
nuclear@6 333 void Widget::on_mouse_focus(const FocusEvent &ev)
nuclear@6 334 {
nuclear@6 335 }
nuclear@6 336
nuclear@6 337 void Widget::on_key(const KeyEvent &ev)
nuclear@6 338 {
nuclear@6 339 }
nuclear@6 340
nuclear@6 341 void Widget::on_click()
nuclear@6 342 {
nuclear@6 343 }
nuclear@6 344
nuclear@6 345 void Widget::on_double_click()
nuclear@6 346 {
nuclear@6 347 }
nuclear@6 348
nuclear@6 349 void Widget::on_change()
nuclear@6 350 {
nuclear@6 351 }
nuclear@6 352
nuclear@6 353
nuclear@6 354 #define CALL_CB(w, ev) \
nuclear@6 355 do { \
nuclear@6 356 if((w)->widget->cb[ev.type].func) { \
nuclear@6 357 (w)->widget->cb[ev.type].func((w), ev, (w)->widget->cb[ev.type].cls); \
nuclear@6 358 } \
nuclear@6 359 } while(0)
nuclear@6 360
nuclear@6 361 #define CALL_CB_TYPE(w, t) \
nuclear@6 362 do { \
nuclear@6 363 Event ev; \
nuclear@6 364 ev.type = (t); \
nuclear@6 365 CALL_CB(w, ev); \
nuclear@6 366 } while(0)
nuclear@6 367
nuclear@6 368 /* the event dispatcher generates high-level events (click, etc)
nuclear@6 369 * and calls the on_whatever() functions for both low and high-level
nuclear@6 370 * events.
nuclear@6 371 * The on_whatever functions are called *after* any other actions performed
nuclear@6 372 * here, to give subclasses the opportunity to override them easily, by
nuclear@6 373 * overriding the on_ functions, without having to override handle_event itself
nuclear@6 374 */
nuclear@6 375 // TODO also call callbacks here I guess...
nuclear@6 376 void Widget::handle_event(const Event &ev)
nuclear@6 377 {
nuclear@6 378 switch(ev.type) {
nuclear@6 379 case EV_MOUSE_BUTTON:
nuclear@6 380 if(ev.button.press) {
nuclear@6 381 press();
nuclear@6 382 } else {
nuclear@6 383 if(is_pressed()) {
nuclear@6 384 CALL_CB_TYPE(this, EV_CLICK);
nuclear@6 385 on_click();
nuclear@6 386 }
nuclear@6 387 release();
nuclear@6 388 }
nuclear@6 389
nuclear@6 390 on_mouse_button(ev.button);
nuclear@6 391 break;
nuclear@6 392
nuclear@6 393 case EV_MOUSE_MOTION:
nuclear@6 394 on_mouse_motion(ev.motion);
nuclear@6 395 break;
nuclear@6 396
nuclear@6 397 case EV_MOUSE_FOCUS:
nuclear@6 398 if(ev.focus.enter) {
nuclear@6 399 mousein();
nuclear@6 400 } else {
nuclear@6 401 mouseout();
nuclear@6 402 }
nuclear@6 403 on_mouse_focus(ev.focus);
nuclear@6 404 break;
nuclear@6 405
nuclear@6 406 case EV_KEY:
nuclear@6 407 on_key(ev.key);
nuclear@6 408 break;
nuclear@6 409
nuclear@6 410 case EV_CHANGE:
nuclear@6 411 on_change();
nuclear@6 412 break;
nuclear@6 413
nuclear@6 414 default:
nuclear@6 415 break;
nuclear@6 416 }
nuclear@6 417
nuclear@6 418 CALL_CB(this, ev);
nuclear@6 419 }
nuclear@6 420
nuclear@6 421
nuclear@6 422 void Widget::set_callback(EventType evtype, EventCallback func, void *cls)
nuclear@6 423 {
nuclear@6 424 widget->cb[evtype].func = func;
nuclear@6 425 widget->cb[evtype].cls = cls;
nuclear@6 426 }
nuclear@6 427
nuclear@6 428
nuclear@6 429 } // namespace goatkit