]> git.tdb.fi Git - libs/gltk.git/blob - source/container.cpp
Store the Resources reference only in Root widget
[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():
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         set_parent(wdg, this);
29         children.push_back(create_child(&wdg));
30 }
31
32 void Container::remove(Widget &wdg)
33 {
34         for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
35                 if((*i)->widget==&wdg)
36                 {
37                         set_parent(wdg, 0);
38                         delete *i;
39                         children.erase(i);
40                         return;
41                 }
42
43         throw InvalidState("That Widget is not in this Container");
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 Container::Child *Container::create_child(Widget *wdg)
143 {
144         return new Child(*this, wdg);
145 }
146
147 void Container::on_reparent()
148 {
149         for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
150         {
151                 if(Container *c = dynamic_cast<Container *>((*i)->widget))
152                         c->on_reparent();
153                 update_style(*(*i)->widget);
154         }
155 }
156
157
158 Container::Child::Child(Container &c, Widget *w):
159         container(c),
160         widget(w)
161 {
162         widget->signal_visibility_changed.connect(sigc::mem_fun(this, &Child::visibility_changed));
163 }
164
165 Container::Child::~Child()
166 {
167         if(widget==container.click_focus)
168                 container.click_focus = 0;
169 }
170
171 void Container::Child::visibility_changed(bool v)
172 {
173         if(!v && widget==container.click_focus)
174                 container.click_focus = 0;
175 }
176
177 } // namespace GLtk
178 } // namespace Msp