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
ItemLayoutDataBGroupLayout::ItemLayoutData30 ItemLayoutData()
31 : weight(1)
32 {
33 }
34 };
35
36
BGroupLayout(orientation orientation,float spacing)37 BGroupLayout::BGroupLayout(orientation orientation, float spacing)
38 :
39 BTwoDimensionalLayout(),
40 fOrientation(orientation)
41 {
42 SetSpacing(spacing);
43 }
44
45
BGroupLayout(BMessage * from)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
~BGroupLayout()57 BGroupLayout::~BGroupLayout()
58 {
59 }
60
61
62 float
Spacing() const63 BGroupLayout::Spacing() const
64 {
65 return fHSpacing;
66 }
67
68
69 void
SetSpacing(float spacing)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
Orientation() const82 BGroupLayout::Orientation() const
83 {
84 return fOrientation;
85 }
86
87
88 void
SetOrientation(orientation orientation)89 BGroupLayout::SetOrientation(orientation orientation)
90 {
91 if (orientation != fOrientation) {
92 fOrientation = orientation;
93
94 InvalidateLayout();
95 }
96 }
97
98
99 float
ItemWeight(int32 index) const100 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
SetItemWeight(int32 index,float weight)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*
AddView(BView * child)124 BGroupLayout::AddView(BView* child)
125 {
126 return BTwoDimensionalLayout::AddView(child);
127 }
128
129
130 BLayoutItem*
AddView(int32 index,BView * child)131 BGroupLayout::AddView(int32 index, BView* child)
132 {
133 return BTwoDimensionalLayout::AddView(index, child);
134 }
135
136
137 BLayoutItem*
AddView(BView * child,float weight)138 BGroupLayout::AddView(BView* child, float weight)
139 {
140 return AddView(-1, child, weight);
141 }
142
143
144 BLayoutItem*
AddView(int32 index,BView * child,float weight)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
AddItem(BLayoutItem * item)156 BGroupLayout::AddItem(BLayoutItem* item)
157 {
158 return BTwoDimensionalLayout::AddItem(item);
159 }
160
161
162 bool
AddItem(int32 index,BLayoutItem * item)163 BGroupLayout::AddItem(int32 index, BLayoutItem* item)
164 {
165 return BTwoDimensionalLayout::AddItem(index, item);
166 }
167
168
169 bool
AddItem(BLayoutItem * item,float weight)170 BGroupLayout::AddItem(BLayoutItem* item, float weight)
171 {
172 return AddItem(-1, item, weight);
173 }
174
175
176 bool
AddItem(int32 index,BLayoutItem * item,float weight)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
Archive(BMessage * into,bool deep) const190 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
AllArchived(BMessage * into) const203 BGroupLayout::AllArchived(BMessage* into) const
204 {
205 return BTwoDimensionalLayout::AllArchived(into);
206 }
207
208
209 status_t
AllUnarchived(const BMessage * from)210 BGroupLayout::AllUnarchived(const BMessage* from)
211 {
212 return BTwoDimensionalLayout::AllUnarchived(from);
213 }
214
215
216 BArchivable*
Instantiate(BMessage * from)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
ItemArchived(BMessage * into,BLayoutItem * item,int32 index) const226 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
ItemUnarchived(const BMessage * from,BLayoutItem * item,int32 index)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
ItemAdded(BLayoutItem * item,int32 atIndex)248 BGroupLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
249 {
250 item->SetLayoutData(new(nothrow) ItemLayoutData);
251 return item->LayoutData() != NULL;
252 }
253
254
255 void
ItemRemoved(BLayoutItem * item,int32 fromIndex)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
PrepareItems(orientation orientation)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
InternalCountColumns()280 BGroupLayout::InternalCountColumns()
281 {
282 return (fOrientation == B_HORIZONTAL ? fVisibleItems.CountItems() : 1);
283 }
284
285
286 int32
InternalCountRows()287 BGroupLayout::InternalCountRows()
288 {
289 return (fOrientation == B_VERTICAL ? fVisibleItems.CountItems() : 1);
290 }
291
292
293 void
GetColumnRowConstraints(orientation orientation,int32 index,ColumnRowConstraints * constraints)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
GetItemDimensions(BLayoutItem * item,Dimensions * dimensions)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*
_LayoutDataForItem(BLayoutItem * item) const331 BGroupLayout::_LayoutDataForItem(BLayoutItem* item) const
332 {
333 return item == NULL ? NULL : (ItemLayoutData*)item->LayoutData();
334 }
335
336
337 status_t
Perform(perform_code code,void * _data)338 BGroupLayout::Perform(perform_code code, void* _data)
339 {
340 return BTwoDimensionalLayout::Perform(code, _data);
341 }
342
343
_ReservedGroupLayout1()344 void BGroupLayout::_ReservedGroupLayout1() {}
_ReservedGroupLayout2()345 void BGroupLayout::_ReservedGroupLayout2() {}
_ReservedGroupLayout3()346 void BGroupLayout::_ReservedGroupLayout3() {}
_ReservedGroupLayout4()347 void BGroupLayout::_ReservedGroupLayout4() {}
_ReservedGroupLayout5()348 void BGroupLayout::_ReservedGroupLayout5() {}
_ReservedGroupLayout6()349 void BGroupLayout::_ReservedGroupLayout6() {}
_ReservedGroupLayout7()350 void BGroupLayout::_ReservedGroupLayout7() {}
_ReservedGroupLayout8()351 void BGroupLayout::_ReservedGroupLayout8() {}
_ReservedGroupLayout9()352 void BGroupLayout::_ReservedGroupLayout9() {}
_ReservedGroupLayout10()353 void BGroupLayout::_ReservedGroupLayout10() {}
354