tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / layouter / CollapsingLayouter.cpp
blobd070d11365b09aae67956ef8cf1eca91519e26dd
1 /*
2 * Copyright 2011, Haiku, Inc.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
6 #include "CollapsingLayouter.h"
8 #include "ComplexLayouter.h"
9 #include "OneElementLayouter.h"
10 #include "SimpleLayouter.h"
12 #include <ObjectList.h>
13 #include <Size.h>
16 class CollapsingLayouter::ProxyLayoutInfo : public LayoutInfo {
17 public:
18 ProxyLayoutInfo(LayoutInfo* target, int32 elementCount)
20 fTarget(target),
21 fElementCount(elementCount)
23 fElements = new int32[elementCount];
26 ~ProxyLayoutInfo()
28 delete[] fElements;
29 delete fTarget;
32 void
33 LayoutTarget(Layouter* layouter, float size)
35 if (layouter)
36 layouter->Layout(fTarget, size);
39 void
40 SetElementPosition(int32 element, int32 position)
42 fElements[element] = position;
45 float
46 ElementLocation(int32 element)
48 if (element < 0 || element >= fElementCount || fElements[element] < 0)
49 return 0;
50 return fTarget->ElementLocation(fElements[element]);
53 float
54 ElementSize(int32 element)
56 if (element < 0 || element >= fElementCount || fElements[element] < 0)
57 return 0;
58 return fTarget->ElementSize(fElements[element]);
61 float
62 ElementRangeSize(int32 element, int32 length)
64 if (element < 0 || element >= fElementCount || fElements[element] < 0)
65 return 0;
66 return fTarget->ElementRangeSize(fElements[element], length);
69 private:
70 int32* fElements;
71 LayoutInfo* fTarget;
72 int32 fElementCount;
76 struct CollapsingLayouter::Constraint {
77 int32 length;
78 float min;
79 float max;
80 float preferred;
84 struct CollapsingLayouter::ElementInfo {
85 float weight;
86 int32 position;
87 bool valid;
88 BObjectList<Constraint> constraints;
90 ElementInfo()
92 weight(0),
93 position(-1),
94 valid(false),
95 constraints(5, true)
99 ~ElementInfo()
103 void SetTo(const ElementInfo& other)
105 weight = other.weight;
106 position = other.position;
107 valid = other.valid;
108 for (int32 i = other.constraints.CountItems() - 1; i >= 0; i--)
109 constraints.AddItem(new Constraint(*other.constraints.ItemAt(i)));
114 CollapsingLayouter::CollapsingLayouter(int32 elementCount, float spacing)
116 fElementCount(elementCount),
117 fElements(new ElementInfo[elementCount]),
118 fValidElementCount(0),
119 fHaveMultiElementConstraints(false),
120 fSpacing(spacing),
121 fLayouter(NULL)
126 CollapsingLayouter::~CollapsingLayouter()
128 delete[] fElements;
129 delete fLayouter;
133 void
134 CollapsingLayouter::AddConstraints(int32 element, int32 length, float min,
135 float max, float preferred)
137 if (min == B_SIZE_UNSET && max == B_SIZE_UNSET)
138 return;
139 if (element < 0 || length <= 0 || element + length > fElementCount)
140 return;
142 Constraint* constraint = new Constraint();
143 constraint->length = length;
144 constraint->min = min;
145 constraint->max = max;
146 constraint->preferred = preferred;
148 if (length > 1)
149 fHaveMultiElementConstraints = true;
151 int32 validElements = fValidElementCount;
153 for (int32 i = element; i < element + length; i++) {
154 if (fElements[i].valid == false) {
155 fElements[i].valid = true;
156 fValidElementCount++;
160 fElements[element].constraints.AddItem(constraint);
161 if (fValidElementCount > validElements) {
162 delete fLayouter;
163 fLayouter = NULL;
166 if (fLayouter)
167 _AddConstraints(element, constraint);
172 void
173 CollapsingLayouter::SetWeight(int32 element, float weight)
175 if (element < 0 || element >= fElementCount)
176 return;
178 ElementInfo& elementInfo = fElements[element];
179 elementInfo.weight = weight;
181 if (fLayouter && elementInfo.position >= 0)
182 fLayouter->SetWeight(elementInfo.position, weight);
186 float
187 CollapsingLayouter::MinSize()
189 _ValidateLayouter();
190 return fLayouter ? fLayouter->MinSize() : 0;
194 float
195 CollapsingLayouter::MaxSize()
197 _ValidateLayouter();
198 return fLayouter ? fLayouter->MaxSize() : B_SIZE_UNLIMITED;
202 float
203 CollapsingLayouter::PreferredSize()
205 _ValidateLayouter();
206 return fLayouter ? fLayouter->PreferredSize() : 0;
210 LayoutInfo*
211 CollapsingLayouter::CreateLayoutInfo()
213 _ValidateLayouter();
215 LayoutInfo* info = fLayouter ? fLayouter->CreateLayoutInfo() : NULL;
216 return new ProxyLayoutInfo(info, fElementCount);
220 void
221 CollapsingLayouter::Layout(LayoutInfo* layoutInfo, float size)
223 _ValidateLayouter();
224 ProxyLayoutInfo* info = static_cast<ProxyLayoutInfo*>(layoutInfo);
225 for (int32 i = 0; i < fElementCount; i++) {
226 info->SetElementPosition(i, fElements[i].position);
229 info->LayoutTarget(fLayouter, size);
233 Layouter*
234 CollapsingLayouter::CloneLayouter()
236 CollapsingLayouter* clone = new CollapsingLayouter(fElementCount, fSpacing);
237 for (int32 i = 0; i < fElementCount; i++)
238 clone->fElements[i].SetTo(fElements[i]);
240 clone->fValidElementCount = fValidElementCount;
241 clone->fHaveMultiElementConstraints = fHaveMultiElementConstraints;
243 if (fLayouter)
244 clone->fLayouter = fLayouter->CloneLayouter();
245 return clone;
249 void
250 CollapsingLayouter::_ValidateLayouter()
252 if (fLayouter)
253 return;
255 _CreateLayouter();
256 _DoCollapse();
257 _AddConstraints();
258 _SetWeights();
262 Layouter*
263 CollapsingLayouter::_CreateLayouter()
265 if (fLayouter)
266 return fLayouter;
268 if (fValidElementCount == 0) {
269 fLayouter = NULL;
270 } else if (fValidElementCount == 1) {
271 fLayouter = new OneElementLayouter();
272 } else if (fHaveMultiElementConstraints) {
273 fLayouter = new ComplexLayouter(fValidElementCount, fSpacing);
274 } else {
275 fLayouter = new SimpleLayouter(fValidElementCount, fSpacing);
278 return fLayouter;
282 void
283 CollapsingLayouter::_DoCollapse()
285 int32 shift = 0;
286 for (int32 i = 0; i < fElementCount; i++) {
287 ElementInfo& element = fElements[i];
288 if (!element.valid) {
289 shift++;
290 element.position = -1;
291 continue;
292 } else {
293 element.position = i - shift;
299 void
300 CollapsingLayouter::_AddConstraints()
302 if (fLayouter == NULL)
303 return;
305 for (int32 i = 0; i < fElementCount; i++) {
306 ElementInfo& element = fElements[i];
307 for (int32 i = element.constraints.CountItems() - 1; i >= 0; i--)
308 _AddConstraints(element.position, element.constraints.ItemAt(i));
313 void
314 CollapsingLayouter::_AddConstraints(int32 position, const Constraint* c)
316 fLayouter->AddConstraints(position, c->length, c->min, c->max,
317 c->preferred);
321 void
322 CollapsingLayouter::_SetWeights()
324 if (!fLayouter)
325 return;
327 for (int32 i = 0; i < fElementCount; i++) {
328 fLayouter->SetWeight(fElements[i].position, fElements[i].weight);