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