canvas::Layout: support height-for-width layouting.
This commit is contained in:
parent
e3f0fad272
commit
d3b211e787
@ -175,6 +175,35 @@ namespace canvas
|
||||
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)
|
||||
{
|
||||
@ -198,6 +227,8 @@ namespace canvas
|
||||
size_hint(0, 0);
|
||||
|
||||
_layout_data.reset();
|
||||
_hfw_width = _hfw_height = _hfw_min_height = -1;
|
||||
|
||||
bool is_first = true;
|
||||
|
||||
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.max_size = (item.maximumSize().*_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()) )
|
||||
{
|
||||
@ -237,6 +269,8 @@ namespace canvas
|
||||
(item.maximumSize().*_get_fixed_coord)() );
|
||||
size_hint.y() = std::max( size_hint.y(),
|
||||
(item.sizeHint().*_get_fixed_coord)() );
|
||||
|
||||
_layout_data.has_hfw = _layout_data.has_hfw || item.hasHeightForWidth();
|
||||
}
|
||||
|
||||
safeAdd(min_size.x(), _layout_data.padding);
|
||||
@ -258,6 +292,40 @@ namespace canvas
|
||||
_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
|
||||
{
|
||||
@ -285,9 +353,45 @@ namespace canvas
|
||||
if( _flags & SIZE_INFO_DIRTY )
|
||||
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)();
|
||||
|
||||
// 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);
|
||||
|
||||
// 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)();
|
||||
SGVec2i cur_pos( (geom.pos().*_get_layout_coord)(),
|
||||
(geom.pos().*_get_fixed_coord)() );
|
||||
@ -296,7 +400,6 @@ namespace canvas
|
||||
if( reverse )
|
||||
cur_pos.x() += (geom.size().*_get_layout_coord)();
|
||||
|
||||
// TODO handle reverse layouting (rtl/btt)
|
||||
for(size_t i = 0; i < _layout_items.size(); ++i)
|
||||
{
|
||||
ItemData const& data = _layout_items[i];
|
||||
|
@ -75,6 +75,10 @@ namespace canvas
|
||||
void setDirection(Direction dir);
|
||||
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);
|
||||
|
||||
bool horiz() const;
|
||||
@ -95,7 +99,13 @@ namespace canvas
|
||||
mutable LayoutItems _layout_items;
|
||||
mutable ItemData _layout_data;
|
||||
|
||||
// Cache for last height-for-width query
|
||||
mutable int _hfw_width,
|
||||
_hfw_height,
|
||||
_hfw_min_height;
|
||||
|
||||
void updateSizeHints() const;
|
||||
void updateWFHCache(int w) const;
|
||||
|
||||
virtual SGVec2i sizeHintImpl() const;
|
||||
virtual SGVec2i minimumSizeImpl() const;
|
||||
|
@ -78,9 +78,28 @@ namespace canvas
|
||||
padding = 0;
|
||||
size = 0;
|
||||
stretch = 0;
|
||||
has_hfw = 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)
|
||||
{
|
||||
@ -122,6 +141,15 @@ namespace canvas
|
||||
d.padding = d.padding_orig;
|
||||
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 )
|
||||
{
|
||||
_num_not_done -= 1;
|
||||
|
@ -83,10 +83,14 @@ namespace canvas
|
||||
padding, //<! padding before element (layouted)
|
||||
size, //<! layouted size
|
||||
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) */
|
||||
void reset();
|
||||
|
||||
int hfw(int w) const;
|
||||
int mhfw(int w) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -78,6 +78,24 @@ namespace canvas
|
||||
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()
|
||||
{
|
||||
|
@ -63,6 +63,10 @@ namespace canvas
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -65,6 +65,20 @@ namespace canvas
|
||||
_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)
|
||||
{
|
||||
@ -97,6 +111,28 @@ namespace canvas
|
||||
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)
|
||||
{
|
||||
@ -112,6 +148,9 @@ namespace canvas
|
||||
.bases<LayoutItemRef>()
|
||||
.bases<nasal::ObjectRef>()
|
||||
.method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
|
||||
.method("setMinimumHeightForWidthFunc",
|
||||
&NasalWidget::setMinimumHeightForWidthFunc)
|
||||
.method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
|
||||
.method("setSizeHint", &NasalWidget::setSizeHint)
|
||||
.method("setMinimumSize", &NasalWidget::setMinimumSize)
|
||||
.method("setMaximumSize", &NasalWidget::setMaximumSize);
|
||||
@ -120,6 +159,31 @@ namespace canvas
|
||||
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
|
||||
{
|
||||
|
@ -40,6 +40,7 @@ namespace canvas
|
||||
public:
|
||||
|
||||
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);
|
||||
|
||||
void setSetGeometryFunc(const SetGeometryFunc& func);
|
||||
void setHeightForWidthFunc(const HeightForWidthFunc& func);
|
||||
void setMinimumHeightForWidthFunc(const HeightForWidthFunc& func);
|
||||
|
||||
void setSizeHint(const SGVec2i& s);
|
||||
void setMinimumSize(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
|
||||
*/
|
||||
@ -63,6 +70,11 @@ namespace canvas
|
||||
|
||||
protected:
|
||||
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 minimumSizeImpl() const;
|
||||
|
@ -44,7 +44,7 @@ class TestWidget:
|
||||
public:
|
||||
TestWidget( const SGVec2i& min_size,
|
||||
const SGVec2i& size_hint,
|
||||
const SGVec2i& max_size )
|
||||
const SGVec2i& max_size = MAX_SIZE )
|
||||
{
|
||||
_size_hint = size_hint;
|
||||
_min_size = min_size;
|
||||
@ -74,6 +74,34 @@ class TestWidget:
|
||||
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;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -255,6 +283,7 @@ BOOST_AUTO_TEST_CASE( vertical_layout)
|
||||
vbox.setDirection(sc::BoxLayout::BottomToTop);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
|
||||
{
|
||||
sc::HBoxLayout hbox;
|
||||
@ -282,6 +311,89 @@ BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
|
||||
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 )
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ class SGRect
|
||||
|
||||
}
|
||||
|
||||
SGRect(const SGVec2<T>& pt):
|
||||
explicit SGRect(const SGVec2<T>& pt):
|
||||
_min(pt),
|
||||
_max(pt)
|
||||
{
|
||||
|
@ -144,6 +144,9 @@ namespace nasal
|
||||
boost::function<Sig>
|
||||
from_nasal_helper(naContext c, naRef ref, boost::function<Sig>*)
|
||||
{
|
||||
if( naIsNil(ref) )
|
||||
return boost::function<Sig>();
|
||||
|
||||
if( !naIsCode(ref)
|
||||
&& !naIsCCode(ref)
|
||||
&& !naIsFunc(ref) )
|
||||
|
Loading…
Reference in New Issue
Block a user