]> git.tdb.fi Git - libs/gltk.git/blob - source/container.cpp
Add child_added/removed events to Container
[libs/gltk.git] / source / container.cpp
1 /* $Id$
2
3 This file is part of libmspgltk
4 Copyright © 2009-2011  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include "container.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GLtk {
14
15 Container::Container():
16         click_focus(0),
17         click_button(0)
18 { }
19
20 Container::~Container()
21 {
22         while(!children.empty())
23                 delete children.front()->widget;
24 }
25
26 void Container::add(Widget &wdg)
27 {
28         wdg.set_parent(this);
29         children.push_back(create_child(&wdg));
30         on_child_added(wdg);
31 }
32
33 void Container::remove(Widget &wdg)
34 {
35         for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
36                 if((*i)->widget==&wdg)
37                 {
38                         wdg.set_parent(0);
39                         delete *i;
40                         children.erase(i);
41                         on_child_removed(wdg);
42                         return;
43                 }
44
45         throw InvalidState("That Widget is not in this Container");
46 }
47
48 Container::Child *Container::create_child(Widget *wdg)
49 {
50         return new Child(*this, wdg);
51 }
52
53 list<Widget *> Container::get_children() const
54 {
55         list<Widget *> result;
56         for(list<Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
57                 result.push_back((*i)->widget);
58         return result;
59 }
60
61 Widget *Container::get_child_at(int x, int y)
62 {
63         for(list<Child *>::iterator i=children.end(); i!=children.begin();)
64                 if((*--i)->widget->is_visible() && (*i)->widget->get_geometry().is_inside(x, y))
65                         return (*i)->widget;
66
67         return 0;
68 }
69
70 Widget *Container::get_descendant_at(int x, int y)
71 {
72         Widget *wdg = get_child_at(x, y);
73         if(Container *cont = dynamic_cast<Container *>(wdg))
74         {
75                 const Geometry &cgeom = wdg->get_geometry();
76                 Widget *wdg2 = cont->get_descendant_at(x-cgeom.x, y-cgeom.y);
77                 if(wdg2)
78                         return wdg2;
79         }
80         return wdg;
81 }
82
83 void Container::button_press(int x, int y, unsigned btn)
84 {
85         if(click_focus)
86         {
87                 const Geometry &cgeom = click_focus->get_geometry();
88                 click_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
89         }
90         else
91         {
92                 if(Widget *wdg = get_child_at(x, y))
93                 {
94                         click_focus = wdg;
95                         click_button = btn;
96
97                         const Geometry &cgeom = wdg->get_geometry();
98                         wdg->button_press(x-cgeom.x, y-cgeom.y, btn);
99                 }
100         }
101 }
102
103 void Container::button_release(int x, int y, unsigned btn)
104 {
105         if(click_focus)
106         {
107                 Widget *wdg = click_focus;
108
109                 if(btn==click_button)
110                         click_focus = 0;
111
112                 const Geometry &cgeom = wdg->get_geometry();
113                 wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
114         }
115         else
116         {
117                 if(Widget *wdg = get_child_at(x, y))
118                 {
119                         const Geometry &cgeom = wdg->get_geometry();
120                         wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
121                 }
122         }
123 }
124
125 void Container::pointer_motion(int x, int y)
126 {
127         if(click_focus)
128         {
129                 const Geometry &cgeom = click_focus->get_geometry();
130                 click_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
131         }
132         else
133         {
134                 Widget *wdg = get_child_at(x, y);
135                 if(wdg)
136                 {
137                         const Geometry &cgeom = wdg->get_geometry();
138                         wdg->pointer_motion(x-cgeom.x, y-cgeom.y);
139                 }
140         }
141 }
142
143 void Container::pointer_leave()
144 {
145         Widget::pointer_leave();
146         click_focus = 0;
147 }
148
149 void Container::on_reparent()
150 {
151         for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
152         {
153                 if(Container *c = dynamic_cast<Container *>((*i)->widget))
154                         c->on_reparent();
155                 (*i)->widget->update_style();
156         }
157 }
158
159
160 Container::Child::Child(Container &c, Widget *w):
161         container(c),
162         widget(w)
163 {
164         widget->signal_visibility_changed.connect(sigc::mem_fun(this, &Child::visibility_changed));
165 }
166
167 Container::Child::~Child()
168 {
169         if(widget==container.click_focus)
170                 container.click_focus = 0;
171 }
172
173 void Container::Child::visibility_changed(bool v)
174 {
175         if(!v && widget==container.click_focus)
176                 container.click_focus = 0;
177 }
178
179 } // namespace GLtk
180 } // namespace Msp