canvas::Layout: support for contents margins.

This commit is contained in:
Thomas Geymayer
2014-07-22 00:48:42 +02:00
parent f25abad9d7
commit 76fc47b24b
11 changed files with 456 additions and 147 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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<ItemData>& items, const ItemData& space)
{

View File

@@ -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
*/

View File

@@ -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<int>::max(),
SGLimits<int>::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<int>::addClipOverflow(h, _margins.vert());
}
//------------------------------------------------------------------------------
int LayoutItem::minimumHeightForWidth(int w) const
{
return heightForWidth(w);
int h = minimumHeightForWidthImpl(w - _margins.horiz());
return h < 0 ? -1 : SGMisc<int>::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)
{

View File

@@ -34,6 +34,53 @@ namespace canvas
typedef SGSharedPtr<LayoutItem> LayoutItemRef;
typedef SGWeakPtr<LayoutItem> 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) {}
/**

View File

@@ -46,41 +46,6 @@ namespace canvas
onRemove();
}
//----------------------------------------------------------------------------
void NasalWidget::invalidate()
{
LayoutItem::invalidate();
_flags |= LAYOUT_DIRTY;
}
//----------------------------------------------------------------------------
void NasalWidget::setGeometry(const SGRect<int>& 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<int>& 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)
{

View File

@@ -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);
};

View File

@@ -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)
{