1 // Basic element for layouting canvas elements
3 // Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "LayoutItem.hxx"
20 #include <simgear/canvas/Canvas.hxx>
27 //----------------------------------------------------------------------------
28 Margins::Margins(int m):
29 l(m), t(m), r(m), b(m)
34 //----------------------------------------------------------------------------
35 Margins::Margins(int h, int v):
42 //----------------------------------------------------------------------------
43 Margins::Margins(int l, int t, int r, int b):
44 l(l), t(t), r(r), b(b)
49 //----------------------------------------------------------------------------
50 int Margins::horiz() const
55 //----------------------------------------------------------------------------
56 int Margins::vert() const
61 //----------------------------------------------------------------------------
62 SGVec2i Margins::size() const
64 return SGVec2i(horiz(), vert());
67 //----------------------------------------------------------------------------
68 bool Margins::isNull() const
70 return l == 0 && t == 0 && r == 0 && b == 0;
73 //----------------------------------------------------------------------------
74 const SGVec2i LayoutItem::MAX_SIZE( SGLimits<int>::max(),
75 SGLimits<int>::max() );
77 //----------------------------------------------------------------------------
78 LayoutItem::LayoutItem():
87 //----------------------------------------------------------------------------
88 LayoutItem::~LayoutItem()
93 //----------------------------------------------------------------------------
94 void LayoutItem::setContentsMargins(const Margins& margins)
99 //----------------------------------------------------------------------------
100 void LayoutItem::setContentsMargins(int left, int top, int right, int bottom)
108 //----------------------------------------------------------------------------
109 void LayoutItem::setContentsMargin(int margin)
111 setContentsMargins(margin, margin, margin, margin);
114 //----------------------------------------------------------------------------
115 Margins LayoutItem::getContentsMargins() const
120 //----------------------------------------------------------------------------
121 SGRecti LayoutItem::contentsRect() const
124 _geometry.x() + _margins.l,
125 _geometry.y() + _margins.t,
126 std::max(0, _geometry.width() - _margins.horiz()),
127 std::max(0, _geometry.height() - _margins.vert())
131 //----------------------------------------------------------------------------
132 SGVec2i LayoutItem::sizeHint() const
134 if( _flags & SIZE_HINT_DIRTY )
136 _size_hint = sizeHintImpl();
137 _flags &= ~SIZE_HINT_DIRTY;
140 return addClipOverflow(_size_hint, _margins.size());
143 //----------------------------------------------------------------------------
144 SGVec2i LayoutItem::minimumSize() const
146 if( _flags & MINIMUM_SIZE_DIRTY )
148 _min_size = minimumSizeImpl();
149 _flags &= ~MINIMUM_SIZE_DIRTY;
152 return addClipOverflow(_min_size, _margins.size());
155 //----------------------------------------------------------------------------
156 SGVec2i LayoutItem::maximumSize() const
158 if( _flags & MAXIMUM_SIZE_DIRTY )
160 _max_size = maximumSizeImpl();
161 _flags &= ~MAXIMUM_SIZE_DIRTY;
164 return addClipOverflow(_max_size, _margins.size());
167 //----------------------------------------------------------------------------
168 bool LayoutItem::hasHeightForWidth() const
173 //----------------------------------------------------------------------------
174 int LayoutItem::heightForWidth(int w) const
176 int h = heightForWidthImpl(w - _margins.horiz());
177 return h < 0 ? -1 : SGMisc<int>::addClipOverflow(h, _margins.vert());
180 //------------------------------------------------------------------------------
181 int LayoutItem::minimumHeightForWidth(int w) const
183 int h = minimumHeightForWidthImpl(w - _margins.horiz());
184 return h < 0 ? -1 : SGMisc<int>::addClipOverflow(h, _margins.vert());
187 //----------------------------------------------------------------------------
188 void LayoutItem::setVisible(bool visible)
191 _flags &= ~EXPLICITLY_HIDDEN;
193 _flags |= EXPLICITLY_HIDDEN;
195 setVisibleInternal(visible);
198 //----------------------------------------------------------------------------
199 bool LayoutItem::isVisible() const
201 return _flags & VISIBLE;
204 //----------------------------------------------------------------------------
205 bool LayoutItem::isExplicitlyHidden() const
207 return _flags & EXPLICITLY_HIDDEN;
210 //----------------------------------------------------------------------------
211 void LayoutItem::invalidate()
213 _flags |= SIZE_INFO_DIRTY | LAYOUT_DIRTY;
217 //----------------------------------------------------------------------------
218 void LayoutItem::invalidateParent()
220 LayoutItemRef parent = _parent.lock();
222 parent->invalidate();
225 //----------------------------------------------------------------------------
226 void LayoutItem::update()
228 if( (_flags & LAYOUT_DIRTY) && isVisible() )
229 contentsRectChanged( contentsRect() );
232 //----------------------------------------------------------------------------
233 void LayoutItem::setGeometry(const SGRecti& geom)
235 if( geom != _geometry )
238 _flags |= LAYOUT_DIRTY;
244 //----------------------------------------------------------------------------
245 SGRecti LayoutItem::geometry() const
250 //----------------------------------------------------------------------------
251 void LayoutItem::setCanvas(const CanvasWeakPtr& canvas)
256 //----------------------------------------------------------------------------
257 CanvasPtr LayoutItem::getCanvas() const
259 return _canvas.lock();
262 //----------------------------------------------------------------------------
263 void LayoutItem::setParent(const LayoutItemWeakRef& parent)
266 LayoutItemRef parent_ref = parent.lock();
269 // Only change the canvas if there is a new parent. If the item is removed
270 // keep the old canvas, as it may be used for example during the call to
272 setCanvas(parent_ref->_canvas);
274 setVisibleInternal(!parent_ref || parent_ref->isVisible());
277 //----------------------------------------------------------------------------
278 LayoutItemRef LayoutItem::getParent() const
280 return _parent.lock();
283 //----------------------------------------------------------------------------
284 SGVec2i LayoutItem::sizeHintImpl() const
289 //----------------------------------------------------------------------------
290 SGVec2i LayoutItem::minimumSizeImpl() const
295 //----------------------------------------------------------------------------
296 SGVec2i LayoutItem::maximumSizeImpl() const
301 //----------------------------------------------------------------------------
302 int LayoutItem::heightForWidthImpl(int w) const
307 //------------------------------------------------------------------------------
308 int LayoutItem::minimumHeightForWidthImpl(int w) const
310 return heightForWidth(w);
313 //----------------------------------------------------------------------------
314 void LayoutItem::setVisibleInternal(bool visible)
316 LayoutItemRef parent = getParent();
317 if( isExplicitlyHidden() || (parent && !parent->isVisible()) )
320 if( isVisible() == visible )
330 visibilityChanged(visible);
333 //----------------------------------------------------------------------------
334 void LayoutItem::callSetVisibleInternal(LayoutItem* item, bool visible)
336 item->setVisibleInternal(visible);
339 } // namespace canvas
340 } // namespace simgear