]> git.tdb.fi Git - libs/gltk.git/blob - source/panel.cpp
Rearrange members
[libs/gltk.git] / source / panel.cpp
1 /* $Id$
2
3 This file is part of libmspgltk
4 Copyright © 2007-2011  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <algorithm>
9 #include <msp/core/refptr.h>
10 #include "button.h"
11 #include "dropdown.h"
12 #include "entry.h"
13 #include "hslider.h"
14 #include "indicator.h"
15 #include "label.h"
16 #include "list.h"
17 #include "panel.h"
18 #include "part.h"
19 #include "table.h"
20 #include "toggle.h"
21 #include "vslider.h"
22
23 using namespace std;
24
25 namespace Msp {
26 namespace GLtk {
27
28 Panel::Panel():
29         pointer_focus(0),
30         pointer_grabbed(false),
31         input_focus(0)
32 { }
33
34 Panel::Child *Panel::create_child(Widget *wdg)
35 {
36         return new Child(*this, wdg);
37 }
38
39 void Panel::raise(Widget &wdg)
40 {
41         for(list<Container::Child *>::iterator i=children.begin(); i!=children.end(); ++i)
42                 if((*i)->widget==&wdg)
43                 {
44                         children.splice(children.end(), children, i);
45                         return;
46                 }
47
48         throw InvalidState("That Widget is not in this Panel");
49 }
50
51 Widget *Panel::get_final_input_focus() const
52 {
53         if(Panel *panel = dynamic_cast<Panel *>(input_focus))
54         {
55                 Widget *focus = panel->get_final_input_focus();
56                 if(focus)
57                         return focus;
58         }
59         return input_focus;
60 }
61
62 void Panel::render_special(const Part &part) const
63 {
64         if(part.get_name()=="children")
65         {
66                 for(list<Container::Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
67                         if((*i)->widget->is_visible())
68                                 (*i)->widget->render();
69         }
70 }
71
72 void Panel::button_press(int x, int y, unsigned btn)
73 {
74         if(pointer_grabbed)
75         {
76                 const Geometry &cgeom = pointer_focus->get_geometry();
77                 pointer_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
78         }
79         else
80         {
81                 if(Widget *wdg = get_child_at(x, y))
82                 {
83                         set_pointer_focus(wdg);
84                         if(wdg->is_focusable())
85                                 set_input_focus(wdg);
86                 }
87                 Container::button_press(x, y, btn);
88         }
89 }
90
91 void Panel::button_release(int x, int y, unsigned btn)
92 {
93         if(pointer_grabbed)
94         {
95                 const Geometry &cgeom = pointer_focus->get_geometry();
96                 pointer_focus->button_release(x-cgeom.x, y-cgeom.y, btn);
97         }
98         else
99                 Container::button_release(x, y, btn);
100 }
101
102 void Panel::pointer_motion(int x, int y)
103 {
104         if(pointer_grabbed)
105         {
106                 const Geometry &cgeom = pointer_focus->get_geometry();
107                 pointer_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
108         }
109         else
110         {
111                 set_pointer_focus(get_child_at(x, y));
112                 Container::pointer_motion(x, y);
113         }
114 }
115
116 void Panel::pointer_leave()
117 {
118         Container::pointer_leave();
119         set_pointer_focus(0);
120 }
121
122 void Panel::key_press(unsigned key, unsigned mod, wchar_t ch)
123 {
124         if(input_focus)
125                 input_focus->key_press(key, mod, ch);
126 }
127
128 void Panel::key_release(unsigned key, unsigned mod)
129 {
130         if(input_focus)
131                 input_focus->key_release(key, mod);
132 }
133
134 void Panel::focus_out()
135 {
136         set_input_focus(0);
137 }
138
139 void Panel::set_pointer_focus(Widget *wdg)
140 {
141         if(wdg!=pointer_focus)
142         {
143                 if(pointer_focus)
144                         pointer_focus->pointer_leave();
145
146                 pointer_focus = wdg;
147
148                 if(pointer_focus)
149                         pointer_focus->pointer_enter();
150         }
151 }
152
153 void Panel::set_input_focus(Widget *wdg)
154 {
155         if(wdg!=input_focus)
156         {
157                 if(input_focus)
158                         input_focus->focus_out();
159
160                 input_focus = wdg;
161
162                 if(input_focus)
163                 {
164                         raise(*wdg);
165                         input_focus->focus_in();
166                 }
167         }
168 }
169
170
171 Panel::Loader::Loader(Panel &p, map<string, Widget *> &m):
172         Widget::Loader(p),
173         pnl(p),
174         wdg_map(m)
175 {
176         add("button",    &Loader::child<Button>);
177         add("dropdown",  &Loader::child<Dropdown>);
178         add("entry",     &Loader::child<Entry>);
179         add("hslider",   &Loader::child<HSlider>);
180         add("indicator", &Loader::child<Indicator>);
181         add("label",     &Loader::child<Label>);
182         add("list",      &Loader::child<List>);
183         add("panel",     &Loader::panel);
184         add("table",     &Loader::child<Table>);
185         add("toggle",    &Loader::child<Toggle>);
186         add("vslider",   &Loader::child<VSlider>);
187 }
188
189 template<typename T>
190 void Panel::Loader::child(const string &n)
191 {
192         RefPtr<T> chl = new T();
193         load_sub(*chl);
194         pnl.add(*chl.get());
195         wdg_map[n] = chl.release();
196 }
197
198 void Panel::Loader::panel(const string &n)
199 {
200         RefPtr<Panel> p = new Panel();
201         load_sub(*p, wdg_map);
202         pnl.add(*p.get());
203         wdg_map[n] = p.release();
204 }
205
206
207 Panel::Child::Child(Panel &p, Widget *w):
208         Container::Child(p, w)
209 {
210         widget->signal_visibility_changed.connect(sigc::mem_fun(this, &Child::visibility_changed));
211         widget->signal_request_focus.connect(sigc::mem_fun(this, &Child::request_focus));
212         widget->signal_grab_pointer.connect(sigc::mem_fun(this, &Child::grab_pointer));
213         widget->signal_ungrab_pointer.connect(sigc::mem_fun(this, &Child::ungrab_pointer));
214 }
215
216 Panel::Child::~Child()
217 {
218         visibility_changed(false);
219 }
220
221 void Panel::Child::visibility_changed(bool v)
222 {
223         if(!v)
224         {
225                 Panel &panel = static_cast<Panel &>(container);
226                 if(widget==panel.pointer_focus)
227                         panel.set_pointer_focus(0);
228                 if(widget==panel.input_focus)
229                         panel.set_input_focus(0);
230         }
231 }
232
233 void Panel::Child::request_focus()
234 {
235         Panel &panel = static_cast<Panel &>(container);
236         panel.set_input_focus(widget);
237         if(panel.parent && panel.visible)
238                 panel.set_focus();
239 }
240
241 void Panel::Child::grab_pointer()
242 {
243         Panel &panel = static_cast<Panel &>(container);
244         if(!panel.pointer_grabbed)
245         {
246                 panel.set_pointer_focus(widget);
247                 panel.pointer_grabbed = true;
248                 panel.signal_grab_pointer.emit();
249         }
250 }
251
252 void Panel::Child::ungrab_pointer()
253 {
254         Panel &panel = static_cast<Panel &>(container);
255         if(panel.pointer_grabbed && panel.pointer_focus==widget)
256         {
257                 // XXX Should set to the widget under pointer
258                 panel.set_pointer_focus(0);
259                 panel.pointer_grabbed = false;
260                 panel.signal_ungrab_pointer.emit();
261         }
262 }
263
264 } // namespace GLtk
265 } // namespace Msp