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
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41252 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -90,7 +90,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (Info* info = _InfoAt(index))
|
if (Info* info = _InfoAt(index))
|
||||||
return info->minSize;
|
return info->minSize;
|
||||||
return -1;
|
return B_SIZE_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMinSize(int32 index, float size)
|
void SetMinSize(int32 index, float size)
|
||||||
@@ -103,7 +103,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (Info* info = _InfoAt(index))
|
if (Info* info = _InfoAt(index))
|
||||||
return info->maxSize;
|
return info->maxSize;
|
||||||
return B_SIZE_UNLIMITED;
|
return B_SIZE_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMaxSize(int32 index, float size)
|
void SetMaxSize(int32 index, float size)
|
||||||
@@ -138,8 +138,8 @@ private:
|
|||||||
for (int32 i = count; i <= index; i++) {
|
for (int32 i = count; i <= index; i++) {
|
||||||
Info* info = new Info;
|
Info* info = new Info;
|
||||||
info->weight = 1;
|
info->weight = 1;
|
||||||
info->minSize = 0;
|
info->minSize = B_SIZE_UNSET;
|
||||||
info->maxSize = B_SIZE_UNLIMITED;
|
info->maxSize = B_SIZE_UNSET;
|
||||||
fInfos.AddItem(info);
|
fInfos.AddItem(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ MergeObject <libbe>interface_kit.o :
|
|||||||
WidthBuffer.cpp
|
WidthBuffer.cpp
|
||||||
|
|
||||||
# layouter
|
# layouter
|
||||||
|
CollapsingLayouter.cpp
|
||||||
ComplexLayouter.cpp
|
ComplexLayouter.cpp
|
||||||
Layouter.cpp
|
Layouter.cpp
|
||||||
LayoutOptimizer.cpp
|
LayoutOptimizer.cpp
|
||||||
|
|||||||
@@ -18,9 +18,7 @@
|
|||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "ComplexLayouter.h"
|
#include "CollapsingLayouter.h"
|
||||||
#include "OneElementLayouter.h"
|
|
||||||
#include "SimpleLayouter.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -706,12 +704,7 @@ BTwoDimensionalLayout::CompoundLayouter::ValidateMinMax()
|
|||||||
|
|
||||||
int elementCount = _CountElements();
|
int elementCount = _CountElements();
|
||||||
|
|
||||||
if (elementCount <= 1)
|
fLayouter = new CollapsingLayouter(elementCount, _Spacing());
|
||||||
fLayouter = new OneElementLayouter();
|
|
||||||
else if (_HasMultiElementItems())
|
|
||||||
fLayouter = new ComplexLayouter(elementCount, _Spacing());
|
|
||||||
else
|
|
||||||
fLayouter = new SimpleLayouter(elementCount, _Spacing());
|
|
||||||
|
|
||||||
// tell the layouter about our constraints
|
// tell the layouter about our constraints
|
||||||
// TODO: We should probably ignore local layouters whose view is hidden.
|
// TODO: We should probably ignore local layouters whose view is hidden.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user