From: Thomas Geymayer Date: Sun, 15 Jun 2014 11:47:50 +0000 (+0200) Subject: canvas::Layout: proper cleanup/update on removing items. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=737b1948bf57e6171b14ce3dfde991b4f23efec0;p=simgear.git canvas::Layout: proper cleanup/update on removing items. --- diff --git a/simgear/canvas/layout/BoxLayout.cxx b/simgear/canvas/layout/BoxLayout.cxx index c7140467..f6c4c48a 100644 --- a/simgear/canvas/layout/BoxLayout.cxx +++ b/simgear/canvas/layout/BoxLayout.cxx @@ -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(); } diff --git a/simgear/canvas/layout/BoxLayout.hxx b/simgear/canvas/layout/BoxLayout.hxx index fc3b4a25..8982aeaf 100644 --- a/simgear/canvas/layout/BoxLayout.hxx +++ b/simgear/canvas/layout/BoxLayout.hxx @@ -40,6 +40,7 @@ namespace canvas }; BoxLayout(Direction dir); + ~BoxLayout(); virtual void addItem(const LayoutItemRef& item); diff --git a/simgear/canvas/layout/Layout.cxx b/simgear/canvas/layout/Layout.cxx index ff6994d1..7ebad9d4 100644 --- a/simgear/canvas/layout/Layout.cxx +++ b/simgear/canvas/layout/Layout.cxx @@ -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(); } diff --git a/simgear/canvas/layout/LayoutItem.cxx b/simgear/canvas/layout/LayoutItem.cxx index 1dfc07d9..5de51ce3 100644 --- a/simgear/canvas/layout/LayoutItem.cxx +++ b/simgear/canvas/layout/LayoutItem.cxx @@ -99,10 +99,7 @@ namespace canvas //---------------------------------------------------------------------------- void LayoutItem::invalidate() { - _flags |= SIZE_HINT_DIRTY - | MINIMUM_SIZE_DIRTY - | MAXIMUM_SIZE_DIRTY; - + _flags |= SIZE_INFO_DIRTY; invalidateParent(); } diff --git a/simgear/canvas/layout/LayoutItem.hxx b/simgear/canvas/layout/LayoutItem.hxx index 810c1a55..f950605d 100644 --- a/simgear/canvas/layout/LayoutItem.hxx +++ b/simgear/canvas/layout/LayoutItem.hxx @@ -108,6 +108,9 @@ namespace canvas */ LayoutItemRef getParent() const; + /// Called before item is removed from a layout + virtual void onRemove() {} + protected: friend class Canvas; diff --git a/simgear/canvas/layout/NasalWidget.cxx b/simgear/canvas/layout/NasalWidget.cxx index d512b7fe..1c1b16cb 100644 --- a/simgear/canvas/layout/NasalWidget.cxx +++ b/simgear/canvas/layout/NasalWidget.cxx @@ -34,19 +34,25 @@ namespace canvas } //---------------------------------------------------------------------------- - void NasalWidget::setGeometry(const SGRect& geom) + void NasalWidget::invalidate() { - if( _geometry == geom ) - return; - _geometry = geom; + LayoutItem::invalidate(); + _flags |= LAYOUT_DIRTY; + } - if( !_set_geometry ) + //---------------------------------------------------------------------------- + void NasalWidget::setGeometry(const SGRect& geom) + { + 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 Deleter; + + naContext c = naNewContext(); + try + { + Deleter del = + nasal::get_member(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) { diff --git a/simgear/canvas/layout/NasalWidget.hxx b/simgear/canvas/layout/NasalWidget.hxx index 1fc4446a..46a81259 100644 --- a/simgear/canvas/layout/NasalWidget.hxx +++ b/simgear/canvas/layout/NasalWidget.hxx @@ -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; diff --git a/simgear/nasal/cppbind/NasalObject.cxx b/simgear/nasal/cppbind/NasalObject.cxx index ac1ead9d..c26ab674 100644 --- a/simgear/nasal/cppbind/NasalObject.cxx +++ b/simgear/nasal/cppbind/NasalObject.cxx @@ -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) { diff --git a/simgear/nasal/cppbind/NasalObject.hxx b/simgear/nasal/cppbind/NasalObject.hxx index bcdd9908..d1ed920d 100644 --- a/simgear/nasal/cppbind/NasalObject.hxx +++ b/simgear/nasal/cppbind/NasalObject.hxx @@ -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); diff --git a/simgear/nasal/cppbind/from_nasal.hxx b/simgear/nasal/cppbind/from_nasal.hxx index fe672c01..368d4a96 100644 --- a/simgear/nasal/cppbind/from_nasal.hxx +++ b/simgear/nasal/cppbind/from_nasal.hxx @@ -63,6 +63,16 @@ namespace nasal } }; + template + 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(c, out); + } + } // namespace nasal #endif /* SG_FROM_NASAL_HXX_ */