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