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