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