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