canvas::Layout: proper cleanup/update on removing items.

This commit is contained in:
Thomas Geymayer
2014-06-15 13:47:50 +02:00
parent 1225e53162
commit 737b1948bf
10 changed files with 88 additions and 14 deletions

View File

@@ -32,6 +32,13 @@ namespace canvas
setDirection(dir);
}
//----------------------------------------------------------------------------
BoxLayout::~BoxLayout()
{
_parent.reset(); // No need to invalidate parent again...
clear();
}
//----------------------------------------------------------------------------
void BoxLayout::addItem(const LayoutItemRef& item)
{
@@ -114,6 +121,7 @@ namespace canvas
LayoutItems::iterator it = _layout_items.begin() + index;
LayoutItemRef item = it->layout_item;
item->onRemove();
_layout_items.erase(it);
invalidate();
@@ -124,6 +132,12 @@ namespace canvas
//----------------------------------------------------------------------------
void BoxLayout::clear()
{
for( LayoutItems::iterator it = _layout_items.begin();
it != _layout_items.end();
++it )
{
it->layout_item->onRemove();
}
_layout_items.clear();
invalidate();
}

View File

@@ -40,6 +40,7 @@ namespace canvas
};
BoxLayout(Direction dir);
~BoxLayout();
virtual void addItem(const LayoutItemRef& item);

View File

@@ -45,11 +45,11 @@ namespace canvas
//----------------------------------------------------------------------------
void Layout::setGeometry(const SGRecti& geom)
{
if( geom == _geometry )
return;
_geometry = geom;
_flags |= LAYOUT_DIRTY;
if( geom != _geometry )
{
_geometry = geom;
_flags |= LAYOUT_DIRTY;
}
update();
}

View File

@@ -99,10 +99,7 @@ namespace canvas
//----------------------------------------------------------------------------
void LayoutItem::invalidate()
{
_flags |= SIZE_HINT_DIRTY
| MINIMUM_SIZE_DIRTY
| MAXIMUM_SIZE_DIRTY;
_flags |= SIZE_INFO_DIRTY;
invalidateParent();
}

View File

@@ -108,6 +108,9 @@ namespace canvas
*/
LayoutItemRef getParent() const;
/// Called before item is removed from a layout
virtual void onRemove() {}
protected:
friend class Canvas;

View File

@@ -33,20 +33,26 @@ namespace canvas
}
//----------------------------------------------------------------------------
void NasalWidget::invalidate()
{
LayoutItem::invalidate();
_flags |= LAYOUT_DIRTY;
}
//----------------------------------------------------------------------------
void NasalWidget::setGeometry(const SGRect<int>& geom)
{
if( _geometry == geom )
return;
_geometry = geom;
if( !_set_geometry )
if( _geometry != geom )
_geometry = geom;
else if( !(_flags & LAYOUT_DIRTY) || !_set_geometry )
return;
naContext c = naNewContext();
try
{
_set_geometry(nasal::to_nasal(c, this), geom);
_flags &= ~LAYOUT_DIRTY;
}
catch( std::exception const& ex )
{
@@ -59,6 +65,33 @@ namespace canvas
naFreeContext(c);
}
//----------------------------------------------------------------------------
void NasalWidget::onRemove()
{
if( !_nasal_impl.valid() )
return;
typedef boost::function<void(nasal::Me)> Deleter;
naContext c = naNewContext();
try
{
Deleter del =
nasal::get_member<Deleter>(c, _nasal_impl.get_naRef(), "onRemove");
if( del )
del(_nasal_impl.get_naRef());
}
catch( std::exception const& ex )
{
SG_LOG(
SG_GUI,
SG_WARN,
"NasalWidget::onRemove: callback error: '" << ex.what() << "'"
);
}
naFreeContext(c);
}
//----------------------------------------------------------------------------
void NasalWidget::setSetGeometryFunc(const SetGeometryFunc& func)
{

View File

@@ -49,7 +49,9 @@ namespace canvas
*/
NasalWidget(naRef impl);
virtual void invalidate();
virtual void setGeometry(const SGRecti& geom);
virtual void onRemove();
void setSetGeometryFunc(const SetGeometryFunc& func);
void setHeightForWidthFunc(const HeightForWidthFunc& func);
@@ -69,6 +71,12 @@ namespace canvas
static void setupGhost(nasal::Hash& ns);
protected:
enum WidgetFlags
{
LAYOUT_DIRTY = LayoutItem::LAST_FLAG << 1,
LAST_FLAG = LAYOUT_DIRTY
};
SetGeometryFunc _set_geometry;
HeightForWidthFunc _height_for_width,
_min_height_for_width;

View File

@@ -41,6 +41,12 @@ namespace nasal
return _nasal_impl.get_naRef();
}
//----------------------------------------------------------------------------
bool Object::valid() const
{
return _nasal_impl.valid();
}
//----------------------------------------------------------------------------
bool Object::_set(naContext c, const std::string& key, naRef val)
{

View File

@@ -39,6 +39,8 @@ namespace nasal
void setImpl(naRef obj);
naRef getImpl() const;
bool valid() const;
bool _set(naContext c, const std::string& key, naRef val);
bool _get(naContext c, const std::string& key, naRef& out);

View File

@@ -63,6 +63,16 @@ namespace nasal
}
};
template<class T>
T get_member(naContext c, naRef obj, const std::string& name)
{
naRef out;
if( !naMember_get(c, obj, to_nasal(c, name), &out) )
return T();
return from_nasal<T>(c, out);
}
} // namespace nasal
#endif /* SG_FROM_NASAL_HXX_ */