]> 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 7c2e180b7856fd20c81790b62c8a78c63dc11dcb..f585b257808e7f379da3ac77f512d7bcb39bbf67 100644 (file)
@@ -23,12 +23,60 @@ 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)
@@ -42,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
   {
@@ -51,7 +137,7 @@ namespace canvas
       _flags &= ~SIZE_HINT_DIRTY;
     }
 
-    return _size_hint;
+    return addClipOverflow(_size_hint, _margins.size());
   }
 
   //----------------------------------------------------------------------------
@@ -63,7 +149,7 @@ namespace canvas
       _flags &= ~MINIMUM_SIZE_DIRTY;
     }
 
-    return _min_size;
+    return addClipOverflow(_min_size, _margins.size());
   }
 
   //----------------------------------------------------------------------------
@@ -75,7 +161,7 @@ namespace canvas
       _flags &= ~MAXIMUM_SIZE_DIRTY;
     }
 
-    return _max_size;
+    return addClipOverflow(_max_size, _margins.size());
   }
 
   //----------------------------------------------------------------------------
@@ -87,19 +173,44 @@ namespace canvas
   //----------------------------------------------------------------------------
   int LayoutItem::heightForWidth(int w) const
   {
-    return -1;
+    int h = heightForWidthImpl(w - _margins.horiz());
+    return h < 0 ? -1 : SGMisc<int>::addClipOverflow(h, _margins.vert());
   }
 
   //------------------------------------------------------------------------------
   int LayoutItem::minimumHeightForWidth(int w) const
   {
-    return heightForWidth(w);
+    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;
+    _flags |= SIZE_INFO_DIRTY | LAYOUT_DIRTY;
     invalidateParent();
   }
 
@@ -111,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();
   }
 
   //----------------------------------------------------------------------------
@@ -140,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());
   }
 
   //----------------------------------------------------------------------------
@@ -167,5 +298,43 @@ namespace canvas
     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
 } // namespace simgear