]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/layout/LayoutItem.cxx
canvas::Layout: support for contents margins.
[simgear.git] / simgear / canvas / layout / LayoutItem.cxx
index 31be629ea309116211ffb5238d13215277094fad..f585b257808e7f379da3ac77f512d7bcb39bbf67 100644 (file)
@@ -24,9 +24,62 @@ namespace simgear
 namespace canvas
 {
 
+  //----------------------------------------------------------------------------
+  Margins::Margins(int m):
+    l(m), t(m), r(m), b(m)
+  {
+
+  }
+
+  //----------------------------------------------------------------------------
+  Margins::Margins(int h, int v):
+    l(h), t(v),
+    r(h), b(v)
+  {
+
+  }
+
+  //----------------------------------------------------------------------------
+  Margins::Margins(int l, int t, int r, int b):
+    l(l), t(t), r(r), b(b)
+  {
+
+  }
+
+  //----------------------------------------------------------------------------
+  int Margins::horiz() const
+  {
+    return l + r;
+  }
+
+  //----------------------------------------------------------------------------
+  int Margins::vert() const
+  {
+    return t + b;
+  }
+
+  //----------------------------------------------------------------------------
+  SGVec2i Margins::size() const
+  {
+    return SGVec2i(horiz(), vert());
+  }
+
+  //----------------------------------------------------------------------------
+  bool Margins::isNull() const
+  {
+    return l == 0 && t == 0 && r == 0 && b == 0;
+  }
+
+  //----------------------------------------------------------------------------
+  const SGVec2i LayoutItem::MAX_SIZE( SGLimits<int>::max(),
+                                      SGLimits<int>::max() );
+
   //----------------------------------------------------------------------------
   LayoutItem::LayoutItem():
-    _flags(0)
+    _flags(VISIBLE),
+    _size_hint(0, 0),
+    _min_size(0, 0),
+    _max_size(MAX_SIZE)
   {
     invalidate();
   }
@@ -37,6 +90,44 @@ namespace canvas
 
   }
 
+  //----------------------------------------------------------------------------
+  void LayoutItem::setContentsMargins(const Margins& margins)
+  {
+    _margins = margins;
+  }
+
+  //----------------------------------------------------------------------------
+  void LayoutItem::setContentsMargins(int left, int top, int right, int bottom)
+  {
+    _margins.l = left;
+    _margins.t = top;
+    _margins.r = right;
+    _margins.b = bottom;
+  }
+
+  //----------------------------------------------------------------------------
+  void LayoutItem::setContentsMargin(int margin)
+  {
+    setContentsMargins(margin, margin, margin, margin);
+  }
+
+  //----------------------------------------------------------------------------
+  Margins LayoutItem::getContentsMargins() const
+  {
+    return _margins;
+  }
+
+  //----------------------------------------------------------------------------
+  SGRecti LayoutItem::contentsRect() const
+  {
+    return SGRecti(
+      _geometry.x() + _margins.l,
+      _geometry.y() + _margins.t,
+      std::max(0, _geometry.width() - _margins.horiz()),
+      std::max(0, _geometry.height() - _margins.vert())
+    );
+  }
+
   //----------------------------------------------------------------------------
   SGVec2i LayoutItem::sizeHint() const
   {
@@ -46,7 +137,7 @@ namespace canvas
       _flags &= ~SIZE_HINT_DIRTY;
     }
 
-    return _size_hint;
+    return addClipOverflow(_size_hint, _margins.size());
   }
 
   //----------------------------------------------------------------------------
@@ -58,7 +149,7 @@ namespace canvas
       _flags &= ~MINIMUM_SIZE_DIRTY;
     }
 
-    return _min_size;
+    return addClipOverflow(_min_size, _margins.size());
   }
 
   //----------------------------------------------------------------------------
@@ -70,16 +161,56 @@ namespace canvas
       _flags &= ~MAXIMUM_SIZE_DIRTY;
     }
 
-    return _max_size;
+    return addClipOverflow(_max_size, _margins.size());
   }
 
   //----------------------------------------------------------------------------
