canvas::Layout: support height-for-width layouting.
This commit is contained in:
parent
e3f0fad272
commit
d3b211e787
@ -175,6 +175,35 @@ namespace canvas
|
|||||||
return _direction;
|
return _direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool BoxLayout::hasHeightForWidth() const
|
||||||
|
{
|
||||||
|
if( _flags & SIZE_INFO_DIRTY )
|
||||||
|
updateSizeHints();
|
||||||
|
|
||||||
|
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)
|
void BoxLayout::setCanvas(const CanvasWeakPtr& canvas)
|
||||||
{
|
{
|
||||||
@ -198,6 +227,8 @@ namespace canvas
|
|||||||
size_hint(0, 0);
|
size_hint(0, 0);
|
||||||
|
|
||||||
_layout_data.reset();
|
_layout_data.reset();
|
||||||
|
_hfw_width = _hfw_height = _hfw_min_height = -1;
|
||||||
|
|
||||||
bool is_first = true;
|
bool is_first = true;
|
||||||
|
|
||||||
for(size_t i = 0; i < _layout_items.size(); ++i)
|
for(size_t i = 0; i < _layout_items.size(); ++i)
|
||||||
@ -210,6 +241,7 @@ namespace canvas
|
|||||||
item_data.min_size = (item.minimumSize().*_get_layout_coord)();
|
item_data.min_size = (item.minimumSize().*_get_layout_coord)();
|
||||||
item_data.max_size = (item.maximumSize().*_get_layout_coord)();
|
item_data.max_size = (item.maximumSize().*_get_layout_coord)();
|
||||||
item_data.size_hint = (item.sizeHint().*_get_layout_coord)();
|
item_data.size_hint = (item.sizeHint().*_get_layout_coord)();
|
||||||
|
item_data.has_hfw = item.hasHeightForWidth();
|
||||||
|
|
||||||
if( !dynamic_cast<SpacerItem*>(item_data.layout_item.get()) )
|
if( !dynamic_cast<SpacerItem*>(item_data.layout_item.get()) )
|
||||||
{
|
{
|
||||||
@ -237,6 +269,8 @@ namespace canvas
|
|||||||
(item.maximumSize().*_get_fixed_coord)() );
|
(item.maximumSize().*_get_fixed_coord)() );
|
||||||
size_hint.y() = std::max( size_hint.y(),
|
size_hint.y() = std::max( size_hint.y(),
|
||||||
(item.sizeHint().*_get_fixed_coord)() );
|
(item.sizeHint().*_get_fixed_coord)() );
|
||||||
|
|
||||||
|
_layout_data.has_hfw = _layout_data.has_hfw || item.hasHeightForWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
safeAdd(min_size.x(), _layout_data.padding);
|
safeAdd(min_size.x(), _layout_data.padding);
|
||||||
@ -258,6 +292,40 @@ namespace canvas
|
|||||||
_flags &= ~SIZE_INFO_DIRTY;
|
_flags &= ~SIZE_INFO_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void BoxLayout::updateWFHCache(int w) const
|
||||||
|
{
|
||||||
|
if( w == _hfw_width )
|
||||||
|
return;
|
||||||
|
|
||||||
|
_hfw_height = 0;
|
||||||
|
_hfw_min_height = 0;
|
||||||
|
|
||||||
|
if( horiz() )
|
||||||
|
{
|
||||||
|
_layout_data.size = w;
|
||||||
|
const_cast<BoxLayout*>(this)->distribute(_layout_items, _layout_data);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < _layout_items.size(); ++i)
|
||||||
|
{
|
||||||
|
ItemData const& data = _layout_items[i];
|
||||||
|
_hfw_height = std::max(_hfw_height, data.hfw(data.size));
|
||||||
|
_hfw_min_height = std::max(_hfw_min_height, data.mhfw(data.size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < _layout_items.size(); ++i)
|
||||||
|
{
|
||||||
|
ItemData const& data = _layout_items[i];
|
||||||
|
_hfw_height += data.hfw(w) + data.padding_orig;
|
||||||
|
_hfw_min_height += data.mhfw(w) + data.padding_orig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_hfw_width = w;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
SGVec2i BoxLayout::sizeHintImpl() const
|
SGVec2i BoxLayout::sizeHintImpl() const
|
||||||
{
|
{
|
||||||
@ -285,9 +353,45 @@ namespace canvas
|
|||||||
if( _flags & SIZE_INFO_DIRTY )
|
if( _flags & SIZE_INFO_DIRTY )
|
||||||
updateSizeHints();
|
updateSizeHints();
|
||||||
|
|
||||||
|
// Store current size hints because vertical layouts containing
|
||||||
|
// height-for-width items the size hints are update for the actual width of
|
||||||
|
// the layout
|
||||||
|
int min_size_save = _layout_data.min_size,
|
||||||
|
size_hint_save = _layout_data.size_hint;
|
||||||
|
|
||||||
_layout_data.size = (geom.size().*_get_layout_coord)();
|
_layout_data.size = (geom.size().*_get_layout_coord)();
|
||||||
|
|
||||||
|
// update width dependent data for layouting of vertical layouts
|
||||||
|
if( _layout_data.has_hfw && !horiz() )
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < _layout_items.size(); ++i)
|
||||||
|
{
|
||||||
|
ItemData& data = _layout_items[i];
|
||||||
|
if( data.has_hfw )
|
||||||
|
{
|
||||||
|
int w = SGMisc<int>::clip( geom.width(),
|
||||||
|
data.layout_item->minimumSize().x(),
|
||||||
|
data.layout_item->maximumSize().x() );
|
||||||
|
|
||||||
|
int d = data.layout_item->minimumHeightForWidth(w) - data.min_size;
|
||||||
|
data.min_size += d;
|
||||||
|
_layout_data.min_size += d;
|
||||||
|
|
||||||
|
d = data.layout_item->heightForWidth(w) - data.size_hint;
|
||||||
|
data.size_hint += d;
|
||||||
|
_layout_data.size_hint += d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do the actual layouting
|
||||||
distribute(_layout_items, _layout_data);
|
distribute(_layout_items, _layout_data);
|
||||||
|
|
||||||
|
// Restore size hints possibly changed by vertical layouting
|
||||||
|
_layout_data.min_size = min_size_save;
|
||||||
|
_layout_data.size_hint = size_hint_save;
|
||||||
|
|
||||||
|
// and finally set the layouted geometry for each item
|
||||||
int fixed_size = (geom.size().*_get_fixed_coord)();
|
int fixed_size = (geom.size().*_get_fixed_coord)();
|
||||||
SGVec2i cur_pos( (geom.pos().*_get_layout_coord)(),
|
SGVec2i cur_pos( (geom.pos().*_get_layout_coord)(),
|
||||||
(geom.pos().*_get_fixed_coord)() );
|
(geom.pos().*_get_fixed_coord)() );
|
||||||
@ -296,7 +400,6 @@ namespace canvas
|
|||||||
if( reverse )
|
if( reverse )
|
||||||
cur_pos.x() += (geom.size().*_get_layout_coord)();
|
cur_pos.x() += (geom.size().*_get_layout_coord)();
|
||||||
|
|
||||||
// TODO handle reverse layouting (rtl/btt)
|
|
||||||
for(size_t i = 0; i < _layout_items.size(); ++i)
|
for(size_t i = 0; i < _layout_items.size(); ++i)
|
||||||
{
|
{
|
||||||
ItemData const& data = _layout_items[i];
|
ItemData const& data = _layout_items[i];
|
||||||
|
@ -75,6 +75,10 @@ namespace canvas
|
|||||||
void setDirection(Direction dir);
|
void setDirection(Direction dir);
|
||||||
Direction direction() const;
|
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);
|
virtual void setCanvas(const CanvasWeakPtr& canvas);
|
||||||
|
|
||||||
bool horiz() const;
|
bool horiz() const;
|
||||||
@ -95,7 +99,13 @@ namespace canvas
|
|||||||
mutable LayoutItems _layout_items;
|
mutable LayoutItems _layout_items;
|
||||||
mutable ItemData _layout_data;
|
mutable ItemData _layout_data;
|
||||||
|
|
||||||
|
// Cache for last height-for-width query
|
||||||
|
mutable int _hfw_width,
|
||||||
|
_hfw_height,
|
||||||
|
_hfw_min_height;
|
||||||
|
|
||||||
void updateSizeHints() const;
|
void updateSizeHints() const;
|
||||||
|
void updateWFHCache(int w) const;
|
||||||
|
|
||||||
virtual SGVec2i sizeHintImpl() const;
|
virtual SGVec2i sizeHintImpl() const;
|
||||||
virtual SGVec2i minimumSizeImpl() const;
|
virtual SGVec2i minimumSizeImpl() const;
|
||||||
|
@ -78,9 +78,28 @@ namespace canvas
|
|||||||
padding = 0;
|
padding = 0;
|
||||||
size = 0;
|
size = 0;
|
||||||
stretch = 0;
|
stretch = 0;
|
||||||
|
has_hfw = false;
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
int Layout::ItemData::hfw(int w) const
|
||||||
|
{
|
||||||
|
if( has_hfw )
|
||||||
|
return layout_item->heightForWidth(w);
|
||||||
|
else
|
||||||
|
return layout_item->sizeHint().y();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
int Layout::ItemData::mhfw(int w) const
|
||||||
|
{
|
||||||
|
if( has_hfw )
|
||||||
|
return layout_item->minimumHeightForWidth(w);
|
||||||
|
else
|
||||||
|
return layout_item->minimumSize().y();
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Layout::safeAdd(int& a, int b)
|
void Layout::safeAdd(int& a, int b)
|
||||||
{
|
{
|
||||||
@ -122,6 +141,15 @@ namespace canvas
|
|||||||
d.padding = d.padding_orig;
|
d.padding = d.padding_orig;
|
||||||
d.done = d.size >= (less_then_hint ? d.size_hint : d.max_size);
|
d.done = d.size >= (less_then_hint ? d.size_hint : d.max_size);
|
||||||
|
|
||||||
|
SG_LOG(
|
||||||
|
SG_GUI,
|
||||||
|
SG_DEBUG,
|
||||||
|
i << ") initial=" << d.size
|
||||||
|
<< ", min=" << d.min_size
|
||||||
|
<< ", hint=" << d.size_hint
|
||||||
|
<< ", max=" << d.max_size
|
||||||
|
);
|
||||||
|
|
||||||
if( d.done )
|
if( d.done )
|
||||||
{
|
{
|
||||||
_num_not_done -= 1;
|
_num_not_done -= 1;
|
||||||
|
@ -83,10 +83,14 @@ namespace canvas
|
|||||||
padding, //<! padding before element (layouted)
|
padding, //<! padding before element (layouted)
|
||||||
size, //<! layouted size
|
size, //<! layouted size
|
||||||
stretch; //<! stretch factor
|
stretch; //<! stretch factor
|
||||||
bool done; //<! layouting done
|
bool has_hfw : 1, //<! height for width
|
||||||
|
done : 1; //<! layouting done
|
||||||
|
|
||||||
/** Clear values (reset to default/empty state) */
|
/** Clear values (reset to default/empty state) */
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
int hfw(int w) const;
|
||||||
|
int mhfw(int w) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,6 +78,24 @@ namespace canvas
|
|||||||
return _max_size;
|
return _max_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool LayoutItem::hasHeightForWidth() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
int LayoutItem::heightForWidth(int w) const
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int LayoutItem::minimumHeightForWidth(int w) const
|
||||||
|
{
|
||||||
|
return heightForWidth(w);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void LayoutItem::invalidate()
|
void LayoutItem::invalidate()
|
||||||
{
|
{
|
||||||
|
@ -63,6 +63,10 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
SGVec2i maximumSize() const;
|
SGVec2i maximumSize() const;
|
||||||
|
|
||||||
|
virtual bool hasHeightForWidth() const;
|
||||||
|
virtual int heightForWidth(int w) const;
|
||||||
|
virtual int minimumHeightForWidth(int w) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark all cached data as invalid and require it to be recalculated.
|
* Mark all cached data as invalid and require it to be recalculated.
|
||||||
*/
|
*/
|
||||||
|
@ -65,6 +65,20 @@ namespace canvas
|
|||||||
_set_geometry = func;
|
_set_geometry = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void NasalWidget::setHeightForWidthFunc(const HeightForWidthFunc& func)
|
||||||
|
{
|
||||||
|
_height_for_width = func;
|
||||||
|
invalidateParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void NasalWidget::setMinimumHeightForWidthFunc(const HeightForWidthFunc& func)
|
||||||
|
{
|
||||||
|
_min_height_for_width = func;
|
||||||
|
invalidateParent();
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void NasalWidget::setSizeHint(const SGVec2i& s)
|
void NasalWidget::setSizeHint(const SGVec2i& s)
|
||||||
{
|
{
|
||||||
@ -97,6 +111,28 @@ namespace canvas
|
|||||||
invalidateParent();
|
invalidateParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool NasalWidget::hasHeightForWidth() const
|
||||||
|
{
|
||||||
|
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)
|
static naRef f_makeNasalWidget(const nasal::CallContext& ctx)
|
||||||
{
|
{
|
||||||
@ -112,6 +148,9 @@ namespace canvas
|
|||||||
.bases<LayoutItemRef>()
|
.bases<LayoutItemRef>()
|
||||||
.bases<nasal::ObjectRef>()
|
.bases<nasal::ObjectRef>()
|
||||||
.method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
|
.method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
|
||||||
|
.method("setMinimumHeightForWidthFunc",
|
||||||
|
&NasalWidget::setMinimumHeightForWidthFunc)
|
||||||
|
.method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
|
||||||
.method("setSizeHint", &NasalWidget::setSizeHint)
|
.method("setSizeHint", &NasalWidget::setSizeHint)
|
||||||
.method("setMinimumSize", &NasalWidget::setMinimumSize)
|
.method("setMinimumSize", &NasalWidget::setMinimumSize)
|
||||||
.method("setMaximumSize", &NasalWidget::setMaximumSize);
|
.method("setMaximumSize", &NasalWidget::setMaximumSize);
|
||||||
@ -120,6 +159,31 @@ namespace canvas
|
|||||||
widget_hash.set("new", &f_makeNasalWidget);
|
widget_hash.set("new", &f_makeNasalWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
int NasalWidget::callHeightForWidthFunc( const HeightForWidthFunc& hfw,
|
||||||
|
int w ) const
|
||||||
|
{
|
||||||
|
if( hfw.empty() )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
naContext c = naNewContext();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return hfw(nasal::to_nasal(c, const_cast<NasalWidget*>(this)), w);
|
||||||
|
}
|
||||||
|
catch( std::exception const& ex )
|
||||||
|
{
|
||||||
|
SG_LOG(
|
||||||
|
SG_GUI,
|
||||||
|
SG_WARN,
|
||||||
|
"NasalWidget.heightForWidth: callback error: '" << ex.what() << "'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
naFreeContext(c);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
SGVec2i NasalWidget::sizeHintImpl() const
|
SGVec2i NasalWidget::sizeHintImpl() const
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,7 @@ namespace canvas
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
typedef boost::function<void (nasal::Me, const SGRecti&)> SetGeometryFunc;
|
typedef boost::function<void (nasal::Me, const SGRecti&)> SetGeometryFunc;
|
||||||
|
typedef boost::function<int (nasal::Me, int)> HeightForWidthFunc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -51,11 +52,17 @@ namespace canvas
|
|||||||
virtual void setGeometry(const SGRecti& geom);
|
virtual void setGeometry(const SGRecti& geom);
|
||||||
|
|
||||||
void setSetGeometryFunc(const SetGeometryFunc& func);
|
void setSetGeometryFunc(const SetGeometryFunc& func);
|
||||||
|
void setHeightForWidthFunc(const HeightForWidthFunc& func);
|
||||||
|
void setMinimumHeightForWidthFunc(const HeightForWidthFunc& func);
|
||||||
|
|
||||||
void setSizeHint(const SGVec2i& s);
|
void setSizeHint(const SGVec2i& s);
|
||||||
void setMinimumSize(const SGVec2i& s);
|
void setMinimumSize(const SGVec2i& s);
|
||||||
void setMaximumSize(const SGVec2i& s);
|
void setMaximumSize(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
|
* @param ns Namespace to register the class interface
|
||||||
*/
|
*/
|
||||||
@ -63,6 +70,11 @@ namespace canvas
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
SetGeometryFunc _set_geometry;
|
SetGeometryFunc _set_geometry;
|
||||||
|
HeightForWidthFunc _height_for_width,
|
||||||
|
_min_height_for_width;
|
||||||
|
|
||||||
|
int callHeightForWidthFunc( const HeightForWidthFunc& hfw,
|
||||||
|
int w ) const;
|
||||||
|
|
||||||
virtual SGVec2i sizeHintImpl() const;
|
virtual SGVec2i sizeHintImpl() const;
|
||||||
virtual SGVec2i minimumSizeImpl() const;
|
virtual SGVec2i minimumSizeImpl() const;
|
||||||
|
@ -44,7 +44,7 @@ class TestWidget:
|
|||||||
public:
|
public:
|
||||||
TestWidget( const SGVec2i& min_size,
|
TestWidget( const SGVec2i& min_size,
|
||||||
const SGVec2i& size_hint,
|
const SGVec2i& size_hint,
|
||||||
const SGVec2i& max_size )
|
const SGVec2i& max_size = MAX_SIZE )
|
||||||
{
|
{
|
||||||
_size_hint = size_hint;
|
_size_hint = size_hint;
|
||||||
_min_size = min_size;
|
_min_size = min_size;
|
||||||
@ -74,6 +74,34 @@ class TestWidget:
|
|||||||
virtual SGVec2i maximumSizeImpl() const { return _max_size; }
|
virtual SGVec2i maximumSizeImpl() const { return _max_size; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TestWidgetHFW:
|
||||||
|
public TestWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestWidgetHFW( const SGVec2i& min_size,
|
||||||
|
const SGVec2i& size_hint,
|
||||||
|
const SGVec2i& max_size = MAX_SIZE ):
|
||||||
|
TestWidget(min_size, size_hint, max_size)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool hasHeightForWidth() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int heightForWidth(int w) const
|
||||||
|
{
|
||||||
|
return _size_hint.x() * _size_hint.y() / w;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int minimumHeightForWidth(int w) const
|
||||||
|
{
|
||||||
|
return _min_size.x() * _min_size.y() / w;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef SGSharedPtr<TestWidget> TestWidgetRef;
|
typedef SGSharedPtr<TestWidget> TestWidgetRef;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -255,6 +283,7 @@ BOOST_AUTO_TEST_CASE( vertical_layout)
|
|||||||
vbox.setDirection(sc::BoxLayout::BottomToTop);
|
vbox.setDirection(sc::BoxLayout::BottomToTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
|
BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
|
||||||
{
|
{
|
||||||
sc::HBoxLayout hbox;
|
sc::HBoxLayout hbox;
|
||||||
@ -282,6 +311,89 @@ BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
|
|||||||
BOOST_CHECK_EQUAL(hbox.itemAt(0), w1);
|
BOOST_CHECK_EQUAL(hbox.itemAt(0), w1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
BOOST_AUTO_TEST_CASE( boxlayout_hfw )
|
||||||
|
{
|
||||||
|
TestWidgetRef w1( new TestWidgetHFW( SGVec2i(16, 16),
|
||||||
|
SGVec2i(32, 32) ) ),
|
||||||
|
w2( new TestWidgetHFW( SGVec2i(24, 24),
|
||||||
|
SGVec2i(48, 48) ) );
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(w1->heightForWidth(16), 64);
|
||||||
|
BOOST_CHECK_EQUAL(w1->minimumHeightForWidth(16), 16);
|
||||||
|
BOOST_CHECK_EQUAL(w2->heightForWidth(24), 96);
|
||||||
|
BOOST_CHECK_EQUAL(w2->minimumHeightForWidth(24), 24);
|
||||||
|
|
||||||
|
TestWidgetRef w_no_hfw( new TestWidget( SGVec2i(16, 16),
|
||||||
|
SGVec2i(32, 32) ) );
|
||||||
|
BOOST_CHECK(!w_no_hfw->hasHeightForWidth());
|
||||||
|
BOOST_CHECK_EQUAL(w_no_hfw->heightForWidth(16), -1);
|
||||||
|
BOOST_CHECK_EQUAL(w_no_hfw->minimumHeightForWidth(16), -1);
|
||||||
|
|
||||||
|
// horizontal
|
||||||
|
sc::HBoxLayout hbox;
|
||||||
|
hbox.setSpacing(5);
|
||||||
|
hbox.addItem(w1);
|
||||||
|
hbox.addItem(w2);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(hbox.heightForWidth(45), w2->heightForWidth(24));
|
||||||
|
BOOST_CHECK_EQUAL(hbox.heightForWidth(85), w2->heightForWidth(48));
|
||||||
|
|
||||||
|
hbox.addItem(w_no_hfw);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(hbox.heightForWidth(66), 96);
|
||||||
|
BOOST_CHECK_EQUAL(hbox.heightForWidth(122), 48);
|
||||||
|
BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(66), 24);
|
||||||
|
BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(122), 16);
|
||||||
|
|
||||||
|
hbox.setGeometry(SGRecti(0, 0, 66, 24));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 16, 24));
|
||||||
|
BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(21, 0, 24, 24));
|
||||||
|
BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(50, 0, 16, 24));
|
||||||
|
|
||||||
|
// vertical
|
||||||
|
sc::VBoxLayout vbox;
|
||||||
|
vbox.setSpacing(5);
|
||||||
|
vbox.addItem(w1);
|
||||||
|
vbox.addItem(w2);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 143);
|
||||||
|
BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 74);
|
||||||
|
BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 39);
|
||||||
|
BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 22);
|
||||||
|
|
||||||
|
vbox.addItem(w_no_hfw);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 180);
|
||||||
|
BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 111);
|
||||||
|
BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 60);
|
||||||
|
BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 43);
|
||||||
|
|
||||||
|
SGVec2i min_size = vbox.minimumSize(),
|
||||||
|
size_hint = vbox.sizeHint();
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(min_size, SGVec2i(24, 66));
|
||||||
|
BOOST_CHECK_EQUAL(size_hint, SGVec2i(48, 122));
|
||||||
|
|
||||||
|
vbox.setGeometry(SGRecti(0, 0, 24, 122));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 24, 33));
|
||||||
|
BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
|
||||||
|
BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
|
||||||
|
|
||||||
|
// Vertical layouting modifies size hints, so check if they are correctly
|
||||||
|
// restored
|
||||||
|
BOOST_CHECK_EQUAL(min_size, vbox.minimumSize());
|
||||||
|
BOOST_CHECK_EQUAL(size_hint, vbox.sizeHint());
|
||||||
|
|
||||||
|
vbox.setGeometry(SGRecti(0, 0, 50, 122));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 50, 44));
|
||||||
|
BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 49, 50, 70));
|
||||||
|
BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 124, 50, 56));
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
BOOST_AUTO_TEST_CASE( nasal_layout )
|
BOOST_AUTO_TEST_CASE( nasal_layout )
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ class SGRect
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SGRect(const SGVec2<T>& pt):
|
explicit SGRect(const SGVec2<T>& pt):
|
||||||
_min(pt),
|
_min(pt),
|
||||||
_max(pt)
|
_max(pt)
|
||||||
{
|
{
|
||||||
|
@ -144,6 +144,9 @@ namespace nasal
|
|||||||
boost::function<Sig>
|
boost::function<Sig>
|
||||||
from_nasal_helper(naContext c, naRef ref, boost::function<Sig>*)
|
from_nasal_helper(naContext c, naRef ref, boost::function<Sig>*)
|
||||||
{
|
{
|
||||||
|
if( naIsNil(ref) )
|
||||||
|
return boost::function<Sig>();
|
||||||
|
|
||||||
if( !naIsCode(ref)
|
if( !naIsCode(ref)
|
||||||
&& !naIsCCode(ref)
|
&& !naIsCCode(ref)
|
||||||
&& !naIsFunc(ref) )
|
&& !naIsFunc(ref) )
|
||||||
|
Loading…
Reference in New Issue
Block a user