]> git.tdb.fi Git - libs/gltk.git/blob - source/container.cpp
Allow custom tooltips at empty areas of a Root
[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                 Widget *wdg2=cont->get_descendant_at(x-cgeom.x, y-cgeom.y);
71                 if(wdg2)
72                         return wdg2;
73         }
74         return wdg;
75 }
76
77 void Container::button_press(int x, int y, unsigned btn)
78 {
79         if(click_focus)
80         {
81                 const Geometry &cgeom=click_focus->get_geometry();
82                 click_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
83         }
84         else
85         {
86                 if(Widget *wdg=get_child_at(x, y))
87                 {
88                         click_focus=wdg;
89                         click_button=btn;
90
91                         const Geometry &cgeom=wdg->get_geometry();
92                         wdg->button_press(x-cgeom.x, y-cgeom.y, btn);
93                 }
94         }
95 }
96
97 void Container::button_release(int x, int y, unsigned btn)
98 {
99         if(click_focus)
100         {
101                 Widget *wdg=click_focus;
102
103                 if(btn==click_button)
104                         click_focus=0;
105
106                 const Geometry &cgeom=wdg->get_geometry();
107                 wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
108         }
109         else
110         {
111                 if(Widget *wdg=get_child_at(x, y))
112                 {
113                         const Geometry &cgeom=wdg->get_geometry();
114                         wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
115                 }
116         }
117 }
118
119 void Container::pointer_motion(int x, int y)
120 {
121         if(click_focus)
122         {
123                 const Geometry &cgeom=click_focus->get_geometry();
124                 click_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
125         }
126         else
127         {
128                 Widget *wdg=get_child_at(x, y);
129                 if(wdg)
130                 {
131                         const Geometry &cgeom=wdg->get_geometry();
132                         wdg->pointer_motion(x-cgeom.x, y-cgeom.y);
133                 }
134         }
135 }
136
137 void Container::pointer_leave()
138 {
139         Widget::pointer_leave();
140         click_focus=0;
141 }
142
143 Container::Child *Container::create_child(Widget *wdg)
144 {
145         return new Child(*this, wdg);
146 }
147
148
149 Container::Child::Child(Container &c, Widget *w):
150         container(c),
151         widget(w)
152 {
153         widget->signal_visibility_changed.connect(sigc::mem_fun(this, &Child::visibility_changed));
154 }
155
156 Container::Child::~Child()
157 {
158         if(widget==container.click_focus)
159                 container.click_focus=0;
160 }
161
162 void Container::Child::visibility_changed(bool v)
163 {
164         if(!v && widget==container.click_focus)
165                 container.click_focus=0;
166 }
167
168 } // namespace GLtk
169 } // namespace Msp