[haiku-commits] r41252 - in haiku/trunk/src/kits/interface: . layouter

  • From: yourpalal2@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 15 Apr 2011 01:20:28 +0200 (CEST)

Author: yourpalal
Date: 2011-04-15 01:20:27 +0200 (Fri, 15 Apr 2011)
New Revision: 41252
Changeset: https://dev.haiku-os.org/changeset/41252
Ticket: https://dev.haiku-os.org/ticket/6979

Added:
   haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.cpp
   haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.h
Modified:
   haiku/trunk/src/kits/interface/GridLayout.cpp
   haiku/trunk/src/kits/interface/Jamfile
   haiku/trunk/src/kits/interface/TwoDimensionalLayout.cpp
Log:
Add a new layouter 'CollapsingLayouter', which is used by BTwoDimensionalLayout 
to collapse empty rows or columns. Update BGridLayout so that empty 
rows/columns are given min/max constraints of B_SIZE_UNSET by default, which 
allows them to be collapsed. Fixes #6979


Modified: haiku/trunk/src/kits/interface/GridLayout.cpp
===================================================================
--- haiku/trunk/src/kits/interface/GridLayout.cpp       2011-04-14 23:00:33 UTC 
(rev 41251)
+++ haiku/trunk/src/kits/interface/GridLayout.cpp       2011-04-14 23:20:27 UTC 
(rev 41252)
@@ -90,7 +90,7 @@
        {
                if (Info* info = _InfoAt(index))
                        return info->minSize;
-               return -1;
+               return B_SIZE_UNSET;
        }
 
        void SetMinSize(int32 index, float size)
@@ -103,7 +103,7 @@
        {
                if (Info* info = _InfoAt(index))
                        return info->maxSize;
-               return B_SIZE_UNLIMITED;
+               return B_SIZE_UNSET;
        }
 
        void SetMaxSize(int32 index, float size)
@@ -138,8 +138,8 @@
                        for (int32 i = count; i <= index; i++) {
                                Info* info = new Info;
                                info->weight = 1;
-                               info->minSize = 0;
-                               info->maxSize = B_SIZE_UNLIMITED;
+                               info->minSize = B_SIZE_UNSET;
+                               info->maxSize = B_SIZE_UNSET;
                                fInfos.AddItem(info);
                        }
                }

Modified: haiku/trunk/src/kits/interface/Jamfile
===================================================================
--- haiku/trunk/src/kits/interface/Jamfile      2011-04-14 23:00:33 UTC (rev 
41251)
+++ haiku/trunk/src/kits/interface/Jamfile      2011-04-14 23:20:27 UTC (rev 
41252)
@@ -133,6 +133,7 @@
        WidthBuffer.cpp
 
        # layouter
+       CollapsingLayouter.cpp
        ComplexLayouter.cpp
        Layouter.cpp
        LayoutOptimizer.cpp

Modified: haiku/trunk/src/kits/interface/TwoDimensionalLayout.cpp
===================================================================
--- haiku/trunk/src/kits/interface/TwoDimensionalLayout.cpp     2011-04-14 
23:00:33 UTC (rev 41251)
+++ haiku/trunk/src/kits/interface/TwoDimensionalLayout.cpp     2011-04-14 
23:20:27 UTC (rev 41252)
@@ -18,9 +18,7 @@
 
 #include <Referenceable.h>
 
-#include "ComplexLayouter.h"
-#include "OneElementLayouter.h"
-#include "SimpleLayouter.h"
+#include "CollapsingLayouter.h"
 
 
 
@@ -706,12 +704,7 @@
 
        int elementCount = _CountElements();
 
-       if (elementCount <= 1)
-               fLayouter = new OneElementLayouter();
-       else if (_HasMultiElementItems())
-               fLayouter = new ComplexLayouter(elementCount, _Spacing());
-       else
-               fLayouter = new SimpleLayouter(elementCount, _Spacing());
+       fLayouter = new CollapsingLayouter(elementCount, _Spacing());
 
        // tell the layouter about our constraints
        // TODO: We should probably ignore local layouters whose view is hidden.

