diff options
Diffstat (limited to 'src/Container.cc')
-rw-r--r-- | src/Container.cc | 526 |
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 | |||
33 | Container::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 | |||
43 | Container::~Container() { | ||
44 | // ~FbWindow cleans event manager | ||
45 | } | ||
46 | |||
47 | void 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 | |||
57 | void 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 | ||
64 | void Container::move(int x, int y) { | ||
65 | FbTk::FbWindow::move(x, y); | ||
66 | // no need to reposition | ||
67 | } | ||
68 | |||
69 | void 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 | |||
99 | void 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 | |||
126 | void 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 | ||
155 | bool 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 | |||
196 | bool 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 | |||
209 | bool 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 | |||
223 | void Container::removeAll() { | ||
224 | m_item_list.clear(); | ||
225 | if (!m_update_lock) { | ||
226 | clear(); | ||
227 | } | ||
228 | |||
229 | } | ||
230 | |||
231 | int 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 | |||
246 | void 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 | |||
253 | void 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 | |||
263 | void Container::setAlignment(Container::Alignment a) { | ||
264 | m_align = a; | ||
265 | } | ||
266 | |||
267 | void Container::exposeEvent(XExposeEvent &event) { | ||
268 | if (!m_update_lock) { | ||
269 | clearArea(event.x, event.y, event.width, event.height); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | bool 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 | |||
291 | bool 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 | |||
309 | bool 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 | |||
327 | void 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 | |||
438 | unsigned 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 | |||
465 | void 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 | |||
471 | void 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 | |||
479 | void 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 | |||
487 | void 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 | |||
495 | void 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 | |||
503 | void 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 | } | ||