]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/layout/NasalWidget.cxx
canvas::Layout: support for contents margins.
[simgear.git] / simgear / canvas / layout / NasalWidget.cxx
index d512b7fe96d7657db052816531e723b93e819e5b..5c027e8518359be9470a54f39c766ae63b5313e8 100644 (file)
@@ -19,6 +19,7 @@
 #include "NasalWidget.hxx"
 
 #include <simgear/canvas/Canvas.hxx>
+#include <simgear/nasal/cppbind/NasalContext.hxx>
 #include <simgear/nasal/cppbind/Ghost.hxx>
 
 namespace simgear
@@ -28,35 +29,38 @@ namespace canvas
 
   //----------------------------------------------------------------------------
   NasalWidget::NasalWidget(naRef impl):
-    Object(impl)
+    Object(impl),
+    _layout_size_hint(32, 32),
+    _layout_min_size(16, 16),
+    _layout_max_size(MAX_SIZE),
+    _user_size_hint(0, 0),
+    _user_min_size(0, 0),
+    _user_max_size(MAX_SIZE)
   {
 
   }
 
   //----------------------------------------------------------------------------
-  void NasalWidget::setGeometry(const SGRect<int>& geom)
+  NasalWidget::~NasalWidget()
   {
-    if( _geometry == geom )
-      return;
-    _geometry = geom;
-
-    if( !_set_geometry )
-      return;
+    onRemove();
+  }
 
-    naContext c = naNewContext();
+  //----------------------------------------------------------------------------
+  void NasalWidget::onRemove()
+  {
     try
     {
-      _set_geometry(nasal::to_nasal(c, this), geom);
+      callMethod<void>("onRemove");
     }
     catch( std::exception const& ex )
     {
       SG_LOG(
         SG_GUI,
         SG_WARN,
-        "NasalWidget::setGeometry: callback error: '" << ex.what() << "'"
+        "NasalWidget::onRemove: callback error: '" << ex.what() << "'"
       );
     }
-    naFreeContext(c);
   }
 
   //----------------------------------------------------------------------------