Added: haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.cpp
===================================================================
--- haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.cpp              
                (rev 0)
+++ haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.cpp      
2011-04-14 23:20:27 UTC (rev 41252)
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2011, Haiku, Inc.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#include "CollapsingLayouter.h"
+
+#include "ComplexLayouter.h"
+#include "OneElementLayouter.h"
+#include "SimpleLayouter.h"
+
+#include <ObjectList.h>
+#include <Size.h>
+
+
+class CollapsingLayouter::ProxyLayoutInfo : public LayoutInfo {
+public:
+       ProxyLayoutInfo(LayoutInfo* target, int32 elementCount)
+               :
+               fTarget(target),
+               fElementCount(elementCount)
+       {
+               fElements = new int32[elementCount];
+       }
+
+       ~ProxyLayoutInfo()
+       {
+               delete[] fElements;
+               delete fTarget;
+       }
+
+       void
+       LayoutTarget(Layouter* layouter, float size)
+       {
+               if (layouter)
+                       layouter->Layout(fTarget, size);
+       }
+
+       void
+       SetElementPosition(int32 element, int32 position)
+       {
+               fElements[element] = position;
+       }
+
+       float
+       ElementLocation(int32 element)
+       {
+               if (element < 0 || element >= fElementCount || 
fElements[element] < 0)
+                       return 0;
+               return fTarget->ElementLocation(fElements[element]);
+       }
+
+       float
+       ElementSize(int32 element)
+       {
+               if (element < 0 || element >= fElementCount || 
fElements[element] < 0)
+                       return 0;
+               return fTarget->ElementSize(fElements[element]);
+       }
+
+       float
+       ElementRangeSize(int32 element, int32 length)
+       {
+               if (element < 0 || element >= fElementCount || 
fElements[element] < 0)
+                       return 0;
+               return fTarget->ElementRangeSize(fElements[element], length);
+       }
+
+private:
+       int32*                                  fElements;
+       LayoutInfo*                             fTarget;
+       int32                                   fElementCount;
+};
+
+
+struct CollapsingLayouter::Constraint {
+       int32 length;
+       float min;
+       float max;
+       float preferred;
+};
+
+
+struct CollapsingLayouter::ElementInfo {
+       float weight;
+       int32 position;
+       bool valid;
+       BObjectList<Constraint> constraints;
+
+       ElementInfo()
+               :
+               weight(0),
+               position(-1),
+               valid(false),
+               constraints(5, true)
+       {
+       }
+
+       ~ElementInfo()
+       {
+       }
+
+       void SetTo(const ElementInfo& other)
+       {
+               weight = other.weight;
+               position = other.position;
+               valid = other.valid;
+               for (int32 i = other.constraints.CountItems() - 1; i >= 0; i--)
+                       constraints.AddItem(new 
Constraint(*other.constraints.ItemAt(i)));
+       }
+
+       int32 LengthOfLongestConstraint()
+       {
+               int32 length = 0;
+               for (int32 i = constraints.CountItems() - 1; i >= 0; i--)
+                       length = max_c(length, constraints.ItemAt(i)->length);
+               return length;
+       }
+};
+
+
+CollapsingLayouter::CollapsingLayouter(int32 elementCount, float spacing)
+       :
+       fElementCount(elementCount),
+       fElements(new ElementInfo[elementCount]),
+       fValidElementCount(0),
+       fHaveMultiElementConstraints(false),
+       fSpacing(spacing),
+       fLayouter(NULL)
+{
+}
+
+
+CollapsingLayouter::~CollapsingLayouter()
+{
+       delete[] fElements;
+       delete fLayouter;
+}
+
+
+void
+CollapsingLayouter::AddConstraints(int32 element, int32 length, float min,
+       float max, float preferred)
+{
+       if (min == B_SIZE_UNSET && max == B_SIZE_UNSET)
+               return;
+       if (element < 0 || length <= 0 || element + length > fElementCount)
+               return;
+
+       Constraint* constraint = new Constraint();
+       constraint->length = length;
+       constraint->min = min;
+       constraint->max = max;
+       constraint->preferred = preferred;
+
+       if (length > 1)
+               fHaveMultiElementConstraints = true;
+       
+       int32 validElements = fValidElementCount;
+
+       for (int32 i = element; i < element + length; i++) {
+               if (fElements[i].valid == false) {
+                       fElements[i].valid = true;
+                       fValidElementCount++;
+               }
+       }
+
+       fElements[element].constraints.AddItem(constraint);
+       if (fValidElementCount > validElements) {
+               delete fLayouter;
+               fLayouter = NULL;
+       }
+
+       if (fLayouter)
+               _AddConstraints(element, constraint);
+       
+}
+
+
+void
+CollapsingLayouter::SetWeight(int32 element, float weight)
+{
+       if (element < 0 || element >= fElementCount)
+               return;
+
+       ElementInfo& elementInfo = fElements[element];
+       elementInfo.weight = weight;
+
+       if (fLayouter && elementInfo.position >= 0)
+               fLayouter->SetWeight(elementInfo.position, weight);
+}
+
+
+float
+CollapsingLayouter::MinSize()
+{
+       _ValidateLayouter();
+       return fLayouter->MinSize();
+}
+
+
+float
+CollapsingLayouter::MaxSize()
+{
+       _ValidateLayouter();
+       return fLayouter->MaxSize();
+}
+
+
+float
+CollapsingLayouter::PreferredSize()
+{
+       _ValidateLayouter();
+       return fLayouter->PreferredSize();
+}
+
+
+LayoutInfo*
+CollapsingLayouter::CreateLayoutInfo()
+{
+       _ValidateLayouter();
+
+       return new ProxyLayoutInfo(fLayouter->CreateLayoutInfo(), 
fElementCount);
+}
+
+
+void
+CollapsingLayouter::Layout(LayoutInfo* layoutInfo, float size)
+{
+       _ValidateLayouter();
+       ProxyLayoutInfo* info = static_cast<ProxyLayoutInfo*>(layoutInfo);
+       for (int32 i = 0; i < fElementCount; i++) {
+               info->SetElementPosition(i, fElements[i].position);
+       }
+
+       info->LayoutTarget(fLayouter, size);
+}
+
+
+Layouter*
+CollapsingLayouter::CloneLayouter()
+{
+       CollapsingLayouter* clone = new CollapsingLayouter(fElementCount, 
fSpacing);
+       for (int32 i = 0; i < fElementCount; i++)
+               clone->fElements[i].SetTo(fElements[i]);
+
+       clone->fValidElementCount = fValidElementCount;
+       clone->fHaveMultiElementConstraints = fHaveMultiElementConstraints;
+
+       if (fLayouter)
+               clone->fLayouter = fLayouter->CloneLayouter();
+       return clone;
+}
+
+
+void
+CollapsingLayouter::_ValidateLayouter()
+{
+       if (fLayouter)
+               return;
+
+       _CreateLayouter();
+       _DoCollapse();
+       _AddConstraints();
+       _SetWeights();
+}
+
+
+Layouter*
+CollapsingLayouter::_CreateLayouter()
+{
+       if (fLayouter)
+               return fLayouter;
+
+       if (fValidElementCount == 0) {
+               fLayouter =  NULL;
+       } else if (fValidElementCount == 1) {
+               fLayouter =  new OneElementLayouter();
+       } else if (fHaveMultiElementConstraints) {
+               fLayouter =  new ComplexLayouter(fValidElementCount, fSpacing);
+       } else {
+               fLayouter = new SimpleLayouter(fValidElementCount, fSpacing);
+       }
+
+       return fLayouter;
+}
+
+
+void
+CollapsingLayouter::_DoCollapse()
+{
+       int32 shift = 0;
+       for (int32 i = 0; i < fElementCount; i++) {
+               ElementInfo& element = fElements[i];
+               if (!element.valid) {
+                       shift++;
+                       element.position = -1;
+                       continue;
+               } else {
+                       element.position = i - shift;
+               }
+       }
+}
+
+
+void
+CollapsingLayouter::_AddConstraints()
+{
+       if (fLayouter == NULL)
+               return;
+
+       for (int32 i = 0; i < fElementCount; i++) {
+               ElementInfo& element = fElements[i];
+               for (int32 i = element.constraints.CountItems() - 1; i >= 0; 
i--)
+                       _AddConstraints(element.position, 
element.constraints.ItemAt(i));
+       }
+}
+
+
+void
+CollapsingLayouter::_AddConstraints(int32 position, const Constraint* c)
+{
+       fLayouter->AddConstraints(position, c->length, c->min, c->max,
+               c->preferred);
+}
+
+
+void
+CollapsingLayouter::_SetWeights()
+{
+       for (int32 i = 0; i < fElementCount; i++) {
+               fLayouter->SetWeight(fElements[i].position, 
fElements[i].weight);
+       }
+}

