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