xref: /haiku/src/kits/interface/GroupLayout.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  * Copyright 2010, Haiku, Inc.
3  * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <GroupLayout.h>
9 
10 #include <ControlLook.h>
11 #include <LayoutItem.h>
12 #include <Message.h>
13 
14 #include <new>
15 
16 
17 using std::nothrow;
18 
19 
20 namespace {
21 	const char* const kItemWeightField = "BGroupLayout:item:weight";
22 	const char* const kVerticalField = "BGroupLayout:vertical";
23 }
24 
25 
26 struct BGroupLayout::ItemLayoutData {
27 	float	weight;
28 
29 	ItemLayoutData()
30 		: weight(1)
31 	{
32 	}
33 };
34 
35 
36 BGroupLayout::BGroupLayout(enum orientation orientation, float spacing)
37 	:
38 	BTwoDimensionalLayout(),
39 	fOrientation(orientation)
40 {
41 	SetSpacing(spacing);
42 }
43 
44 
45 BGroupLayout::BGroupLayout(BMessage* from)
46 	:
47 	BTwoDimensionalLayout(from)
48 {
49 	bool isVertical;
50 	if (from->FindBool(kVerticalField, &isVertical) != B_OK)
51 		isVertical = false;
52 	fOrientation = isVertical ? B_VERTICAL : B_HORIZONTAL;
53 }
54 
55 
56 BGroupLayout::~BGroupLayout()
57 {
58 }
59 
60 
61 float
62 BGroupLayout::Spacing() const
63 {
64 	return fHSpacing;
65 }
66 
67 
68 void
69 BGroupLayout::SetSpacing(float spacing)
70 {
71 	spacing = BControlLook::ComposeSpacing(spacing);
72 	if (spacing != fHSpacing) {
73 		fHSpacing = spacing;
74 		fVSpacing = spacing;
75 		InvalidateLayout();
76 	}
77 }
78 
79 
80 orientation
81 BGroupLayout::Orientation() const
82 {
83 	return fOrientation;
84 }
85 
86 
87 void
88 BGroupLayout::SetOrientation(enum orientation orientation)
89 {
90 	if (orientation != fOrientation) {
91 		fOrientation = orientation;
92 
93 		InvalidateLayout();
94 	}
95 }
96 
97 
98 float
99 BGroupLayout::ItemWeight(int32 index) const
100 {
101 	if (index < 0 || index >= CountItems())
102 		return 0;
103 
104 	ItemLayoutData* data = _LayoutDataForItem(ItemAt(index));
105 	return (data ? data->weight : 0);
106 }
107 
108 
109 void
110 BGroupLayout::SetItemWeight(int32 index, float weight)
111 {
112 	if (index < 0 || index >= CountItems())
113 		return;
114 
115 	if (ItemLayoutData* data = _LayoutDataForItem(ItemAt(index)))
116 		data->weight = weight;
117 
118 	InvalidateLayout();
119 }
120 
121 
122 BLayoutItem*
123 BGroupLayout::AddView(BView* child)
124 {
125 	return BTwoDimensionalLayout::AddView(child);
126 }
127 
128 
129 BLayoutItem*
130 BGroupLayout::AddView(int32 index, BView* child)
131 {
132 	return BTwoDimensionalLayout::AddView(index, child);
133 }
134 
135 
136 BLayoutItem*
137 BGroupLayout::AddView(BView* child, float weight)
138 {
139 	return AddView(-1, child, weight);
140 }
141 
142 
143 BLayoutItem*
144 BGroupLayout::AddView(int32 index, BView* child, float weight)
145 {
146 	BLayoutItem* item = AddView(index, child);
147 	if (ItemLayoutData* data = _LayoutDataForItem(item))
148 		data->weight = weight;
149 
150 	return item;
151 }
152 
153 
154 bool
155 BGroupLayout::AddItem(BLayoutItem* item)
156 {
157 	return BTwoDimensionalLayout::AddItem(item);
158 }
159 
160 
161 bool
162 BGroupLayout::AddItem(int32 index, BLayoutItem* item)
163 {
164 	return BTwoDimensionalLayout::AddItem(index, item);
165 }
166 
167 
168 bool
169 BGroupLayout::AddItem(BLayoutItem* item, float weight)
170 {
171 	return AddItem(-1, item, weight);
172 }
173 
174 
175 bool
176 BGroupLayout::AddItem(int32 index, BLayoutItem* item, float weight)
177 {
178 	bool success = AddItem(index, item);
179 	if (success) {
180 		if (ItemLayoutData* data = _LayoutDataForItem(item))
181 			data->weight = weight;
182 	}
183 
184 	return success;
185 }
186 
187 
188 status_t
189 BGroupLayout::Archive(BMessage* into, bool deep) const
190 {
191 	BArchiver archiver(into);
192 	status_t err = BTwoDimensionalLayout::Archive(into, deep);
193 
194 	if (err == B_OK)
195 		err = into->AddBool(kVerticalField, fOrientation == B_VERTICAL);
196 
197 	return archiver.Finish(err);
198 }
199 
200 
201 status_t
202 BGroupLayout::AllArchived(BMessage* into) const
203 {
204 	return BTwoDimensionalLayout::AllArchived(into);
205 }
206 
207 
208 status_t
209 BGroupLayout::AllUnarchived(const BMessage* from)
210 {
211 	return BTwoDimensionalLayout::AllUnarchived(from);
212 }
213 
214 
215 BArchivable*
216 BGroupLayout::Instantiate(BMessage* from)
217 {
218 	if (validate_instantiation(from, "BGroupLayout"))
219 		return new(nothrow) BGroupLayout(from);
220 	return NULL;
221 }
222 
223 
224 status_t
225 BGroupLayout::ItemArchived(BMessage* into,
226 	BLayoutItem* item, int32 index) const
227 {
228 	return into->AddFloat(kItemWeightField, _LayoutDataForItem(item)->weight);
229 }
230 
231 
232 status_t
233 BGroupLayout::ItemUnarchived(const BMessage* from,
234 	BLayoutItem* item, int32 index)
235 {
236 	float weight;
237 	status_t err = from->FindFloat(kItemWeightField, index, &weight);
238 
239 	if (err == B_OK)
240 		_LayoutDataForItem(item)->weight = weight;
241 
242 	return err;
243 }
244 
245 
246 bool
247 BGroupLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
248 {
249 	item->SetLayoutData(new(nothrow) ItemLayoutData);
250 	return item->LayoutData() != NULL;
251 }
252 
253 
254 void
255 BGroupLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
256 {
257 	if (ItemLayoutData* data = _LayoutDataForItem(item)) {
258 		item->SetLayoutData(NULL);
259 		delete data;
260 	}
261 }
262 
263 
264 void
265 BGroupLayout::PrepareItems(enum orientation orientation)
266 {
267 	// filter the visible items
268 	fVisibleItems.MakeEmpty();
269 	int32 itemCount = CountItems();
270 	for (int i = 0; i < itemCount; i++) {
271 		BLayoutItem* item = ItemAt(i);
272 		if (item->IsVisible())
273 			fVisibleItems.AddItem(item);
274 	}
275 }
276 
277 
278 int32
279 BGroupLayout::InternalCountColumns()
280 {
281 	return (fOrientation == B_HORIZONTAL ? fVisibleItems.CountItems() : 1);
282 }
283 
284 
285 int32
286 BGroupLayout::InternalCountRows()
287 {
288 	return (fOrientation == B_VERTICAL ? fVisibleItems.CountItems() : 1);
289 }
290 
291 
292 void
293 BGroupLayout::GetColumnRowConstraints(enum orientation orientation, int32 index,
294 	ColumnRowConstraints* constraints)
295 {
296 	if (index >= 0 && index < fVisibleItems.CountItems()) {
297 		BLayoutItem* item = (BLayoutItem*)fVisibleItems.ItemAt(index);
298 		constraints->min = -1;
299 		constraints->max = B_SIZE_UNLIMITED;
300 		if (ItemLayoutData* data = _LayoutDataForItem(item))
301 			constraints->weight = data->weight;
302 		else
303 			constraints->weight = 1;
304 	}
305 }
306 
307 
308 void
309 BGroupLayout::GetItemDimensions(BLayoutItem* item, Dimensions* dimensions)
310 {
311 	int32 index = fVisibleItems.IndexOf(item);
312 	if (index < 0)
313 		return;
314 
315 	if (fOrientation == B_HORIZONTAL) {
316 		dimensions->x = index;
317 		dimensions->y = 0;
318 		dimensions->width = 1;
319 		dimensions->height = 1;
320 	} else {
321 		dimensions->x = 0;
322 		dimensions->y = index;
323 		dimensions->width = 1;
324 		dimensions->height = 1;
325 	}
326 }
327 
328 
329 BGroupLayout::ItemLayoutData*
330 BGroupLayout::_LayoutDataForItem(BLayoutItem* item) const
331 {
332 	if (!item)
333 		return NULL;
334 	return (ItemLayoutData*)item->LayoutData();
335 }
336 
337 
338 status_t
339 BGroupLayout::Perform(perform_code code, void* _data)
340 {
341 	return BTwoDimensionalLayout::Perform(code, _data);
342 }
343 
344 
345 void BGroupLayout::_ReservedGroupLayout1() {}
346 void BGroupLayout::_ReservedGroupLayout2() {}
347 void BGroupLayout::_ReservedGroupLayout3() {}
348 void BGroupLayout::_ReservedGroupLayout4() {}
349 void BGroupLayout::_ReservedGroupLayout5() {}
350 void BGroupLayout::_ReservedGroupLayout6() {}
351 void BGroupLayout::_ReservedGroupLayout7() {}
352 void BGroupLayout::_ReservedGroupLayout8() {}
353 void BGroupLayout::_ReservedGroupLayout9() {}
354 void BGroupLayout::_ReservedGroupLayout10() {}
355 
356