aboutsummaryrefslogtreecommitdiff
path: root/src/Container.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Container.cc')
-rw-r--r--src/Container.cc241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/Container.cc b/src/Container.cc
new file mode 100644
index 0000000..e39c582
--- /dev/null
+++ b/src/Container.cc
@@ -0,0 +1,241 @@
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.10 2003/12/21 16:12:19 rathnor 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
136}
137
138int Container::find(Item item) {
139 ItemList::iterator it = m_item_list.begin();
140 ItemList::iterator it_end = m_item_list.end();
141 int index = 0;
142 for (; it != it_end; ++it, ++index) {
143 if ((*it) == item)
144 break;
145 }
146
147 if (it == it_end)
148 return -1;
149
150 return index;
151}
152
153void Container::setSelected(int pos) {
154 if (pos < 0 || pos >= size())
155 m_selected = 0;
156 else {
157 ItemList::iterator it = m_item_list.begin();
158 for (; pos != 0; --pos, ++it)
159 continue;
160 m_selected = *it;
161 if (m_selected)
162 m_selected->clear();
163 }
164
165}
166
167void Container::setMaxSizePerClient(unsigned int size) {
168 m_max_size_per_client = size;
169}
170
171void Container::setAlignment(Container::Alignment a) {
172 m_align = a;
173}
174
175void Container::exposeEvent(XExposeEvent &event) {
176 if (!m_update_lock)
177 clearArea(event.x, event.y, event.width, event.height);
178}
179
180void Container::repositionItems() {
181 if (size() == 0 || m_update_lock)
182 return;
183
184 //!! TODO vertical position
185
186 const int max_width_per_client = maxWidthPerClient();
187
188 ItemList::iterator it = m_item_list.begin();
189 const ItemList::iterator it_end = m_item_list.end();
190 int borderW = m_item_list.front()->borderWidth();
191
192 int rounding_error = width() - ((maxWidthPerClient() + borderW)* m_item_list.size() - borderW);
193
194 int next_x = -borderW; // zero so the border of the first shows
195 int extra = 0;
196 int direction = 1;
197 if (alignment() == RIGHT) {
198 direction = -1;
199 next_x = width() - max_width_per_client + borderW;
200 }
201
202 for (; it != it_end; ++it, next_x += direction*(max_width_per_client + borderW + extra)) {
203 if (rounding_error != 0) {
204 --rounding_error;
205 extra = 1;
206 } else {
207 extra = 0;
208 }
209 // resize each clients including border in size
210 (*it)->moveResize(next_x,
211 -borderW,
212 max_width_per_client + extra,
213 height());
214 (*it)->clear();
215 }
216
217}
218
219
220unsigned int Container::maxWidthPerClient() const {
221 switch (alignment()) {
222 case RIGHT:
223 case LEFT:
224 return m_max_size_per_client;
225 break;
226 case RELATIVE:
227 int count = size();
228 if (count == 0)
229 return width();
230 else {
231 int borderW = m_item_list.front()->borderWidth();
232 // there're count-1 borders to fit in with the windows
233 // -> 1 per window plus end
234 return (width() - (count - 1) * borderW) / count;
235 }
236 break;
237 }
238
239 // this will never happen anyway
240 return 1;
241}