@@ -69,68 +73,82 @@ namespace canvas
   void NasalWidget::setHeightForWidthFunc(const HeightForWidthFunc& func)
   {
     _height_for_width = func;
-    invalidateParent();
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
   void NasalWidget::setMinimumHeightForWidthFunc(const HeightForWidthFunc& func)
   {
     _min_height_for_width = func;
-    invalidateParent();
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
   void NasalWidget::setSizeHint(const SGVec2i& s)
   {
-    if( _size_hint == s )
+    if( _user_size_hint == s )
       return;
 
-    _size_hint = s;
+    _user_size_hint = s;
 
     // TODO just invalidate size_hint? Probably not a performance issue...
-    invalidateParent();
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
   void NasalWidget::setMinimumSize(const SGVec2i& s)
   {
-    if( _min_size == s )
+    if( _user_min_size == s )
       return;
 
-    _min_size = s;
-    invalidateParent();
+    _user_min_size = s;
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
   void NasalWidget::setMaximumSize(const SGVec2i& s)
   {
-    if( _max_size == s )
+    if( _user_max_size == s )
       return;
 
-    _max_size = s;
-    invalidateParent();
+    _user_max_size = s;
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
-  bool NasalWidget::hasHeightForWidth() const
+  void NasalWidget::setLayoutSizeHint(const SGVec2i& s)
   {
-    return !_height_for_width.empty() || !_min_height_for_width.empty();
+    if( _layout_size_hint == s )
+      return;
+
+    _layout_size_hint = s;
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
-  int NasalWidget::heightForWidth(int w) const
+  void NasalWidget::setLayoutMinimumSize(const SGVec2i& s)
   {
-    return callHeightForWidthFunc( _height_for_width.empty()
-                                 ? _min_height_for_width
-                                 : _height_for_width, w );
+    if( _layout_min_size == s )
+      return;
+
+    _layout_min_size = s;
+    invalidate();
   }
 
   //----------------------------------------------------------------------------
-  int NasalWidget::minimumHeightForWidth(int w) const
+  void NasalWidget::setLayoutMaximumSize(const SGVec2i& s)
   {
-    return callHeightForWidthFunc( _min_height_for_width.empty()
-                                 ? _height_for_width
-                                 : _min_height_for_width, w );
+    if( _layout_max_size == s )
+      return;
+
+    _layout_max_size = s;
+    invalidate();
+  }
+
+  //----------------------------------------------------------------------------
+  bool NasalWidget::hasHeightForWidth() const
+  {
+    return !_height_for_width.empty() || !_min_height_for_width.empty();
   }
 
   //----------------------------------------------------------------------------
@@ -153,7 +171,10 @@ namespace canvas
       .method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
       .method("setSizeHint", &NasalWidget::setSizeHint)
       .method("setMinimumSize", &NasalWidget::setMinimumSize)
-      .method("setMaximumSize", &NasalWidget::setMaximumSize);
+      .method("setMaximumSize", &NasalWidget::setMaximumSize)
+      .method("setLayoutSizeHint", &NasalWidget::setLayoutSizeHint)
+      .method("setLayoutMinimumSize", &NasalWidget::setLayoutMinimumSize)
+      .method("setLayoutMaximumSize", &NasalWidget::setLayoutMaximumSize);
 
     nasal::Hash widget_hash = ns.createHash("Widget");
     widget_hash.set("new", &f_makeNasalWidget);
@@ -187,19 +208,87 @@ namespace canvas
   //----------------------------------------------------------------------------
   SGVec2i NasalWidget::sizeHintImpl() const
   {
-    return _size_hint;
+    return SGVec2i(
+      _user_size_hint.x() > 0 ? _user_size_hint.x() : _layout_size_hint.x(),
+      _user_size_hint.y() > 0 ? _user_size_hint.y() : _layout_size_hint.y()
+    );
   }
 
   //----------------------------------------------------------------------------
   SGVec2i NasalWidget::minimumSizeImpl() const
   {
-    return _min_size;
+    return SGVec2i(
+      _user_min_size.x() > 0 ? _user_min_size.x() : _layout_min_size.x(),
+      _user_min_size.y() > 0 ? _user_min_size.y() : _layout_min_size.y()
+    );
   }
 
   //----------------------------------------------------------------------------
   SGVec2i NasalWidget::maximumSizeImpl() const
   {
-    return _max_size;
+    return SGVec2i(
+      _user_max_size.x() < MAX_SIZE.x() ? _user_max_size.x()
+                                        : _layout_max_size.x(),
+      _user_max_size.y() < MAX_SIZE.y() ? _user_max_size.y()
+                                        : _layout_max_size.y()
+    );
+  }
+
+
+  //----------------------------------------------------------------------------
+  int NasalWidget::heightForWidthImpl(int w) const
+  {
+    return callHeightForWidthFunc( _height_for_width.empty()
+                                 ? _min_height_for_width
+                                 : _height_for_width, w );
+  }
+
+  //----------------------------------------------------------------------------
+  int NasalWidget::minimumHeightForWidthImpl(int w) const
+  {
+    return callHeightForWidthFunc( _min_height_for_width.empty()
+                                 ? _height_for_width
+                                 : _min_height_for_width, w );
+  }
+
+
+  //----------------------------------------------------------------------------
+  void NasalWidget::contentsRectChanged(const SGRect<int>& rect)
+  {
+    if( !_set_geometry )
+      return;
+
+    try
+    {
+      nasal::Context c;
+      _set_geometry(nasal::to_nasal(c, this), rect);
+      _flags &= ~LAYOUT_DIRTY;
+    }
+    catch( std::exception const& ex )
+    {
+      SG_LOG(
+        SG_GUI,
+        SG_WARN,
+        "NasalWidget::setGeometry: callback error: '" << ex.what() << "'"
+      );
+    }
+  }
+
+  //----------------------------------------------------------------------------
+  void NasalWidget::visibilityChanged(bool visible)
+  {
+    try
+    {
+      callMethod<void>("visibilityChanged", visible);
+    }
+    catch( std::exception const& ex )
+    {
+      SG_LOG(
+        SG_GUI,
+        SG_WARN,
+        "NasalWidget::visibilityChanged: callback error: '" << ex.what() << "'"
+      );
+    }
   }
 
 } // namespace canvas