aboutsummaryrefslogtreecommitdiff
path: root/src/Container.cc
diff options
context:
space:
mode:
authorMark Tiefenbruck <mark@fluxbox.org>2007-12-28 05:47:55 (GMT)
committerMark Tiefenbruck <mark@fluxbox.org>2007-12-28 05:47:55 (GMT)
commite8a2f155e8d5a082a8c04f291e65c137c20a05cb (patch)
tree4107154a6c73d518b604aab43371c994ae172624 /src/Container.cc
parent00ceefd8846bda6f4dc43a5a990086545ea28727 (diff)
downloadfluxbox-e8a2f155e8d5a082a8c04f291e65c137c20a05cb.zip
fluxbox-e8a2f155e8d5a082a8c04f291e65c137c20a05cb.tar.bz2
moved Container to FbTk
Diffstat (limited to 'src/Container.cc')
-rw-r--r--src/Container.cc526
1 files changed, 0 insertions, 526 deletions
diff --git a/src/Container.cc b/src/Container.cc
deleted file mode 100644
index e2d01c7..0000000
--- a/src/Container.cc
+++ /dev/null
@@ -1,526 +0,0 @@
1// Container.cc
2// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
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$
24
25#include "Container.hh"
26
27#include "FbTk/Button.hh"
28#include "FbTk/EventManager.hh"
29#include "CompareWindow.hh"
30
31#include <algorithm>
32
33Container::Container(const FbTk::FbWindow &parent):
34 FbTk::FbWindow(parent, 0, 0, 1, 1, ExposureMask),
35 m_orientation(FbTk::ROT0),
36 m_align(RELATIVE),
37 m_max_size_per_client(60),
38 m_max_total_size(0),
39 m_update_lock(false) {
40 FbTk::EventManager::instance()->add(*this, *this);
41}
42
43Container::~Container() {
44 // ~FbWindow cleans event manager
45}
46
47void Container::resize(unsigned int width, unsigned int height) {
48 // do we need to resize?
49 if (FbTk::FbWindow::width() == width &&
50 FbTk::FbWindow::height() == height)
51 return;
52
53 FbTk::FbWindow::resize(width, height);
54 repositionItems();
55}
56
57void Container::moveResize(int x, int y,
58 unsigned int width, unsigned int height) {
59 FbTk::FbWindow::moveResize(x, y, width, height);
60 repositionItems();
61}
62
63#ifdef NOT_USED
64void Container::move(int x, int y) {
65 FbTk::FbWindow::move(x, y);
66 // no need to reposition
67}
68
69void Container::insertItems(ItemList &item_list, int pos) {
70
71 // make sure all items have parent == this
72 ItemList::iterator it = m_item_list.begin();
73 ItemList::iterator it_end = m_item_list.end();
74 for (; it != it_end; ++it) {
75 if ((*it)->parent() != this)
76 return;
77 }
78
79 if (pos > size() || pos < 0) {
80 // insert last
81 m_item_list.splice(m_item_list.end(), item_list);
82 } else if (pos == 0) {
83 // insert first
84 m_item_list.splice(m_item_list.begin(), item_list);
85 } else {
86 // find insert point
87 for (it = m_item_list.begin(); pos != 0; ++it, --pos)
88 continue;
89 m_item_list.splice(it, item_list);
90 }
91
92 m_item_list.unique();
93
94 // update position
95 repositionItems();
96}
97#endif
98
99void Container::insertItem(Item item, int pos) {
100 if (find(item) != -1)
101 return;
102
103 // it must be a child of this window
104 if (item->parent() != this)
105 return;
106
107 item->setOrientation(m_orientation);
108 if (pos >= size() || pos < 0) {
109 m_item_list.push_back(item);
110 } else if (pos == 0) {
111 m_item_list.push_front(item);
112 } else {
113 ItemList::iterator it = m_item_list.begin();
114 for (; pos != 0; ++it, --pos)
115 continue;
116
117 m_item_list.insert(it, item);
118 }
119
120 // make sure we dont have duplicate items
121 m_item_list.unique();
122
123 repositionItems();
124}
125
126void Container::moveItem(Item item, int movement) {
127
128 int index = find(item);
129 const size_t size = m_item_list.size();
130
131 if (index < 0 || (movement % static_cast<signed>(size)) == 0) {
132 return;
133 }
134
135 int newindex = (index + movement) % static_cast<signed>(size);
136 if (newindex < 0) // neg wrap
137 newindex += size;
138
139 ItemList::iterator it = std::find(m_item_list.begin(),
140 m_item_list.end(),
141 item);
142 m_item_list.erase(it);
143
144 for (it = m_item_list.begin(); newindex >= 0; ++it, --newindex) {
145 if (newindex == 0) {
146 break;
147 }
148 }
149
150 m_item_list.insert(it, item);
151 repositionItems();
152}
153
154// returns true if something was done
155bool Container::moveItemTo(Item item, int x, int y) {
156 Window parent_return=0,
157 root_return=0,
158 *children_return = NULL;
159
160 unsigned int nchildren_return;
161
162 // get the root window
163 if (!XQueryTree(display(), window(),
164 &root_return, &parent_return, &children_return, &nchildren_return))
165 parent_return = parent_return;
166
167 if (children_return != NULL)
168 XFree(children_return);
169
170 int dest_x = 0, dest_y = 0;
171 Window itemwin = 0;
172 if (!XTranslateCoordinates(display(),
173 root_return, window(),
174 x, y, &dest_x, &dest_y,
175 &itemwin))
176 return false;
177
178 ItemList::iterator it = find_if(m_item_list.begin(),
179 m_item_list.end(),
180 CompareWindow(&FbTk::FbWindow::window,
181 itemwin));
182 // not found :(
183 if (it == m_item_list.end())
184 return false;
185
186 Window child_return = 0;
187 //make x and y relative to our item
188 if (!XTranslateCoordinates(display(),
189 window(), itemwin,
190 dest_x, dest_y, &x, &y,
191 &child_return))
192 return false;
193 return true;
194}
195
196bool Container::removeItem(Item item) {
197 ItemList::iterator it = m_item_list.begin();
198 ItemList::iterator it_end = m_item_list.end();
199 for (; it != it_end && (*it) != item; ++it);
200
201 if (it == it_end)
202 return false;
203
204 m_item_list.erase(it);
205 repositionItems();
206 return true;
207}
208
209bool Container::removeItem(int index) {
210 if (index < 0 || index > size())
211 return false;
212
213 ItemList::iterator it = m_item_list.begin();
214 for (; index != 0; ++it, --index)
215 continue;
216
217 m_item_list.erase(it);
218
219 repositionItems();
220 return true;
221}
222
223void Container::removeAll() {
224 m_item_list.clear();
225 if (!m_update_lock) {
226 clear();
227 }
228
229}
230
231int Container::find(ConstItem item) {
232 ItemList::iterator it = m_item_list.begin();
233 ItemList::iterator it_end = m_item_list.end();
234 int index = 0;
235 for (; it != it_end; ++it, ++index) {
236 if ((*it) == item)
237 break;
238 }
239
240 if (it == it_end)
241 return -1;
242
243 return index;
244}
245
246void Container::setMaxSizePerClient(unsigned int size) {
247 if (size != m_max_size_per_client) {
248 m_max_size_per_client = size;
249 repositionItems();
250 }
251}
252
253void Container::setMaxTotalSize(unsigned int size) {
254 if (m_max_total_size == size)
255 return;
256
257 m_max_total_size = size;
258
259 repositionItems();
260 return;
261}
262
263void Container::setAlignment(Container::Alignment a) {
264 m_align = a;
265}
266
267void Container::exposeEvent(XExposeEvent &event) {
268 if (!m_update_lock) {
269 clearArea(event.x, event.y, event.width, event.height);
270 }
271}
272
273bool Container::tryExposeEvent(XExposeEvent &event) {
274 if (event.window == window()) {
275 exposeEvent(event);
276 return true;
277 }
278
279 ItemList::iterator it = find_if(m_item_list.begin(),
280 m_item_list.end(),
281 CompareWindow(&FbTk::FbWindow::window,
282 event.window));
283 // not found :(
284 if (it == m_item_list.end())
285 return false;
286
287 (*it)->exposeEvent(event);
288 return true;
289}
290
291bool Container::tryButtonPressEvent(XButtonEvent &event) {
292 if (event.window == window()) {
293 // we don't have a buttonrelease event atm
294 return true;
295 }
296
297 ItemList::iterator it = find_if(m_item_list.begin(),
298 m_item_list.end(),
299 CompareWindow(&FbTk::FbWindow::window,
300 event.window));
301 // not found :(
302 if (it == m_item_list.end())
303 return false;
304
305 (*it)->buttonPressEvent(event);
306 return true;
307}
308
309bool Container::tryButtonReleaseEvent(XButtonEvent &event) {
310 if (event.window == window()) {
311 // we don't have a buttonrelease event atm
312 return true;
313 }
314
315 ItemList::iterator it = find_if(m_item_list.begin(),
316 m_item_list.end(),
317 CompareWindow(&FbTk::FbWindow::window,
318 event.window));
319 // not found :(
320 if (it == m_item_list.end())
321 return false;
322
323 (*it)->buttonReleaseEvent(event);
324 return true;
325}
326
327void Container::repositionItems() {
328 if (empty() || m_update_lock)
329 return;
330
331 /**
332 NOTE: all calculations here are done in non-rotated space
333 */
334
335 unsigned int max_width_per_client = maxWidthPerClient();
336 unsigned int borderW = m_item_list.front()->borderWidth();
337 size_t num_items = m_item_list.size();
338
339 unsigned int total_width;
340 unsigned int cur_width;
341 unsigned int height;
342
343 // unrotate
344 if (m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) {
345 total_width = cur_width = width();
346 height = this->height();
347 } else {
348 total_width = cur_width = this->height();
349 height = width();
350 }
351
352 // if we have a max total size, then we must also resize ourself
353 // within that bound
354 Alignment align = alignment();
355 if (m_max_total_size && (align == RIGHT || align == LEFT)) {
356 total_width = (max_width_per_client + borderW) * num_items - borderW;
357 if (total_width > m_max_total_size) {
358 total_width = m_max_total_size;
359 if (m_max_total_size > ((num_items - 1)*borderW)) { // don't go negative with unsigned nums
360 max_width_per_client = ( m_max_total_size - (num_items - 1)*borderW ) / num_items;
361 } else
362 max_width_per_client = 1;
363 }
364
365 if (total_width != cur_width) {
366 // calling Container::resize here risks infinite loops
367 unsigned int neww = total_width, newh = height;
368 translateSize(m_orientation, neww, newh);
369 if (align == RIGHT && m_orientation != FbTk::ROT270 || align == LEFT && m_orientation == FbTk::ROT270) {
370 int deltax = 0;
371 int deltay = 0;
372 if (m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180)
373 deltax = - (total_width - cur_width);
374 else
375 deltay = - (total_width - cur_width);
376
377 FbTk::FbWindow::moveResize(x() + deltax, y() + deltay, neww, newh);
378 } else {
379 FbTk::FbWindow::resize(neww, newh);
380 }
381 }
382 }
383
384
385 ItemList::iterator it = m_item_list.begin();
386 const ItemList::iterator it_end = m_item_list.end();
387
388 int rounding_error = 0;
389
390 if (align == RELATIVE || total_width == m_max_total_size) {
391 rounding_error = total_width - ((max_width_per_client + borderW)* num_items - borderW);
392 }
393
394 int next_x = -borderW; // zero so the border of the first shows
395 int extra = 0;
396 int direction = 1;
397 if (align == RIGHT) {
398 direction = -1;
399 next_x = total_width - max_width_per_client - borderW;
400 }
401
402 int tmpx, tmpy;
403 unsigned int tmpw, tmph;
404 for (; it != it_end; ++it, next_x += direction*(max_width_per_client + borderW + extra)) {
405 // we only need to do error stuff with alignment RELATIVE
406 // OR with max_total_size triggered
407 if (rounding_error) {
408 --rounding_error;
409 extra = 1;
410 //counter for different direction
411 if (align == RIGHT && !extra)
412 --next_x;
413 } else {
414 if (extra && align == RIGHT) // last extra
415 ++next_x;
416 extra = 0;
417 }
418 // rotate the x and y coords
419 tmpx = next_x;
420 tmpy = -borderW;
421 tmpw = max_width_per_client + extra;
422 tmph = height;
423
424 FbTk::translateCoords(m_orientation, tmpx, tmpy, total_width, height);
425 FbTk::translatePosition(m_orientation, tmpx, tmpy, tmpw, tmph, borderW);
426 FbTk::translateSize(m_orientation, tmpw, tmph);
427
428 // resize each clients including border in size
429 (*it)->moveResize(tmpx, tmpy,
430 tmpw, tmph);
431
432 // moveresize does a clear
433 }
434
435}
436
437
438unsigned int Container::maxWidthPerClient() const {
439 switch (alignment()) {
440 case RIGHT:
441 case LEFT:
442 return m_max_size_per_client;
443 break;
444 case RELATIVE:
445 if (size() == 0)
446 return width();
447 else {
448 unsigned int borderW = m_item_list.front()->borderWidth();
449 // there're count-1 borders to fit in with the windows
450 // -> 1 per window plus end
451 unsigned int w = width(), h = height();
452 translateSize(m_orientation, w, h);
453 if (w < (size()-1)*borderW)
454 return 1;
455 else
456 return (w - (size() - 1) * borderW) / size();
457 }
458 break;
459 }
460
461 // this will never happen anyway
462 return 1;
463}
464
465void Container::for_each(std::mem_fun_t<void, FbTk::FbWindow> function) {
466 std::for_each(m_item_list.begin(),
467 m_item_list.end(),
468 function);
469}
470
471void Container::setAlpha(unsigned char alpha) {
472 FbTk::FbWindow::setAlpha(alpha);
473 ItemList::iterator it = m_item_list.begin();
474 ItemList::iterator it_end = m_item_list.end();
475 for (; it != it_end; ++it)
476 (*it)->setAlpha(alpha);
477}
478
479void Container::parentMoved() {
480 FbTk::FbWindow::parentMoved();
481 ItemList::iterator it = m_item_list.begin();
482 ItemList::iterator it_end = m_item_list.end();
483 for (; it != it_end; ++it)
484 (*it)->parentMoved();
485}
486
487void Container::invalidateBackground() {
488 FbTk::FbWindow::invalidateBackground();
489 ItemList::iterator it = m_item_list.begin();
490 ItemList::iterator it_end = m_item_list.end();
491 for (; it != it_end; ++it)
492 (*it)->invalidateBackground();
493}
494
495void Container::clear() {
496 ItemList::iterator it = m_item_list.begin();
497 ItemList::iterator it_end = m_item_list.end();
498 for (; it != it_end; ++it)
499 (*it)->clear();
500
501}
502
503void Container::setOrientation(FbTk::Orientation orient) {
504 if (m_orientation == orient)
505 return;
506
507 FbTk::FbWindow::invalidateBackground();
508
509 ItemList::iterator it = m_item_list.begin();
510 ItemList::iterator it_end = m_item_list.end();
511 for (; it != it_end; ++it)
512 (*it)->setOrientation(orient);
513
514 if ((m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) &&
515 (orient == FbTk::ROT90 || orient == FbTk::ROT270) ||
516 (m_orientation == FbTk::ROT90 || m_orientation == FbTk::ROT270) &&
517 (orient == FbTk::ROT0 || orient == FbTk::ROT180)) {
518 // flip width and height
519 m_orientation = orient;
520 resize(height(), width());
521 } else {
522 m_orientation = orient;
523 repositionItems();
524 }
525
526}