]> git.tdb.fi Git - libs/gltk.git/blob - source/root.cpp
de2472797199108870d8b045679d53019ad815a8
[libs/gltk.git] / source / root.cpp
1 #include <msp/gl/blend.h>
2 #include <msp/input/keys.h>
3 #include <msp/time/units.h>
4 #include <msp/time/utils.h>
5 #include "label.h"
6 #include "style.h"
7 #include "root.h"
8
9 namespace Msp {
10 namespace GLtk {
11
12 Root::Root(const Resources &r, Graphics::Window &window):
13         resources(r),
14         keyboard(new Input::Keyboard(window)),
15         mouse(new Input::Mouse(window)),
16         own_input(true)
17 {
18         init(&window);
19 }
20
21 Root::Root(const Resources &r, Graphics::Window *window, Input::Keyboard *k, Input::Mouse *m):
22         resources(r),
23         keyboard(k),
24         mouse(m),
25         own_input(false)
26 {
27         init(window);
28 }
29
30 void Root::init(Graphics::Window *window)
31 {
32         if(window)
33                 set_geometry(Geometry(0, 0, window->get_width(), window->get_height()));
34
35         lbl_tooltip = 0;
36         tooltip_target = 0;
37
38         update_style();
39
40         if(mouse)
41         {
42                 mouse->signal_button_press.connect(sigc::mem_fun(this, &Root::button_press_event));
43                 mouse->signal_button_release.connect(sigc::mem_fun(this, &Root::button_release_event));
44                 mouse->signal_axis_motion.connect(sigc::mem_fun(this, &Root::axis_motion_event));
45         }
46
47         if(keyboard)
48         {
49                 keyboard->signal_button_press.connect(sigc::mem_fun(this, &Root::key_press_event));
50                 keyboard->signal_button_release.connect(sigc::mem_fun(this, &Root::key_release_event));
51                 keyboard->signal_character.connect(sigc::mem_fun(this, &Root::character_event));
52         }
53 }
54
55 Root::~Root()
56 {
57         if(own_input)
58         {
59                 delete keyboard;
60                 delete mouse;
61         }
62 }
63
64 void Root::tick()
65 {
66         if(tooltip_timeout && Time::now()>tooltip_timeout)
67         {
68                 std::string tip;
69                 if(Widget *wdg = get_descendant_at(pointer_x, pointer_y))
70                 {
71                         tip = wdg->get_tooltip();
72                         tooltip_target = wdg;
73                 }
74                 else
75                 {
76                         tip = signal_tooltip.emit(pointer_x, pointer_y);
77                         tooltip_target = this;
78                 }
79
80                 if(!tip.empty())
81                 {
82                         if(!lbl_tooltip)
83                         {
84                                 lbl_tooltip = new Label;
85                                 add(*lbl_tooltip);
86                                 lbl_tooltip->set_style("tooltip");
87                         }
88
89                         lbl_tooltip->set_text(tip);
90                         lbl_tooltip->autosize();
91                         const Geometry &tip_geom = lbl_tooltip->get_geometry();
92                         unsigned x = pointer_x+10;
93                         unsigned y = pointer_y-10-lbl_tooltip->get_geometry().h;
94                         if(x+tip_geom.w>geom.w)
95                         {
96                                 if(pointer_x>static_cast<int>(tip_geom.w+2))
97                                         x = pointer_x-2-tip_geom.w;
98                                 else
99                                         x = geom.w-tip_geom.w;
100                         }
101                         lbl_tooltip->set_position(x, y);
102                         raise(*lbl_tooltip);
103                         lbl_tooltip->set_visible(true);
104                 }
105
106                 tooltip_timeout = Time::TimeStamp();
107         }
108 }
109
110 void Root::render() const
111 {
112         GL::MatrixStack::projection() = GL::Matrix::ortho_bottomleft(geom.w, geom.h);
113         GL::MatrixStack::modelview() = GL::Matrix();
114         GL::Bind bind_blend(GL::Blend::alpha());
115
116         GL::Renderer renderer(0);
117         Widget::render(renderer);
118 }
119
120 bool Root::button_press_event(unsigned btn)
121 {
122         if(visible)
123         {
124                 Widget *old_focus = pointer_focus;
125
126                 int x, y;
127                 get_pointer(x, y);
128                 button_press(x, y, btn);
129
130                 if(pointer_focus || old_focus)
131                         return true;
132         }
133
134         return false;
135 }
136
137 bool Root::button_release_event(unsigned btn)
138 {
139         if(visible)
140         {
141                 Widget *old_focus = pointer_focus;
142
143                 int x, y;
144                 get_pointer(x, y);
145                 button_release(x, y, btn);
146
147                 if(pointer_focus || old_focus)
148                         return true;
149         }
150
151         return false;
152 }
153
154 bool Root::axis_motion_event(unsigned, float, float)
155 {
156         if(visible)
157         {
158                 int x, y;
159                 get_pointer(x, y);
160                 pointer_motion(x, y);
161
162                 if(!tooltip_target)
163                 {
164                         pointer_x = x;
165                         pointer_y = y;
166                         tooltip_timeout = Time::now()+700*Time::msec;
167                 }
168                 else if(get_descendant_at(x, y)!=tooltip_target)
169                 {
170                         if(lbl_tooltip)
171                                 lbl_tooltip->set_visible(false);
172                         tooltip_target = 0;
173                 }
174
175                 if(pointer_focus)
176                         return true;
177         }
178
179         return false;
180 }
181
182 bool Root::key_press_event(unsigned key)
183 {
184         // XXX Modifiers
185         if(visible)
186         {
187                 Widget *old_focus = input_focus;
188
189                 key_press(key, 0);
190
191                 if(input_focus || old_focus)
192                         return true;
193         }
194
195         return false;
196 }
197
198 bool Root::key_release_event(unsigned key)
199 {
200         if(visible)
201         {
202                 Widget *old_focus = input_focus;
203
204                 key_release(key, 0);
205
206                 if(input_focus || old_focus)
207                         return true;
208         }
209
210         return false;
211 }
212
213 bool Root::character_event(StringCodec::unichar ch)
214 {
215         if(visible)
216         {
217                 Widget *old_focus = input_focus;
218
219                 character(ch);
220
221                 if(input_focus || old_focus)
222                         return true;
223         }
224
225         return false;
226 }
227
228 void Root::get_pointer(int &x, int &y)
229 {
230         x = (mouse->get_axis_value(0)*0.5+0.5)*geom.w;
231         y = (mouse->get_axis_value(1)*0.5+0.5)*geom.h;
232 }
233
234 void Root::on_child_added(Widget &wdg)
235 {
236         if(&wdg!=lbl_tooltip)
237                 Panel::on_child_added(wdg);
238 }
239
240 } // namespace GLtk
241 } // namespace Msp