]> git.mxchange.org Git - simgear.git/commitdiff
canvas::Layout: proper cleanup/update on removing items.
authorThomas Geymayer <tomgey@gmail.com>
Sun, 15 Jun 2014 11:47:50 +0000 (13:47 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Sun, 15 Jun 2014 14:30:25 +0000 (16:30 +0200)
simgear/canvas/layout/BoxLayout.cxx
simgear/canvas/layout/BoxLayout.hxx
simgear/canvas/layout/Layout.cxx
simgear/canvas/layout/LayoutItem.cxx
simgear/canvas/layout/LayoutItem.hxx
simgear/canvas/layout/NasalWidget.cxx
simgear/canvas/layout/NasalWidget.hxx
simgear/nasal/cppbind/NasalObject.cxx
simgear/nasal/cppbind/NasalObject.hxx
simgear/nasal/cppbind/from_nasal.hxx

index c7140467efc7a02b627596ab644981d4ff6ed6ca..f6c4c48aeb296c36f9ed62f5be6be80f0d81fcfd 100644 (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();
   }
index fc3b4a25efa7c5e5226b7049252486f3f400285a..8982aeafa8501891308ae08baa0f35111bf43b28 100644 (file)
@@ -40,6 +40,7 @@ namespace canvas
       };
 
       BoxLayout(Direction dir);
+      ~BoxLayout();
 
       virtual void addItem(const LayoutItemRef& item);
 
index ff6994d181bbdea00c85cb75818a175807c1639c..7ebad9d47d31c12dfb70fcc74cb09ef5f7fb1fd2 100644 (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();
   }
index 1dfc07d935a9e872455101c57c98c9774172139c..5de51ce30f4a3c3b367afd68217efeb19c69fa21 100644 (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();
   }
 
index 810c1a553e3f789320ac8ae624e248c50593a52c..f950605d920dd730eef995ecefd66c1f8a5dde27 100644 (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;
index d512b7fe96d7657db052816531e723b93e819e5b..1c1b16cb6a0088a1794aa1ad7bb5788011660562 100644 (file)
@@ -34,19 +34,25 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  void NasalWidget::setGeometry(const SGRect<int>& geom)
+  void NasalWidget::invalidate()
   {
-    if( _geometry == geom )
-      return;
-    _geometry = geom;
+    LayoutItem::invalidate();
+    _flags |= LAYOUT_DIRTY;
+  }
 
-    if( !_set_geometry )
+  //----------------------------------------------------------------------------
+  void NasalWidget::setGeometry(const SGRect<int>& 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<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)
   {
index 1fc4446a1cdd1e961d6b11b41a70a49b453ef3f5..46a8125994a5a2748d84b3a73c54b078f9bcabbb 100644 (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;
index ac1ead9dcd489fb46bce005b9599a0540f56902a..c26ab674182d8444a1c2d151d06e436ea02b22a6 100644 (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)
   {
index bcdd990893aec0b0a02bc5b977692271f7cde603..d1ed920da25d2996c69642a9ca014eab096591f5 100644 (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);
 
index fe672c0178a1dcd56240571a11846134c70f8313..368d4a96f2bf998c75ead0fad86b58f817b7edb7 100644 (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_ */