aboutsummaryrefslogtreecommitdiff
path: root/src/Container.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Container.cc')
-rw-r--r--src/Container.cc249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/Container.cc b/src/Container.cc
new file mode 100644
index 0000000..b60b460
--- /dev/null
+++ b/src/Container.cc
@@ -0,0 +1,249 @@
1// Container.cc
2// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3// and Simon Bowden (rathnor at users.sourceforge.net)
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
23// $Id: Container.cc,v 1.12 2004/01/14 23:05:14 fluxgen Exp $
24
25#include "Container.hh"
26
27#include "FbTk/Button.hh"
28#include "FbTk/EventManager.hh"
29
30Container::Container(const FbTk::FbWindow &parent):
31 FbTk::FbWindow(parent, 0, 0, 1, 1, ExposureMask),
32 m_align(RELATIVE),
33 m_max_size_per_client(60),
34 m_selected(0),
35 m_update_lock(false) {
36 FbTk::EventManager::instance()->add(*this, *this);
37}
38
39Container::~Container() {
40
41}
42
43void Container::resize(unsigned int width, unsigned int height) {
44 // do we need to resize?
45 if (FbTk::FbWindow::width() == width &&
46 FbTk::FbWindow::height() == height)
47 return;
48
49 FbTk::FbWindow::resize(width, height);
50 repositionItems();
51}
52
53void Container::moveResize(int x, int y,
54 unsigned int width, unsigned int height) {
55 FbTk::FbWindow::moveResize(x, y, width, height);
56 repositionItems();
57}
58
59void Container::insertItems(ItemList &item_list, int pos) {
60
61 // make sure all items have parent == this
62 ItemList::iterator it = m_item_list.begin();
63 ItemList::iterator it_end = m_item_list.end();
64 for (; it != it_end; ++it) {
65 if ((*it)->parent() != this)
66 return;
67 }
68
69 if (pos > size() || pos < 0) {
70 // insert last
71 m_item_list.splice(m_item_list.end(), item_list);
72 } else if (pos == 0) {
73 // insert first
74 m_item_list.splice(m_item_list.begin(), item_list);
75 } else {
76 // find insert point
77 for (it = m_item_list.begin(); pos != 0; ++it, --pos)
78 continue;
79 m_item_list.splice(it, item_list);
80 }
81
82 m_item_list.unique();
83
84 // update position
85 repositionItems();
86}
87
88void Container::insertItem(Item item, int pos) {
89 if (find(item) != -1)
90 return;
91
92 // it must be a child of this window
93 if (item->parent() != this)
94 return;
95
96 if (pos >= size() || pos < 0) {
97 m_item_list.push_back(item);
98 } else if (pos == 0) {
99 m_item_list.push_front(item);
100 } else {
101 ItemList::iterator it = m_item_list.begin();
102 for (; pos != 0; ++it, --pos)
103 continue;
104
105 m_item_list.insert(it, item);
106 }
107
108 // make sure we dont have duplicate items
109 m_item_list.unique();
110
111 repositionItems();
112}
113
114void Container::removeItem(int index) {
115 if (index < 0 || index > size())
116 return;
117
118 ItemList::iterator it = m_item_list.begin();
119 for (; index != 0; ++it, --index)
120 continue;
121
122 if (*it == selected())
123 m_selected = 0;
124
125 m_item_list.erase(it);
126
127 repositionItems();
128}
129
130void Container::removeAll() {
131 m_selected = 0;
132 m_item_list.clear();
133 if (!m_update_lock) {
134 clear();
135 updateTransparent();
136 }
137
138}
139
140int Container::find(Item item) {
141 ItemList::iterator it = m_item_list.begin();
142 ItemList::iterator it_end = m_item_list.end();
143 int index = 0;
144 for (; it != it_end; ++it, ++index) {
145 if ((*it) == item)
146 break;
147 }
148
149 if (it == it_end)
150 return -1;
151
152 return index;
153}
154
155void Container::setSelected(int pos) {
156 if (pos < 0 || pos >= size())
157 m_selected = 0;
158 else {
159 ItemList::iterator it = m_item_list.begin();
160 for (; pos != 0; --pos, ++it)
161 continue;
162 m_selected = *it;
163 if (m_selected) {
164 m_selected->clear();
165 m_selected->updateTransparent();
166 }
167 }
168
169}
170
171void Container::setMaxSizePerClient(unsigned int size) {
172 m_max_size_per_client = size;
173}
174
175void Container::setAlignment(Container::Alignment a) {
176 m_align = a;
177}
178
179void Container::exposeEvent(XExposeEvent &event) {
180 if (!m_update_lock) {
181 clearArea(event.x, event.y, event.width, event.height);
182 updateTransparent(event.x, event.y, event.width, event.height);
183 }
184}
185
186void Container::repositionItems() {
187 if (size() == 0 || m_update_lock)
188 return;
189
190 //!! TODO vertical position
191
192 const int max_width_per_client = maxWidthPerClient();
193
194 ItemList::iterator it = m_item_list.begin();
195 const ItemList::iterator it_end = m_item_list.end();
196 int borderW = m_item_list.front()->borderWidth();
197
198 int rounding_error = width() - ((maxWidthPerClient() + borderW)* m_item_list.size() - borderW);
199
200 int next_x = -borderW; // zero so the border of the first shows
201 int extra = 0;
202 int direction = 1;
203 if (alignment() == RIGHT) {
204 direction = -1;
205 next_x = width() - max_width_per_client + borderW;
206 }
207
208 for (; it != it_end; ++it, next_x += direction*(max_width_per_client + borderW + extra)) {
209 // we only need to do error stuff with alignment RELATIVE
210 if (rounding_error != 0 && alignment() == RELATIVE) {
211 --rounding_error;
212 extra = 1;
213 } else {
214 extra = 0;
215 }
216 // resize each clients including border in size
217 (*it)->moveResize(next_x,
218 -borderW,
219 max_width_per_client + extra,
220 height());
221 (*it)->clear();
222 (*it)->updateTransparent();
223 }
224
225}
226
227
228unsigned int Container::maxWidthPerClient() const {
229 switch (alignment()) {
230 case RIGHT:
231 case LEFT:
232 return m_max_size_per_client;
233 break;
234 case RELATIVE:
235 int count = size();
236 if (count == 0)
237 return width();
238 else {
239 int borderW = m_item_list.front()->borderWidth();
240 // there're count-1 borders to fit in with the windows
241 // -> 1 per window plus end
242 return (width() - (count - 1) * borderW) / count;
243 }
244 break;
245 }
246
247 // this will never happen anyway
248 return 1;
249}