Added: haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.h
===================================================================
--- haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.h                
                (rev 0)
+++ haiku/trunk/src/kits/interface/layouter/CollapsingLayouter.h        
2011-04-14 23:20:27 UTC (rev 41252)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011, Haiku, Inc.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#ifndef COLLAPSING_LAYOUTER_H  
+#define COLLAPSING_LAYOUTER_H
+
+#include "Layouter.h"
+
+
+namespace BPrivate {
+namespace Layout {
+
+
+/* This layouter wraps either a Compound, Simple or OneElement layouter, and
+ * removes elements which have no constraints, or min/max constraints of
+ * B_SIZE_UNSET. The child layouter is given only the constraints for the
+ * remaining elements. When using the LayoutInfo of this layouter,
+ * collapsed (removed) elements are given no space on screen.
+ */
+class CollapsingLayouter : public Layouter {
+public:
+                                                               
CollapsingLayouter(int32 elementCount,
+                                                                       float 
spacing);
+       virtual                                         ~CollapsingLayouter();
+
+       virtual void                            AddConstraints(int32 element, 
int32 length,
+                                                                       float 
min, float max, float preferred);
+       virtual void                            SetWeight(int32 element, float 
weight);
+
+       virtual float                           MinSize();
+       virtual float                           MaxSize();
+       virtual float                           PreferredSize();
+
+       virtual LayoutInfo*                     CreateLayoutInfo();
+       
+       virtual void                            Layout(LayoutInfo* layoutInfo, 
float size);
+
+       virtual Layouter*                       CloneLayouter();
+
+
+private:
+       class   ProxyLayoutInfo;
+       struct  Constraint;
+       struct  ElementInfo;
+
+                       void                            _ValidateLayouter();
+                       Layouter*                       _CreateLayouter();
+                       void                            _DoCollapse();
+                       void                            _AddConstraints();
+                       void                            _AddConstraints(int32 
position,
+                                                                       const 
Constraint* c);
+                       void                            _SetWeights();
+
+                       int32                           fElementCount;
+                       ElementInfo*            fElements;
+                       int32                           fValidElementCount;
+                       bool                            
fHaveMultiElementConstraints;
+                       float                           fSpacing;
+                       Layouter*                       fLayouter;
+};
+
+} // namespace Layout
+} // namespace BPrivate
+
+using BPrivate::Layout::CollapsingLayouter;
+
+#endif // COLLAPSING_LAYOUTER_H


Other related posts:

  • » [haiku-commits] r41252 - in haiku/trunk/src/kits/interface: . layouter - yourpalal2