FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
dockarea.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE:: *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <algorithm>
24 #include <cassert>
25 
26 // 3rd party library includes
27 
28 // FIFE includes
29 // These includes are split up in two parts, separated by one empty line
30 // First block: files included from the FIFE root src directory
31 // Second block: files included from the same folder
33 #include "util/base/exception.h"
34 
35 #include "dockarea.h"
36 
37 namespace fcn {
39  m_activeDockArea(true),
40  m_topSide(false),
41  m_rightSide(false),
42  m_bottomSide(false),
43  m_leftSide(false),
44  m_highlighted(false),
45  m_highlightColor(0xc80000)
46  {
47  setMovable(false);
48  setMargin(0);
49  setPadding(0);
50  setTopResizable(false);
51  setRightResizable(false);
52  setBottomResizable(false);
53  setLeftResizable(false);
54 
55  }
56 
57  DockArea::DockArea(bool active):
58  m_activeDockArea(active),
59  m_topSide(false),
60  m_rightSide(false),
61  m_bottomSide(false),
62  m_leftSide(false),
63  m_highlighted(false),
64  m_highlightColor(0xc80000)
65  {
66  setMovable(false);
67  setMargin(0);
68  setPadding(0);
69  setTopResizable(false);
70  setRightResizable(false);
71  setBottomResizable(false);
72  setLeftResizable(false);
73 
74  }
75 
77  }
78 
79  void DockArea::setActiveDockArea(bool active) {
80  m_activeDockArea = active;
81  }
82 
84  return m_activeDockArea;
85  }
86 
87  void DockArea::setTopSide(bool side) {
88  m_topSide = side;
90  if (side) {
91  setLayout(Container::Horizontal);
92  }
93  }
94 
95  bool DockArea::isTopSide() const {
96  return m_topSide;
97  }
98 
99  void DockArea::setRightSide(bool side) {
100  m_rightSide = side;
102  if (side) {
103  setLayout(Container::Vertical);
104  }
105  }
106 
107  bool DockArea::isRightSide() const {
108  return m_rightSide;
109  }
110 
111  void DockArea::setBottomSide(bool side) {
112  m_bottomSide = side;
114  if (side) {
115  setLayout(Container::Horizontal);
116  }
117  }
118 
119  bool DockArea::isBottomSide() const {
120  return m_bottomSide;
121  }
122 
123  void DockArea::setLeftSide(bool side) {
124  m_leftSide = side;
126  if (side) {
127  setLayout(Container::Vertical);
128  }
129  }
130 
131  bool DockArea::isLeftSide() const {
132  return m_leftSide;
133  }
134 
135  void DockArea::dockWidget(Widget* widget) {
136  add(widget);
137  }
138 
139  void DockArea::undockWidget(Widget* widget) {
140  remove(widget);
141  }
142 
143  void DockArea::setHighlighted(bool highlighted) {
144  if (highlighted != m_highlighted) {
145  if (highlighted) {
146  m_savedColor = getBaseColor();
147  setBaseColor(m_highlightColor);
148  } else {
149  setBaseColor(m_savedColor);
150  }
151  m_highlighted = highlighted;
152  }
153  }
154 
155  bool DockArea::isHighlighted() const {
156  return m_highlighted;
157  }
158 
159  void DockArea::setHighlightColor(const Color& color) {
160  m_highlightColor = color;
161  }
162 
163  const Color& DockArea::getHighlightColor() const {
164  return m_highlightColor;
165  }
166 
167  void DockArea::repositionWidget(Widget* widget) {
168  Widget* placeBefore = NULL;
169  Widget* placeAfter = NULL;
170 
171  Rectangle dim = widget->getDimension();
172  widget->getAbsolutePosition(dim.x, dim.y);
173  std::list<Widget*>::const_iterator currChild(mChildren.begin());
174  std::list<Widget*>::const_iterator endChildren(mChildren.end());
175  for(; currChild != endChildren; ++currChild) {
176  if (!(*currChild)->isVisible() || (*currChild) == widget) {
177  continue;
178  }
179  Rectangle childDim = (*currChild)->getDimension();
180  (*currChild)->getAbsolutePosition(childDim.x, childDim.y);
181  if (childDim.isIntersecting(dim)) {
182  if (getLayout() == Container::Horizontal) {
183  if (dim.x < childDim.x) {
184  if (dim.x + dim.width <= childDim.x + childDim.width / 2) {
185  placeBefore = *currChild;
186  } else {
187  placeAfter = *currChild;
188  }
189  } else if (dim.x >= childDim.x) {
190  if (dim.x <= childDim.x + childDim.width / 2) {
191  placeBefore = *currChild;
192  } else {
193  placeAfter = *currChild;
194  }
195  }
196  }
197  if (getLayout() == Container::Vertical) {
198  if (dim.y < childDim.y) {
199  if (dim.y + dim.height <= childDim.y + childDim.height / 2) {
200  placeBefore = *currChild;
201  } else {
202  placeAfter = *currChild;
203  }
204  } else if (dim.y >= childDim.y) {
205  if (dim.y <= childDim.y + childDim.height / 2) {
206  placeBefore = *currChild;
207  } else {
208  placeAfter = *currChild;
209  }
210  }
211  }
212  }
213  }
214  if (placeBefore || placeAfter) {
215  mChildren.remove(widget);
216  if (placeBefore) {
217  std::list<Widget*>::iterator it = std::find(mChildren.begin(), mChildren.end(), placeBefore);
218  mChildren.insert(it, widget);
219  } else {
220  std::list<Widget*>::iterator it = std::find(mChildren.begin(), mChildren.end(), placeAfter);
221  ++it;
222  mChildren.insert(it, widget);
223  }
224  adaptLayout(false);
225  }
226  }
227 
229  Widget* parent = getParent();
230  if (parent) {
231  DockArea* top = NULL;
232  DockArea* right = NULL;
233  DockArea* bottom = NULL;
234  DockArea* left = NULL;
235  std::list<Widget*> widgets = parent->getWidgetsIn(parent->getChildrenArea());
236  std::list<Widget*>::iterator it = widgets.begin();
237  for (; it != widgets.end(); ++it) {
238  DockArea* tmp = dynamic_cast<DockArea*>(*it);
239  if (!tmp) {
240  continue;
241  }
242  tmp->keepInBounds();
243  if (tmp->isTopSide()) {
244  top = tmp;
245  } else if (tmp->isRightSide()) {
246  right = tmp;
247  } else if (tmp->isBottomSide()) {
248  bottom = tmp;
249  } else if (tmp->isLeftSide()) {
250  left = tmp;
251  }
252  }
253 
254  if (top) {
255  if (right) {
256  if (top->getY() + top->getHeight() >= right->getY() || top->getY() + top->getHeight() + 1 < right->getY()) {
257  int32_t newY = top->getY() + top->getHeight() + 1;
258  int32_t diff = newY - right->getY();
259  right->setY(newY);
260  right->setHeight(right->getHeight() + diff);
261  }
262  }
263  if (left) {
264  if (top->getY() + top->getHeight() >= left->getY() || top->getY() + top->getHeight() + 1 < left->getY()) {
265  int32_t newY = top->getY() + top->getHeight() + 1;
266  int32_t diff = newY - left->getY();
267  left->setY(newY);
268  left->setHeight(left->getHeight() + diff);
269  }
270  }
271  if (bottom) {
272  if (top->getY() + top->getHeight() >= bottom->getY()) {
273  int32_t newY = top->getY() + top->getHeight() + 1;
274  int32_t diff = newY - bottom->getY();
275  bottom->setY(newY);
276  bottom->setHeight(bottom->getHeight() + diff);
277  }
278  }
279  }
280 
281  if (bottom) {
282  if (right) {
283  if (right->getY() + right->getHeight() >= bottom->getY() || right->getY() + right->getHeight() + 1 < bottom->getY()) {
284  Size min = right->getMinSize();
285  Size tmp;
286  right->setMinSize(tmp);
287  int32_t diff = bottom->getY() - (right->getY() + right->getHeight() + 1);
288  right->setHeight(right->getHeight() + diff);
289  right->setMinSize(min);
290  }
291  }
292  if (left) {
293  if (left->getY() + left->getHeight() >= bottom->getY() || left->getY() + left->getHeight() + 1 < bottom->getY()) {
294  Size min = left->getMinSize();
295  Size tmp;
296  left->setMinSize(tmp);
297  int32_t diff = bottom->getY() - (left->getY() + left->getHeight() + 1);
298  left->setHeight(left->getHeight() + diff);
299  left->setMinSize(min);
300  }
301  }
302  }
303  }
304  }
305 
307  Widget* parent = getParent();
308  if (!parent) {
309  return;
310  }
311  Rectangle childArea = parent->getChildrenArea();
312  Rectangle childDim = getDimension();
313  if (childDim.x < childArea.x) {
314  setX(childArea.x);
315  }
316  if (childDim.y < childArea.y) {
317  setY(childArea.y);
318  }
319 
320  if (m_topSide) {
321  if ((childDim.y + childDim.height) > childArea.height) {
322  setHeight(childArea.height - childDim.y);
323  }
324  } else if (m_rightSide) {
325  if ((childDim.x + childDim.width) > childArea.width) {
326  if (childDim.width > childArea.width) {
327  setX(childArea.x);
328  setWidth(childArea.width);
329  } else {
330  setX(childArea.width - childDim.width);
331  }
332  }
333  } else if (m_bottomSide) {
334  if ((childDim.y + childDim.height) > childArea.height) {
335  if (childDim.height > childArea.height) {
336  setY(childArea.y);
337  setHeight(childArea.height);
338  } else {
339  setY(childArea.height - childDim.height);
340  }
341  }
342  } else if (m_leftSide) {
343  if ((childDim.x + childDim.width) > childArea.width) {
344  setWidth(childArea.width - childDim.x);
345  }
346  }
347  }
348 
349  void DockArea::add(Widget* widget) {
350  ResizableWindow::add(widget);
351  int32_t x = widget->getX();
352  int32_t y = widget->getY();
353  adaptLayout(true);
354  widget->setPosition(x, y);
355  repositionWidget(widget);
356  requestMoveToTop();
357  }
358 
359  void DockArea::remove(Widget* widget) {
360  ResizableWindow::remove(widget);
361  adaptLayout(false);
362  }
363 
364  void DockArea::resizeToContent(bool recursiv) {
365  Rectangle oldDimension = getDimension();
366  if (m_resizing) {
368  } else {
369  Window::resizeToContent(recursiv);
370  }
371  if (isRightSide()) {
372  int32_t wDiff = oldDimension.width - getWidth();
373  setX(oldDimension.x + wDiff);
374  } else if (isBottomSide()) {
375  int32_t hDiff = oldDimension.height - getHeight();
376  setY(oldDimension.y + hDiff);
377  }
379  }
380 
381  void DockArea::expandContent(bool recursiv) {
382  Rectangle oldDimension = getDimension();
383  if (m_resizing) {
384  ResizableWindow::expandContent(recursiv);
385  } else {
386  Window::expandContent(recursiv);
387  }
388  if (isRightSide()) {
389  int32_t wDiff = oldDimension.width - getWidth();
390  setX(oldDimension.x + wDiff);
391  } else if (isBottomSide()) {
392  int32_t hDiff = oldDimension.height - getHeight();
393  setY(oldDimension.y + hDiff);
394  }
396  }
397 
398  void DockArea::mouseEntered(MouseEvent& mouseEvent) {
399  if (!m_highlighted) {
400  ResizableWindow::mouseEntered(mouseEvent);
401  }
402  }
403 
404  void DockArea::mouseExited(MouseEvent& mouseEvent) {
405  if (!m_highlighted) {
406  ResizableWindow::mouseExited(mouseEvent);
407  }
408  }
409 
410  void DockArea::mousePressed(MouseEvent& mouseEvent) {
411  if (!m_highlighted) {
412  ResizableWindow::mousePressed(mouseEvent);
413  }
414  }
415 
416  void DockArea::mouseReleased(MouseEvent& mouseEvent) {
417  if (!m_highlighted) {
418  ResizableWindow::mouseReleased(mouseEvent);
419  if (m_resizing) {
421  }
422  }
423  }
424 
425  void DockArea::mouseMoved(MouseEvent& mouseEvent) {
426  if (!m_highlighted) {
427  ResizableWindow::mouseMoved(mouseEvent);
428  }
429  }
430 
431  void DockArea::mouseDragged(MouseEvent& mouseEvent) {
432  if (!m_highlighted) {
433  ResizableWindow::mouseDragged(mouseEvent);
434  if (m_resizing) {
436  }
437  }
438  }
439 }
virtual void mouseEntered(MouseEvent &mouseEvent)
Definition: dockarea.cpp:398
virtual void mouseExited(MouseEvent &mouseEvent)
Definition: dockarea.cpp:404
virtual void mousePressed(MouseEvent &mouseEvent)
virtual void mouseExited(MouseEvent &mouseEvent)
virtual void mouseReleased(MouseEvent &mouseEvent)
void setHighlighted(bool highlighted)
Definition: dockarea.cpp:143
virtual ~DockArea()
Definition: dockarea.cpp:76
Color m_savedColor
Definition: dockarea.h:119
virtual void mouseMoved(MouseEvent &mouseEvent)
void setHighlightColor(const Color &color)
Sets the highlight color of the widget.
Definition: dockarea.cpp:159
void setBottomResizable(bool resizable)
Sets if the widget is resizable at bottom.
void repositionDockAreas()
Definition: dockarea.cpp:228
void setTopSide(bool side)
Definition: dockarea.cpp:87
virtual void mouseDragged(MouseEvent &mouseEvent)
Definition: dockarea.cpp:431
virtual void resizeToContent(bool recursiv=true)
void setLeftSide(bool side)
Definition: dockarea.cpp:123
virtual void mouseMoved(MouseEvent &mouseEvent)
Definition: dockarea.cpp:425
bool isRightSide() const
Definition: dockarea.cpp:107
virtual void add(Widget *widget)
Definition: dockarea.cpp:349
virtual void resizeToContent(bool recursiv=true)
Definition: dockarea.cpp:364
bool m_activeDockArea
Definition: dockarea.h:109
bool isBottomSide() const
Definition: dockarea.cpp:119
bool isActiveDockArea() const
Definition: dockarea.cpp:83
bool m_highlighted
Definition: dockarea.h:116
bool m_leftSide
Definition: dockarea.h:114
void setTopResizable(bool resizable)
Sets if the widget is resizable at top.
virtual void remove(Widget *widget)
Definition: dockarea.cpp:359
bool isHighlighted() const
Definition: dockarea.cpp:155
void setLeftResizable(bool resizable)
Sets if the widget is resizable at left.
virtual void mouseReleased(MouseEvent &mouseEvent)
Definition: dockarea.cpp:416
void setBottomSide(bool side)
Definition: dockarea.cpp:111
void keepInBounds()
Definition: dockarea.cpp:306
bool m_bottomSide
Definition: dockarea.h:113
void undockWidget(Widget *widget)
Definition: dockarea.cpp:139
bool isLeftSide() const
Definition: dockarea.cpp:131
void repositionWidget(Widget *widget)
Definition: dockarea.cpp:167
bool m_topSide
Definition: dockarea.h:111
void setRightSide(bool side)
Definition: dockarea.cpp:99
virtual void mouseDragged(MouseEvent &mouseEvent)
virtual void mousePressed(MouseEvent &mouseEvent)
Definition: dockarea.cpp:410
const Color & getHighlightColor() const
Gets the highlight color.
Definition: dockarea.cpp:163
Color m_highlightColor
Definition: dockarea.h:118
virtual void mouseEntered(MouseEvent &mouseEvent)
void setActiveDockArea(bool active)
Definition: dockarea.cpp:79
bool m_rightSide
Definition: dockarea.h:112
void setRightResizable(bool resizable)
Sets if the widget is resizable at right.
virtual void expandContent(bool recursiv=true)
Definition: dockarea.cpp:381
bool isTopSide() const
Definition: dockarea.cpp:95
void dockWidget(Widget *widget)
Definition: dockarea.cpp:135