]> git.tdb.fi Git - libs/gltk.git/blob - source/panel.cpp
bfd0aa8eca7f8f33e5d0ab0ab9688ac1431de911
[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 "entry.h"
11 #include "label.h"
12 #include "panel.h"
13 #include "part.h"
14
15 using namespace std;
16
17 namespace Msp {
18 namespace GLtk {
19
20 Panel::Panel(const Resources &r):
21         Widget(r),
22         pointer_focus(0),
23         pointer_grab(0),
24         input_focus(0)
25 {
26         update_style();
27 }
28
29 Panel::~Panel()
30 {
31         while(!children.empty())
32                 delete children.front();
33 }
34
35 void Panel::add(Widget &wdg)
36 {
37         set_parent(wdg, this);
38         children.push_back(&wdg);
39 }
40
41 void Panel::remove(Widget &wdg)
42 {
43         ChildSeq::iterator i=find(children.begin(), children.end(), &wdg);
44         if(i!=children.end())
45         {
46                 set_parent(wdg, 0);
47                 children.erase(i);
48         }
49 }
50
51 void Panel::button_press(int x, int y, unsigned btn)
52 {
53         if(pointer_grab>0)
54                 pointer_focus->button_press(x-geom.x, y-geom.y, btn);
55         else if(geom.is_inside(x, y))
56         {
57                 if(Widget *wdg=get_child_at(x, y))
58                 {
59                         set_pointer_focus(wdg, btn);
60                         set_input_focus(wdg);
61
62                         wdg->button_press(x-geom.x, y-geom.y, btn);
63                 }
64         }
65 }
66
67 void Panel::button_release(int x, int y, unsigned btn)
68 {
69         if(pointer_grab>0)
70         {
71                 pointer_focus->button_release(x-geom.x, y-geom.y, btn);
72
73                 if(btn==pointer_grab)
74                         set_pointer_focus(get_child_at(x, y), 0);
75         }
76         else if(geom.is_inside(x, y))
77         {
78                 if(Widget *wdg=get_child_at(x, y))
79                         wdg->button_release(x-geom.x, y-geom.y, btn);
80         }
81 }
82
83 void Panel::pointer_motion(int x, int y)
84 {
85         if(pointer_grab>0)
86                 pointer_focus->pointer_motion(x-geom.x, y-geom.y);
87         else if(geom.is_inside(x, y))
88         {
89                 Widget *wdg=get_child_at(x, y);
90                 set_pointer_focus(wdg, 0);
91                 if(wdg)
92                         wdg->pointer_motion(x-geom.x, y-geom.y);
93         }
94 }
95
96 void Panel::pointer_leave()
97 {
98         set_pointer_focus(0, 0);
99 }
100
101 void Panel::key_press(unsigned key, unsigned mod, wchar_t ch)
102 {
103         if(input_focus)
104                 input_focus->key_press(key, mod, ch);
105 }
106
107 void Panel::key_release(unsigned key, unsigned mod)
108 {
109         if(input_focus)
110                 input_focus->key_release(key, mod);
111 }
112
113 void Panel::focus_out()
114 {
115         set_input_focus(0);
116 }
117
118 void Panel::child_hidden(Widget &wdg)
119 {
120         if(&wdg==pointer_focus)
121                 set_pointer_focus(0, 0);
122 }
123
124 void Panel::render_special(const Part &part) const
125 {
126         if(part.get_name()=="children")
127         {
128                 for(ChildSeq::const_iterator i=children.begin(); i!=children.end(); ++i)
129                         if((*i)->is_visible())
130                                 (*i)->render();
131         }
132 }
133
134 void Panel::set_pointer_focus(Widget *wdg, int grab)
135 {
136         if(grab>0 && !wdg)
137                 throw InvalidParameterValue("Can't grab on null widget");
138
139         if(wdg!=pointer_focus)
140         {
141                 if(pointer_focus)
142                         pointer_focus->pointer_leave();
143
144                 pointer_focus=wdg;
145
146                 if(pointer_focus)
147                         pointer_focus->pointer_enter();
148         }
149
150         pointer_grab=grab;
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                         input_focus->focus_in();
164         }
165 }
166
167 Widget *Panel::get_child_at(int x, int y)
168 {
169         for(ChildSeq::reverse_iterator i=children.rbegin(); i!=children.rend(); ++i)
170                 if((*i)->is_visible() && (*i)->get_geometry().is_inside(x-geom.x, y-geom.y))
171                         return *i;
172
173         return 0;
174 }
175
176
177 Panel::Loader::Loader(Panel &p, map<string, Widget *> &m):
178         Widget::Loader(p),
179         pnl(p),
180         wdg_map(m)
181 {
182         add("button", &Loader::child<Button>);
183         add("entry",  &Loader::child<Entry>);
184         add("label",  &Loader::child<Label>);
185         add("panel",  &Loader::panel);
186 }
187
188 template<typename T>
189 void Panel::Loader::child(const string &n)
190 {
191         RefPtr<T> chl=new T(pnl.res);
192         load_sub(*chl);
193         pnl.add(*chl.get());
194         wdg_map[n]=chl.release();
195 }
196
197 void Panel::Loader::panel(const string &n)
198 {
199         RefPtr<Panel> p=new Panel(pnl.res);
200         load_sub(*p, wdg_map);
201         pnl.add(*p.get());
202         wdg_map[n]=p.release();
203 }
204
205 } // namespace GLtk
206 } // namespace Msp