xref: /haiku/src/kits/interface/GroupLayout.cpp (revision 72156a402f54ea4be9dc3e3e9704c612f7d9ad16)
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::AllUnarchived(const BMessage* from)
203 {
204 	return BTwoDimensionalLayout::AllUnarchived(from);
205 }
206 
207 
208 BArchivable*
209 BGroupLayout::Instantiate(BMessage* from)
210 {
211 	if (validate_instantiation(from, "BGroupLayout"))
212 		return new(nothrow) BGroupLayout(from);
213 	return NULL;
214 }
215 
216 
217 status_t
218 BGroupLayout::ItemArchived(BMessage* into,
219 	BLayoutItem* item, int32 index) const
220 {
221 	return into->AddFloat(kItemWeightField, _LayoutDataForItem(item)->weight);
222 }
223 
224 
225 status_t
226 BGroupLayout::ItemUnarchived(const BMessage* from,
227 	BLayoutItem* item, int32 index)
228 {
229 	float weight;
230 	status_t err = from->FindFloat(kItemWeightField, index, &weight);
231 
232 	if (err == B_OK)
233 		_LayoutDataForItem(item)->weight = weight;
234 
235 	return err;
236 }
237 
238 
239 bool
240 BGroupLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
241 {
242 	item->SetLayoutData(new(nothrow) ItemLayoutData);
243 	return item->LayoutData() != NULL;
244 }
245 
246 
247 void
248 BGroupLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
249 {
250 	if (ItemLayoutData* data = _LayoutDataForItem(item)) {
251 		item->SetLayoutData(NULL);
252 		delete data;
253 	}
254 }
255 
256 
257 void
258 BGroupLayout::PrepareItems(enum orientation orientation)
259 {
260 	// filter the visible items
261 	fVisibleItems.MakeEmpty();
262 	int32 itemCount = CountItems();
263 	for (int i = 0; i < itemCount; i++) {
264 		BLayoutItem* item = ItemAt(i);
265 		if (item->IsVisible())
266 			fVisibleItems.AddItem(item);
267 	}
268 }
269 
270 
271 int32
272 BGroupLayout::InternalCountColumns()
273 {
274 	return (fOrientation == B_HORIZONTAL ? fVisibleItems.CountItems() : 1);
275 }
276 
277 
278 int32
279 BGroupLayout::InternalCountRows()
280 {
281 	return (fOrientation == B_VERTICAL ? fVisibleItems.CountItems() : 1);
282 }
283 
284 
285 void
286 BGroupLayout::GetColumnRowConstraints(enum orientation orientation, int32 index,
287 	ColumnRowConstraints* constraints)
288 {
289 	if (index >= 0 && index < fVisibleItems.CountItems()) {
290 		BLayoutItem* item = (BLayoutItem*)fVisibleItems.ItemAt(index);
291 		constraints->min = -1;
292 		constraints->max = B_SIZE_UNLIMITED;
293 		if (ItemLayoutData* data = _LayoutDataForItem(item))
294 			constraints->weight = data->weight;
295 		else
296 			constraints->weight = 1;
297 	}
298 }
299 
300 
301 void
302 BGroupLayout::GetItemDimensions(BLayoutItem* item, Dimensions* dimensions)
303 {
304 	int32 index = fVisibleItems.IndexOf(item);
305 	if (index < 0)
306 		return;
307 
308 	if (fOrientation == B_HORIZONTAL) {
309 		dimensions->x = index;
310 		dimensions->y = 0;
311 		dimensions->width = 1;
312 		dimensions->height = 1;
313 	} else {
314 		dimensions->x = 0;
315 		dimensions->y = index;
316 		dimensions->width = 1;
317 		dimensions->height = 1;
318 	}
319 }
320 
321 
322 BGroupLayout::ItemLayoutData*
323 BGroupLayout::_LayoutDataForItem(BLayoutItem* item) const
324 {
325 	if (!item)
326 		return NULL;
327 	return (ItemLayoutData*)item->LayoutData();
328 }
329