From 76fc47b24b2481b64b90bbad0ea8ac7d2bf7d7ef Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Tue, 22 Jul 2014 00:48:42 +0200 Subject: [PATCH] canvas::Layout: support for contents margins. --- simgear/canvas/Canvas.cxx | 13 +- simgear/canvas/Canvas.hxx | 3 +- simgear/canvas/layout/BoxLayout.cxx | 41 ++--- simgear/canvas/layout/BoxLayout.hxx | 5 +- simgear/canvas/layout/Layout.cxx | 38 +---- simgear/canvas/layout/Layout.hxx | 10 +- simgear/canvas/layout/LayoutItem.cxx | 127 +++++++++++++- simgear/canvas/layout/LayoutItem.hxx | 164 ++++++++++++++++++- simgear/canvas/layout/NasalWidget.cxx | 91 +++++----- simgear/canvas/layout/NasalWidget.hxx | 9 +- simgear/canvas/layout/canvas_layout_test.cxx | 102 +++++++++++- 11 files changed, 456 insertions(+), 147 deletions(-) diff --git a/simgear/canvas/Canvas.cxx b/simgear/canvas/Canvas.cxx index c7898b45..5ca1eb95 100644 --- a/simgear/canvas/Canvas.cxx +++ b/simgear/canvas/Canvas.cxx @@ -196,7 +196,6 @@ namespace canvas { _layout = layout; _layout->setCanvas(this); - _status |= LAYOUT_DIRTY; } //---------------------------------------------------------------------------- @@ -256,15 +255,7 @@ namespace canvas } if( _layout ) - { - if( (_status & LAYOUT_DIRTY) ) - { - _layout->setGeometry(SGRecti(0, 0, _view_width, _view_height)); - _status &= ~LAYOUT_DIRTY; - } - else - _layout->update(); - } + _layout->setGeometry(SGRecti(0, 0, _view_width, _view_height)); if( _visible || _render_always ) { @@ -410,7 +401,6 @@ namespace canvas if( _view_width == w ) return; _view_width = w; - _status |= LAYOUT_DIRTY; _texture.setViewSize(_view_width, _view_height); } @@ -421,7 +411,6 @@ namespace canvas if( _view_height == h ) return; _view_height = h; - _status |= LAYOUT_DIRTY; _texture.setViewSize(_view_width, _view_height); } diff --git a/simgear/canvas/Canvas.hxx b/simgear/canvas/Canvas.hxx index 2c817f61..cf9ae2a5 100644 --- a/simgear/canvas/Canvas.hxx +++ b/simgear/canvas/Canvas.hxx @@ -53,8 +53,7 @@ namespace canvas { STATUS_OK, STATUS_DIRTY = 1, - LAYOUT_DIRTY = STATUS_DIRTY << 1, - MISSING_SIZE_X = LAYOUT_DIRTY << 1, + MISSING_SIZE_X = STATUS_DIRTY << 1, MISSING_SIZE_Y = MISSING_SIZE_X << 1, MISSING_SIZE = MISSING_SIZE_X | MISSING_SIZE_Y, CREATE_FAILED = MISSING_SIZE_Y << 1 diff --git a/simgear/canvas/layout/BoxLayout.cxx b/simgear/canvas/layout/BoxLayout.cxx index 3da5d98e..3e1d37ff 100644 --- a/simgear/canvas/layout/BoxLayout.cxx +++ b/simgear/canvas/layout/BoxLayout.cxx @@ -229,26 +229,6 @@ namespace canvas return _layout_data.has_hfw; } - //---------------------------------------------------------------------------- - int BoxLayout::heightForWidth(int w) const - { - if( !hasHeightForWidth() ) - return -1; - - updateWFHCache(w); - return _hfw_height; - } - - //---------------------------------------------------------------------------- - int BoxLayout::minimumHeightForWidth(int w) const - { - if( !hasHeightForWidth() ) - return -1; - - updateWFHCache(w); - return _hfw_min_height; - } - //---------------------------------------------------------------------------- void BoxLayout::setCanvas(const CanvasWeakPtr& canvas) { @@ -400,6 +380,27 @@ namespace canvas return _max_size; } + + //---------------------------------------------------------------------------- + int BoxLayout::heightForWidthImpl(int w) const + { + if( !hasHeightForWidth() ) + return -1; + + updateWFHCache(w); + return _hfw_height; + } + + //---------------------------------------------------------------------------- + int BoxLayout::minimumHeightForWidthImpl(int w) const + { + if( !hasHeightForWidth() ) + return -1; + + updateWFHCache(w); + return _hfw_min_height; + } + //---------------------------------------------------------------------------- void BoxLayout::doLayout(const SGRecti& geom) { diff --git a/simgear/canvas/layout/BoxLayout.hxx b/simgear/canvas/layout/BoxLayout.hxx index 639871e9..1978439a 100644 --- a/simgear/canvas/layout/BoxLayout.hxx +++ b/simgear/canvas/layout/BoxLayout.hxx @@ -86,8 +86,6 @@ namespace canvas Direction direction() const; virtual bool hasHeightForWidth() const; - virtual int heightForWidth(int w) const; - virtual int minimumHeightForWidth(int w) const; virtual void setCanvas(const CanvasWeakPtr& canvas); @@ -121,6 +119,9 @@ namespace canvas virtual SGVec2i minimumSizeImpl() const; virtual SGVec2i maximumSizeImpl() const; + virtual int heightForWidthImpl(int w) const; + virtual int minimumHeightForWidthImpl(int w) const; + virtual void doLayout(const SGRecti& geom); virtual void visibilityChanged(bool visible); diff --git a/simgear/canvas/layout/Layout.cxx b/simgear/canvas/layout/Layout.cxx index d3ae3886..ee24be6e 100644 --- a/simgear/canvas/layout/Layout.cxx +++ b/simgear/canvas/layout/Layout.cxx @@ -24,36 +24,6 @@ namespace simgear namespace canvas { - //---------------------------------------------------------------------------- - void Layout::update() - { - if( !(_flags & (LAYOUT_DIRTY | SIZE_INFO_DIRTY)) || !isVisible() ) - return; - - doLayout(_geometry); - - _flags &= ~LAYOUT_DIRTY; - } - - //---------------------------------------------------------------------------- - void Layout::invalidate() - { - LayoutItem::invalidate(); - _flags |= LAYOUT_DIRTY; - } - - //---------------------------------------------------------------------------- - void Layout::setGeometry(const SGRecti& geom) - { - if( geom != _geometry ) - { - _geometry = geom; - _flags |= LAYOUT_DIRTY; - } - - update(); - } - //---------------------------------------------------------------------------- void Layout::removeItem(const LayoutItemRef& item) { @@ -108,6 +78,14 @@ namespace canvas return layout_item->minimumSize().y(); } + //---------------------------------------------------------------------------- + void Layout::contentsRectChanged(const SGRecti& rect) + { + doLayout(rect); + + _flags &= ~LAYOUT_DIRTY; + } + //---------------------------------------------------------------------------- void Layout::distribute(std::vector& items, const ItemData& space) { diff --git a/simgear/canvas/layout/Layout.hxx b/simgear/canvas/layout/Layout.hxx index f28763cb..e543db25 100644 --- a/simgear/canvas/layout/Layout.hxx +++ b/simgear/canvas/layout/Layout.hxx @@ -31,11 +31,6 @@ namespace canvas public LayoutItem { public: - void update(); - - virtual void invalidate(); - virtual void setGeometry(const SGRecti& geom); - virtual void addItem(const LayoutItemRef& item) = 0; virtual void setSpacing(int spacing) = 0; virtual int spacing() const = 0; @@ -74,8 +69,7 @@ namespace canvas protected: enum LayoutFlags { - LAYOUT_DIRTY = LayoutItem::LAST_FLAG << 1, - LAST_FLAG = LAYOUT_DIRTY + LAST_FLAG = LayoutItem::LAST_FLAG }; struct ItemData @@ -99,6 +93,8 @@ namespace canvas int mhfw(int w) const; }; + virtual void contentsRectChanged(const SGRecti& rect); + /** * Override to implement the actual layouting */ diff --git a/simgear/canvas/layout/LayoutItem.cxx b/simgear/canvas/layout/LayoutItem.cxx index a6e30dfb..f585b257 100644 --- a/simgear/canvas/layout/LayoutItem.cxx +++ b/simgear/canvas/layout/LayoutItem.cxx @@ -23,6 +23,54 @@ namespace simgear { namespace canvas { + + //---------------------------------------------------------------------------- + Margins::Margins(int m): + l(m), t(m), r(m), b(m) + { + + } + + //---------------------------------------------------------------------------- + Margins::Margins(int h, int v): + l(h), t(v), + r(h), b(v) + { + + } + + //---------------------------------------------------------------------------- + Margins::Margins(int l, int t, int r, int b): + l(l), t(t), r(r), b(b) + { + + } + + //---------------------------------------------------------------------------- + int Margins::horiz() const + { + return l + r; + } + + //---------------------------------------------------------------------------- + int Margins::vert() const + { + return t + b; + } + + //---------------------------------------------------------------------------- + SGVec2i Margins::size() const + { + return SGVec2i(horiz(), vert()); + } + + //---------------------------------------------------------------------------- + bool Margins::isNull() const + { + return l == 0 && t == 0 && r == 0 && b == 0; + } + + //---------------------------------------------------------------------------- const SGVec2i LayoutItem::MAX_SIZE( SGLimits::max(), SGLimits::max() ); @@ -42,6 +90,44 @@ namespace canvas } + //---------------------------------------------------------------------------- + void LayoutItem::setContentsMargins(const Margins& margins) + { + _margins = margins; + } + + //---------------------------------------------------------------------------- + void LayoutItem::setContentsMargins(int left, int top, int right, int bottom) + { + _margins.l = left; + _margins.t = top; + _margins.r = right; + _margins.b = bottom; + } + + //---------------------------------------------------------------------------- + void LayoutItem::setContentsMargin(int margin) + { + setContentsMargins(margin, margin, margin, margin); + } + + //---------------------------------------------------------------------------- + Margins LayoutItem::getContentsMargins() const + { + return _margins; + } + + //---------------------------------------------------------------------------- + SGRecti LayoutItem::contentsRect() const + { + return SGRecti( + _geometry.x() + _margins.l, + _geometry.y() + _margins.t, + std::max(0, _geometry.width() - _margins.horiz()), + std::max(0, _geometry.height() - _margins.vert()) + ); + } + //---------------------------------------------------------------------------- SGVec2i LayoutItem::sizeHint() const { @@ -51,7 +137,7 @@ namespace canvas _flags &= ~SIZE_HINT_DIRTY; } - return _size_hint; + return addClipOverflow(_size_hint, _margins.size()); } //---------------------------------------------------------------------------- @@ -63,7 +149,7 @@ namespace canvas _flags &= ~MINIMUM_SIZE_DIRTY; } - return _min_size; + return addClipOverflow(_min_size, _margins.size()); } //---------------------------------------------------------------------------- @@ -75,7 +161,7 @@ namespace canvas _flags &= ~MAXIMUM_SIZE_DIRTY; } - return _max_size; + return addClipOverflow(_max_size, _margins.size()); } //---------------------------------------------------------------------------- @@ -87,13 +173,15 @@ namespace canvas //---------------------------------------------------------------------------- int LayoutItem::heightForWidth(int w) const { - return -1; + int h = heightForWidthImpl(w - _margins.horiz()); + return h < 0 ? -1 : SGMisc::addClipOverflow(h, _margins.vert()); } //------------------------------------------------------------------------------ int LayoutItem::minimumHeightForWidth(int w) const { - return heightForWidth(w); + int h = minimumHeightForWidthImpl(w - _margins.horiz()); + return h < 0 ? -1 : SGMisc::addClipOverflow(h, _margins.vert()); } //---------------------------------------------------------------------------- @@ -122,7 +210,7 @@ namespace canvas //---------------------------------------------------------------------------- void LayoutItem::invalidate() { - _flags |= SIZE_INFO_DIRTY; + _flags |= SIZE_INFO_DIRTY | LAYOUT_DIRTY; invalidateParent(); } @@ -134,10 +222,23 @@ namespace canvas parent->invalidate(); } + //---------------------------------------------------------------------------- + void LayoutItem::update() + { + if( (_flags & LAYOUT_DIRTY) && isVisible() ) + contentsRectChanged( contentsRect() ); + } + //---------------------------------------------------------------------------- void LayoutItem::setGeometry(const SGRecti& geom) { - _geometry = geom; + if( geom != _geometry ) + { + _geometry = geom; + _flags |= LAYOUT_DIRTY; + } + + update(); } //---------------------------------------------------------------------------- @@ -197,6 +298,18 @@ namespace canvas return _max_size; } + //---------------------------------------------------------------------------- + int LayoutItem::heightForWidthImpl(int w) const + { + return -1; + } + + //------------------------------------------------------------------------------ + int LayoutItem::minimumHeightForWidthImpl(int w) const + { + return heightForWidth(w); + } + //---------------------------------------------------------------------------- void LayoutItem::setVisibleInternal(bool visible) { diff --git a/simgear/canvas/layout/LayoutItem.hxx b/simgear/canvas/layout/LayoutItem.hxx index e26e032f..130c47c5 100644 --- a/simgear/canvas/layout/LayoutItem.hxx +++ b/simgear/canvas/layout/LayoutItem.hxx @@ -34,6 +34,53 @@ namespace canvas typedef SGSharedPtr LayoutItemRef; typedef SGWeakPtr LayoutItemWeakRef; + /** + * Holds the four margins for a rectangle. + */ + struct Margins + { + int l, t, r, b; + + /** + * Set all margins to the same value @a m. + */ + explicit Margins(int m = 0); + + /** + * Set horizontal and vertical margins to the same values @a h and @a v + * respectively. + * + * @param h Horizontal margins + * @param v Vertical margins + */ + Margins(int h, int v); + + /** + * Set the margins to the given values. + */ + Margins(int left, int top, int right, int bottom); + + /** + * Get the total horizontal margin (sum of left and right margin). + */ + int horiz() const; + + /** + * Get the total vertical margin (sum of top and bottom margin). + */ + int vert() const; + + /** + * Get total horizontal and vertical margin as vector. + */ + SGVec2i size() const; + + /** + * Returns true if all margins are 0. + */ + bool isNull() const; + }; + /** * Base class for all layouting elements. Specializations either implement a * layouting algorithm or a widget. @@ -49,6 +96,49 @@ namespace canvas LayoutItem(); virtual ~LayoutItem(); + /** + * Set the margins to use by the layout system around the item. + * + * The margins define the size of the clear area around an item. It + * increases the size hints and reduces the size of the geometry() + * available to child layouts and widgets. + * + * @see Margins + */ + void setContentsMargins(const Margins& margins); + + /** + * Set the individual margins. + * + * @see setContentsMargins(const Margins&) + */ + void setContentsMargins(int left, int top, int right, int bottom); + + /** + * Set all margins to the same value. + * + * @see setContentsMargins(const Margins&) + */ + void setContentsMargin(int margin); + + /** + * Get the currently used margins. + * + * @see setContentsMargins(const Margins&) + * @see Margins + */ + Margins getContentsMargins() const; + + /** + * Get the area available to the contents. + * + * This is equal to the geometry() reduced by the sizes of the margins. + * + * @see setContentsMargins(const Margins&) + * @see geometry() + */ + SGRecti contentsRect() const; + /** * Get the preferred size of this item. */ @@ -64,9 +154,36 @@ namespace canvas */ SGVec2i maximumSize() const; + /** + * Returns true if this items preferred and minimum height depend on its + * width. + * + * The default implementation returns false. Reimplement for items + * providing height for width. + * + * @see heightForWidth() + * @see minimumHeightForWidth() + */ virtual bool hasHeightForWidth() const; - virtual int heightForWidth(int w) const; - virtual int minimumHeightForWidth(int w) const; + + /** + * Returns the preferred height for the given width @q w. + * + * Reimplement heightForWidthImpl() for items providing height for width. + * + * @see hasHeightForWidth() + */ + int heightForWidth(int w) const; + + /** + * Returns the minimum height for the given width @q w. + * + * Reimplement minimumHeightForWidthImpl() for items providing height for + * width. + * + * @see hasHeightForWidth() + */ + int minimumHeightForWidth(int w) const; virtual void setVisible(bool visible); virtual bool isVisible() const; @@ -82,10 +199,15 @@ namespace canvas virtual void invalidate(); /** - * Mark all cached data of parent item as invalid (if it is known) + * Mark all cached data of parent item as invalid (if the parent is set). */ void invalidateParent(); + /** + * Apply any changes not applied yet. + */ + void update(); + /** * Set position and size of this element. For layouts this triggers a * recalculation of the layout. @@ -134,13 +256,15 @@ namespace canvas | MAXIMUM_SIZE_DIRTY, EXPLICITLY_HIDDEN = MAXIMUM_SIZE_DIRTY << 1, VISIBLE = EXPLICITLY_HIDDEN << 1, - LAST_FLAG = VISIBLE + LAYOUT_DIRTY = VISIBLE << 1, + LAST_FLAG = LAYOUT_DIRTY }; CanvasWeakPtr _canvas; LayoutItemWeakRef _parent; SGRecti _geometry; + Margins _margins; mutable uint32_t _flags; mutable SGVec2i _size_hint, @@ -151,11 +275,43 @@ namespace canvas virtual SGVec2i minimumSizeImpl() const; virtual SGVec2i maximumSizeImpl() const; + /** + * Returns the preferred height for the given width @q w. + * + * The default implementation returns -1, indicating that the preferred + * height is independent of the given width. + * + * Reimplement this function for items supporting height for width. + * + * @note Do not take margins into account, as this is already handled + * before calling this function. + * + * @see hasHeightForWidth() + */ + virtual int heightForWidthImpl(int w) const; + + /** + * Returns the minimum height for the given width @q w. + * + * The default implementation returns -1, indicating that the minimum + * height is independent of the given width. + * + * Reimplement this function for items supporting height for width. + * + * @note Do not take margins into account, as this is already handled + * before calling this function. + * + * @see hasHeightForWidth() + */ + virtual int minimumHeightForWidthImpl(int w) const; + /** * @return whether the visibility has changed. */ void setVisibleInternal(bool visible); + virtual void contentsRectChanged(const SGRecti& rect) {}; + virtual void visibilityChanged(bool visible) {} /** diff --git a/simgear/canvas/layout/NasalWidget.cxx b/simgear/canvas/layout/NasalWidget.cxx index 0cf172e1..5c027e85 100644 --- a/simgear/canvas/layout/NasalWidget.cxx +++ b/simgear/canvas/layout/NasalWidget.cxx @@ -46,41 +46,6 @@ namespace canvas onRemove(); } - //---------------------------------------------------------------------------- - void NasalWidget::invalidate() - { - LayoutItem::invalidate(); - _flags |= LAYOUT_DIRTY; - } - - //---------------------------------------------------------------------------- - void NasalWidget::setGeometry(const SGRect& geom) - { - if( _geometry != geom ) - { - _geometry = geom; - _flags |= LAYOUT_DIRTY; - } - - if( !_set_geometry || !(_flags & LAYOUT_DIRTY) ) - return; - - try - { - nasal::Context c; - _set_geometry(nasal::to_nasal(c, this), geom); - _flags &= ~LAYOUT_DIRTY; - } - catch( std::exception const& ex ) - { - SG_LOG( - SG_GUI, - SG_WARN, - "NasalWidget::setGeometry: callback error: '" << ex.what() << "'" - ); - } - } - //---------------------------------------------------------------------------- void NasalWidget::onRemove() { @@ -186,22 +151,6 @@ namespace canvas return !_height_for_width.empty() || !_min_height_for_width.empty(); } - //---------------------------------------------------------------------------- - int NasalWidget::heightForWidth(int w) const - { - return callHeightForWidthFunc( _height_for_width.empty() - ? _min_height_for_width - : _height_for_width, w ); - } - - //---------------------------------------------------------------------------- - int NasalWidget::minimumHeightForWidth(int w) const - { - return callHeightForWidthFunc( _min_height_for_width.empty() - ? _height_for_width - : _min_height_for_width, w ); - } - //---------------------------------------------------------------------------- static naRef f_makeNasalWidget(const nasal::CallContext& ctx) { @@ -285,6 +234,46 @@ namespace canvas ); } + + //---------------------------------------------------------------------------- + int NasalWidget::heightForWidthImpl(int w) const + { + return callHeightForWidthFunc( _height_for_width.empty() + ? _min_height_for_width + : _height_for_width, w ); + } + + //---------------------------------------------------------------------------- + int NasalWidget::minimumHeightForWidthImpl(int w) const + { + return callHeightForWidthFunc( _min_height_for_width.empty() + ? _height_for_width + : _min_height_for_width, w ); + } + + + //---------------------------------------------------------------------------- + void NasalWidget::contentsRectChanged(const SGRect& rect) + { + if( !_set_geometry ) + return; + + try + { + nasal::Context c; + _set_geometry(nasal::to_nasal(c, this), rect); + _flags &= ~LAYOUT_DIRTY; + } + catch( std::exception const& ex ) + { + SG_LOG( + SG_GUI, + SG_WARN, + "NasalWidget::setGeometry: callback error: '" << ex.what() << "'" + ); + } + } + //---------------------------------------------------------------------------- void NasalWidget::visibilityChanged(bool visible) { diff --git a/simgear/canvas/layout/NasalWidget.hxx b/simgear/canvas/layout/NasalWidget.hxx index 34877e27..504a41e7 100644 --- a/simgear/canvas/layout/NasalWidget.hxx +++ b/simgear/canvas/layout/NasalWidget.hxx @@ -51,8 +51,6 @@ namespace canvas ~NasalWidget(); - virtual void invalidate(); - virtual void setGeometry(const SGRecti& geom); virtual void onRemove(); void setSetGeometryFunc(const SetGeometryFunc& func); @@ -85,8 +83,6 @@ namespace canvas void setLayoutMaximumSize(const SGVec2i& s); virtual bool hasHeightForWidth() const; - virtual int heightForWidth(int w) const; - virtual int minimumHeightForWidth(int w) const; /** * @param ns Namespace to register the class interface @@ -118,6 +114,11 @@ namespace canvas virtual SGVec2i minimumSizeImpl() const; virtual SGVec2i maximumSizeImpl() const; + virtual int heightForWidthImpl(int w) const; + virtual int minimumHeightForWidthImpl(int w) const; + + virtual void contentsRectChanged(const SGRecti& rect); + virtual void visibilityChanged(bool visible); }; diff --git a/simgear/canvas/layout/canvas_layout_test.cxx b/simgear/canvas/layout/canvas_layout_test.cxx index ecab6333..a95aa760 100644 --- a/simgear/canvas/layout/canvas_layout_test.cxx +++ b/simgear/canvas/layout/canvas_layout_test.cxx @@ -64,13 +64,8 @@ class TestWidget: void setMaxSize(const SGVec2i& size) { _max_size = size; } void setSizeHint(const SGVec2i& size) { _size_hint = size; } - virtual void setGeometry(const SGRecti& geom) { _geom = geom; } - virtual SGRecti geometry() const { return _geom; } - protected: - SGRecti _geom; - virtual SGVec2i sizeHintImpl() const { return _size_hint; } virtual SGVec2i minimumSizeImpl() const { return _min_size; } virtual SGVec2i maximumSizeImpl() const { return _max_size; } @@ -78,7 +73,7 @@ class TestWidget: virtual void visibilityChanged(bool visible) { if( !visible ) - _geom.set(0, 0, 0, 0); + _geometry.set(0, 0, 0, 0); } }; @@ -99,12 +94,12 @@ class TestWidgetHFW: return true; } - virtual int heightForWidth(int w) const + virtual int heightForWidthImpl(int w) const { return _size_hint.x() * _size_hint.y() / w; } - virtual int minimumHeightForWidth(int w) const + virtual int minimumHeightForWidthImpl(int w) const { return _min_size.x() * _min_size.y() / w; } @@ -411,6 +406,96 @@ BOOST_AUTO_TEST_CASE( boxlayout_visibility ) BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(50, 0, 19, 32)); } +//------------------------------------------------------------------------------ +BOOST_AUTO_TEST_CASE( boxlayout_contents_margins ) +{ + sc::Margins m; + + BOOST_REQUIRE(m.isNull()); + + m = sc::Margins(5); + + BOOST_REQUIRE_EQUAL(m.l, 5); + BOOST_REQUIRE_EQUAL(m.t, 5); + BOOST_REQUIRE_EQUAL(m.r, 5); + BOOST_REQUIRE_EQUAL(m.b, 5); + + m = sc::Margins(6, 7); + + BOOST_REQUIRE_EQUAL(m.l, 6); + BOOST_REQUIRE_EQUAL(m.t, 7); + BOOST_REQUIRE_EQUAL(m.r, 6); + BOOST_REQUIRE_EQUAL(m.b, 7); + + BOOST_REQUIRE_EQUAL(m.horiz(), 12); + BOOST_REQUIRE_EQUAL(m.vert(), 14); + BOOST_REQUIRE(!m.isNull()); + + m = sc::Margins(1, 2, 3, 4); + + BOOST_REQUIRE_EQUAL(m.l, 1); + BOOST_REQUIRE_EQUAL(m.t, 2); + BOOST_REQUIRE_EQUAL(m.r, 3); + BOOST_REQUIRE_EQUAL(m.b, 4); + + BOOST_REQUIRE_EQUAL(m.horiz(), 4); + BOOST_REQUIRE_EQUAL(m.vert(), 6); + BOOST_REQUIRE_EQUAL(m.size(), SGVec2i(4, 6)); + + sc::BoxLayoutRef hbox( new sc::HBoxLayout ); + + hbox->setContentsMargins(5, 10, 15, 20); + + BOOST_CHECK_EQUAL(hbox->minimumSize(), SGVec2i(20, 30)); + BOOST_CHECK_EQUAL(hbox->sizeHint(), SGVec2i(20, 30)); + BOOST_CHECK_EQUAL(hbox->maximumSize(), SGVec2i(20, 30)); + + hbox->setGeometry(SGRecti(0, 0, 30, 40)); + + BOOST_CHECK_EQUAL(hbox->contentsRect(), SGRecti(5, 10, 10, 10)); + + TestWidgetRef w1( new TestWidget( SGVec2i(16, 16), + SGVec2i(32, 32) ) ), + w2( new TestWidget(*w1) ), + w3( new TestWidget(*w1) ); + + w1->setContentsMargin(5); + w2->setContentsMargin(6); + w3->setContentsMargin(7); + + BOOST_CHECK_EQUAL(w1->minimumSize(), SGVec2i(26, 26)); + BOOST_CHECK_EQUAL(w1->sizeHint(), SGVec2i(42, 42)); + BOOST_CHECK_EQUAL(w1->maximumSize(), sc::LayoutItem::MAX_SIZE); + + BOOST_CHECK_EQUAL(w2->minimumSize(), SGVec2i(28, 28)); + BOOST_CHECK_EQUAL(w2->sizeHint(), SGVec2i(44, 44)); + BOOST_CHECK_EQUAL(w2->maximumSize(), sc::LayoutItem::MAX_SIZE); + + BOOST_CHECK_EQUAL(w3->minimumSize(), SGVec2i(30, 30)); + BOOST_CHECK_EQUAL(w3->sizeHint(), SGVec2i(46, 46)); + BOOST_CHECK_EQUAL(w3->maximumSize(), sc::LayoutItem::MAX_SIZE); + + hbox->addItem(w1); + hbox->addItem(w2); + hbox->addItem(w3); + + BOOST_CHECK_EQUAL(hbox->minimumSize(), SGVec2i(114, 60)); + BOOST_CHECK_EQUAL(hbox->sizeHint(), SGVec2i(162, 76)); + BOOST_CHECK_EQUAL(hbox->maximumSize(), sc::LayoutItem::MAX_SIZE); + + hbox->setGeometry(SGRecti(0, 0, hbox->sizeHint().x(), hbox->sizeHint().y())); + + BOOST_CHECK_EQUAL(hbox->contentsRect(), SGRecti(5, 10, 142, 46)); + + BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(5, 10, 42, 46)); + BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(52, 10, 44, 46)); + BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(101, 10, 46, 46)); + + BOOST_CHECK_EQUAL(w1->contentsRect(), SGRecti(10, 15, 32, 36)); + BOOST_CHECK_EQUAL(w2->contentsRect(), SGRecti(58, 16, 32, 34)); + BOOST_CHECK_EQUAL(w3->contentsRect(), SGRecti(108, 17, 32, 32)); +} + //------------------------------------------------------------------------------ BOOST_AUTO_TEST_CASE( boxlayout_hfw ) { @@ -502,6 +587,7 @@ BOOST_AUTO_TEST_CASE( boxlayout_hfw ) BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32)); } +//------------------------------------------------------------------------------ // TODO extend to_nasal_helper for automatic argument conversion static naRef f_Widget_visibilityChanged(nasal::CallContext ctx) { -- 2.39.5