]> git.tdb.fi Git - libs/gltk.git/blob - source/root.cpp
Add a render method to Root that takes care of proper matrices
[libs/gltk.git] / source / root.cpp
1 /* $Id$
2
3 This file is part of libmspgltk
4 Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/gl/blend.h>
9 #include <msp/input/keys.h>
10 #include <msp/time/units.h>
11 #include <msp/time/utils.h>
12 #include "label.h"
13 #include "style.h"
14 #include "root.h"
15
16 namespace Msp {
17 namespace GLtk {
18
19 Root::Root(const Resources &r, Graphics::Window &w):
20         resources(r),
21         window(w),
22         lbl_tooltip(0),
23         tooltip_target(0)
24 {
25         set_geometry(Geometry(0, 0, window.get_width(), window.get_height()));
26
27         update_style();
28
29         window.signal_button_press.connect(sigc::mem_fun(this, &Root::button_press_event));
30         window.signal_button_release.connect(sigc::mem_fun(this, &Root::button_release_event));
31         window.signal_pointer_motion.connect(sigc::mem_fun(this, &Root::pointer_motion_event));
32         window.signal_key_press.connect(sigc::mem_fun(this, &Root::key_press_event));
33         window.signal_key_release.connect(sigc::mem_fun(this, &Root::key_release_event));
34 }
35
36 void Root::tick()
37 {
38         if(tooltip_timeout && Time::now()>tooltip_timeout)
39         {
40                 std::string tip;
41                 if(Widget *wdg = get_descendant_at(pointer_x, pointer_y))
42                 {
43                         tip = wdg->get_tooltip();
44                         tooltip_target = wdg;
45                 }
46                 else
47                 {
48                         tip = signal_tooltip.emit(pointer_x, pointer_y);
49                         tooltip_target = this;
50                 }
51
52                 if(!tip.empty())
53                 {
54                         if(!lbl_tooltip)
55                         {
56                                 lbl_tooltip = new Label;
57                                 add(*lbl_tooltip);
58                                 lbl_tooltip->set_style("tooltip");
59                         }
60
61                         lbl_tooltip->set_text(tip);
62                         lbl_tooltip->autosize();
63                         const Geometry &tip_geom = lbl_tooltip->get_geometry();
64                         unsigned x = pointer_x+10;
65                         unsigned y = pointer_y-10-lbl_tooltip->get_geometry().h;
66                         if(x+tip_geom.w>geom.w)
67                         {
68                                 if(pointer_x>static_cast<int>(tip_geom.w+2))
69                                         x = pointer_x-2-tip_geom.w;
70                                 else
71                                         x = geom.w-tip_geom.w;
72                         }
73                         lbl_tooltip->set_position(x, y);
74                         raise(*lbl_tooltip);
75                         lbl_tooltip->set_visible(true);
76                 }
77
78                 tooltip_timeout = Time::TimeStamp();
79         }
80 }
81
82 void Root::render() const
83 {
84         GL::MatrixStack::projection() = GL::Matrix::ortho_bottomleft(geom.w, geom.h);
85         GL::MatrixStack::modelview() = GL::Matrix();
86         GL::Bind bind_blend(GL::Blend::alpha());
87
88         Widget::render();
89 }
90
91 void Root::button_press_event(int x, int y, unsigned btn, unsigned mod)
92 {
93         if(visible)
94         {
95                 Widget *old_focus = pointer_focus;
96
97                 translate_coords(x, y);
98                 button_press(x, y, btn);
99
100                 if(!pointer_focus && !old_focus)
101                         signal_button_press.emit(x, geom.h-1-y, btn, mod);
102         }
103 }
104
105 void Root::button_release_event(int x, int y, unsigned btn, unsigned mod)
106 {
107         if(visible)
108         {
109                 Widget *old_focus = pointer_focus;
110
111                 translate_coords(x, y);
112                 button_release(x, y, btn);
113
114                 if(!pointer_focus && !old_focus)
115                         signal_button_release.emit(x, geom.h-1-y, btn, mod);
116         }
117 }
118
119 void Root::pointer_motion_event(int x, int y)
120 {
121         if(visible)
122         {
123                 translate_coords(x, y);
124                 pointer_motion(x, y);
125
126                 if(!tooltip_target)
127                 {
128                         pointer_x = x;
129                         pointer_y = y;
130                         tooltip_timeout = Time::now()+700*Time::msec;
131                 }
132                 else if(get_descendant_at(x, y)!=tooltip_target)
133                 {
134                         if(lbl_tooltip)
135                                 lbl_tooltip->set_visible(false);
136                         tooltip_target = 0;
137                 }
138
139                 if(!pointer_focus)
140                         signal_pointer_motion.emit(x, geom.h-1-y);
141         }
142 }
143
144 void Root::key_press_event(unsigned key, unsigned mod, wchar_t ch)
145 {
146         if(visible)
147         {
148                 Widget *old_focus = input_focus;
149
150                 key_press(Input::key_from_sys(key), mod, ch);
151
152                 if(!input_focus && !old_focus)
153                         signal_key_press.emit(key, mod, ch);
154         }
155 }
156
157 void Root::key_release_event(unsigned key, unsigned mod)
158 {
159         if(visible)
160         {
161                 Widget *old_focus = input_focus;
162
163                 key_release(Input::key_from_sys(key), mod);
164
165                 if(!input_focus && !old_focus)
166                         signal_key_release.emit(key, mod);
167         }
168 }
169
170 void Root::translate_coords(int &x, int &y)
171 {
172         x = x*geom.w/window.get_width();
173         y = geom.h-1-y*geom.h/window.get_height();
174 }
175
176 } // namespace GLtk
177 } // namespace Msp