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