]> git.tdb.fi Git - libs/gltk.git/blob - source/container.cpp
Rearrange members
[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 }
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                         wdg.set_parent(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 Container::Child *Container::create_child(Widget *wdg)
47 {
48         return new Child(*this, wdg);
49 }
50
51 list<Widget *> Container::get_children() const
52 {
53         list<Widget *> result;
54         for(list<Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
55                 result.push_back((*i)->widget);
56         return result;
57 }
58
59 Widget *Container::get_child_at(int x, int y)
60 {
61         for(list<Child *>::iterator i=children.end(); i!=children.begin();)
62                 if((*--i)->widget->is_visible() && (*i)->widget->get_geometry().is_inside(x, y))
63                         return (*i)->widget;
64
65         return 0;
66 }
67
68 Widget *Container::get_descendant_at(int x, int y)
69 {
70         Widget *wdg = get_child_at(x, y);
71         if(Container *cont = dynamic_cast<Container *>(wdg))
72         {
73                 const Geometry &cgeom = wdg->get_geometry();
74                 Widget *wdg2 = cont->get_descendant_at(x-cgeom.x, y-cgeom.y);
75                 if(wdg2)
76                         return wdg2;
77         }
78         return wdg;
79 }
80
81 void Container::button_press(int x, int y, unsigned btn)
82 {
83         if(click_focus)
84         {
85                 const Geometry &cgeom = click_focus->get_geometry();
86                 click_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
87         }
88         else
89         {
90                 if(Widget *wdg = get_child_at(x, y))
91                 {
92                         click_focus = wdg;
93                         click_button = btn;
94
95                         const Geometry &cgeom = wdg->get_geometry();
96                         wdg->button_press(x-cgeom.x, y-cgeom.y, btn);
97                 }
98         }
99 }
100
101 void Container::button_release(int x, int y, unsigned btn)
102 {
103         if(click_focus)
104         {
105                 Widget *wdg = click_focus;
106
107                 if(btn==click_button)
108                         click_focus = 0;
109
110                 const Geometry &cgeom = wdg->get_geometry();
111                 wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
112         }
113         else
114         {
115                 if(Widget *wdg = get_child_at(x, y))
116                 {
117                         const Geometry &cgeom = wdg->get_geometry();
118                         wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
119                 }
120         }
121 }
122
123 void Container::pointer_motion(int x, int y)
124 {
125         if(click_focus)
126         {
127                 const Geometry &cgeom = click_focus->get_geometry();
128                 click_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
129         }
130         else
131         {
132                 Widget *wdg = get_child_at(x, y);
133                 if(wdg)
134                 {
135                         const Geometry &cgeom = wdg->get_geometry();
136                         wdg->pointer_motion(x-cgeom.x, y-cgeom.y);
137                 }
138         }
139 }
140
141 void Container::pointer_leave()
142 {
143         Widget::pointer_leave();
144         click_focus = 0;
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                 (*i)->widget->update_style();
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