-  void LayoutItem::invalidate()
+  bool LayoutItem::hasHeightForWidth() const
   {
-    _flags |= SIZE_HINT_DIRTY
-           |  MINIMUM_SIZE_DIRTY
-           |  MAXIMUM_SIZE_DIRTY;
+    return false;
+  }
+
+  //----------------------------------------------------------------------------
+  int LayoutItem::heightForWidth(int w) const
+  {
+    int h = heightForWidthImpl(w - _margins.horiz());
+    return h < 0 ? -1 : SGMisc<int>::addClipOverflow(h, _margins.vert());
+  }
+
+  //------------------------------------------------------------------------------
+  int LayoutItem::minimumHeightForWidth(int w) const
+  {
+    int h = minimumHeightForWidthImpl(w - _margins.horiz());
+    return h < 0 ? -1 : SGMisc<int>::addClipOverflow(h, _margins.vert());
+  }
+
+  //----------------------------------------------------------------------------
+  void LayoutItem::setVisible(bool visible)
+  {
+    if( visible )
+      _flags &= ~EXPLICITLY_HIDDEN;
+    else
+      _flags |= EXPLICITLY_HIDDEN;
+
+    setVisibleInternal(visible);
+  }
+
+  //----------------------------------------------------------------------------
+  bool LayoutItem::isVisible() const
+  {
+    return _flags & VISIBLE;
+  }
+
+  //----------------------------------------------------------------------------
+  bool LayoutItem::isExplicitlyHidden() const
+  {
+    return _flags & EXPLICITLY_HIDDEN;
+  }
 
+  //----------------------------------------------------------------------------
+  void LayoutItem::invalidate()
+  {
+    _flags |= SIZE_INFO_DIRTY | LAYOUT_DIRTY;
     invalidateParent();
   }
 
@@ -91,10 +222,23 @@ namespace canvas
       parent->invalidate();
   }
 
+  //----------------------------------------------------------------------------
+  void LayoutItem::update()
+  {
+    if( (_flags & LAYOUT_DIRTY) && isVisible() )
+      contentsRectChanged( contentsRect() );
+  }
+
   //----------------------------------------------------------------------------
   void LayoutItem::setGeometry(const SGRecti& geom)
   {
-    _geometry = geom;
+    if( geom != _geometry )
+    {
+      _geometry = geom;
+      _flags |= LAYOUT_DIRTY;
+    }
+
+    update();
   }
 
   //----------------------------------------------------------------------------
@@ -120,7 +264,14 @@ namespace canvas
   {
     _parent = parent;
     LayoutItemRef parent_ref = parent.lock();
-    setCanvas(parent_ref ? parent_ref->_canvas : CanvasWeakPtr());
+
+    if( parent_ref )
+      // Only change the canvas if there is a new parent. If the item is removed
+      // keep the old canvas, as it may be used for example during the call to
+      // onRemove.
+      setCanvas(parent_ref->_canvas);
+
+    setVisibleInternal(!parent_ref || parent_ref->isVisible());
   }
 
   //----------------------------------------------------------------------------
@@ -132,19 +283,57 @@ namespace canvas
   //----------------------------------------------------------------------------
   SGVec2i LayoutItem::sizeHintImpl() const
   {
-    return SGVec2i(16, 16);
+    return _size_hint;
   }
 
   //----------------------------------------------------------------------------
   SGVec2i LayoutItem::minimumSizeImpl() const
   {
-    return SGVec2i(0, 0);
+    return _min_size;
   }
 
   //----------------------------------------------------------------------------
   SGVec2i LayoutItem::maximumSizeImpl() const
   {
-    return SGVec2i(SGLimits<int>::max(), SGLimits<int>::max());
+    return _max_size;
+  }
+
+  //----------------------------------------------------------------------------
+  int LayoutItem::heightForWidthImpl(int w) const
+  {
+    return -1;
+  }
+
+  //------------------------------------------------------------------------------
+  int LayoutItem::minimumHeightForWidthImpl(int w) const
+  {
+    return heightForWidth(w);
+  }
+
+  //----------------------------------------------------------------------------
+  void LayoutItem::setVisibleInternal(bool visible)
+  {
+    LayoutItemRef parent = getParent();
+    if( isExplicitlyHidden() || (parent && !parent->isVisible()) )
+      visible = false;
+
+    if( isVisible() == visible )
+      return;
+
+    invalidateParent();
+
+    if( visible )
+      _flags |= VISIBLE;
+    else
+      _flags &= ~VISIBLE;
+
+    visibilityChanged(visible);
+  }
+
+  //----------------------------------------------------------------------------
+  void LayoutItem::callSetVisibleInternal(LayoutItem* item, bool visible)
+  {
+    item->setVisibleInternal(visible);
   }
 
 } // namespace canvas