1 /*
2 * Copyright 2010, Haiku, Inc.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6
7 #include <AbstractLayout.h>
8 #include <LayoutUtils.h>
9 #include <Message.h>
10 #include <View.h>
11 #include <ViewPrivate.h>
12
13
14 namespace {
15 const char* const kSizesField = "BAbstractLayout:sizes";
16 // kSizesField == {min, max, preferred}
17 const char* const kAlignmentField = "BAbstractLayout:alignment";
18 const char* const kFrameField = "BAbstractLayout:frame";
19 const char* const kVisibleField = "BAbstractLayout:visible";
20
21 enum proxy_type { VIEW_PROXY_TYPE, DATA_PROXY_TYPE };
22 }
23
24
25 struct BAbstractLayout::Proxy {
26
ProxyBAbstractLayout::Proxy27 Proxy(proxy_type type)
28 :
29 type(type)
30 {
31 }
32
~ProxyBAbstractLayout::Proxy33 virtual ~Proxy()
34 {
35 }
36
37 virtual BSize MinSize() const = 0;
38 virtual void SetMinSize(const BSize&) = 0;
39
40 virtual BSize MaxSize() const = 0;
41 virtual void SetMaxSize(const BSize&) = 0;
42
43 virtual BSize PreferredSize() const = 0;
44 virtual void SetPreferredSize(const BSize&) = 0;
45
46 virtual BAlignment Alignment() const = 0;
47 virtual void SetAlignment(const BAlignment&) = 0;
48
49 virtual BRect Frame() const = 0;
50 virtual void SetFrame(const BRect& frame) = 0;
51
52 virtual bool IsVisible(bool ancestorHidden) const = 0;
53 virtual void SetVisible(bool visible) = 0;
54
55 virtual status_t AddDataToArchive(BMessage* archive,
56 bool ancestorHidden) = 0;
57 virtual status_t RestoreDataFromArchive(const BMessage* archive) = 0;
58
59 proxy_type type;
60 };
61
62
63 struct BAbstractLayout::DataProxy : Proxy {
64
DataProxyBAbstractLayout::DataProxy65 DataProxy()
66 :
67 Proxy(DATA_PROXY_TYPE),
68 minSize(),
69 maxSize(),
70 preferredSize(),
71 alignment(),
72 frame(-1, -1, 0, 0),
73 visible(true)
74 {
75 }
76
MinSizeBAbstractLayout::DataProxy77 BSize MinSize() const
78 {
79 return minSize;
80 }
81
SetMinSizeBAbstractLayout::DataProxy82 void SetMinSize(const BSize& min)
83 {
84 minSize = min;
85 }
86
MaxSizeBAbstractLayout::DataProxy87 BSize MaxSize() const
88 {
89 return maxSize;
90 }
91
SetMaxSizeBAbstractLayout::DataProxy92 void SetMaxSize(const BSize& max)
93 {
94 maxSize = max;
95 }
96
PreferredSizeBAbstractLayout::DataProxy97 BSize PreferredSize() const
98 {
99 return preferredSize;
100 }
101
SetPreferredSizeBAbstractLayout::DataProxy102 void SetPreferredSize(const BSize& preferred)
103 {
104 preferredSize = preferred;
105 }
106
AlignmentBAbstractLayout::DataProxy107 BAlignment Alignment() const
108 {
109 return this->alignment;
110 }
111
SetAlignmentBAbstractLayout::DataProxy112 void SetAlignment(const BAlignment& align)
113 {
114 this->alignment = align;
115 }
116
FrameBAbstractLayout::DataProxy117 BRect Frame() const
118 {
119 return frame;
120 }
121
SetFrameBAbstractLayout::DataProxy122 void SetFrame(const BRect& frame)
123 {
124 if (frame == this->frame)
125 return;
126 this->frame = frame;
127 }
128
IsVisibleBAbstractLayout::DataProxy129 bool IsVisible(bool) const
130 {
131 return visible;
132 }
133
SetVisibleBAbstractLayout::DataProxy134 void SetVisible(bool visible)
135 {
136 this->visible = visible;
137 }
138
AddDataToArchiveBAbstractLayout::DataProxy139 status_t AddDataToArchive(BMessage* archive, bool ancestorHidden)
140 {
141 status_t err = archive->AddSize(kSizesField, minSize);
142 if (err == B_OK)
143 err = archive->AddSize(kSizesField, maxSize);
144 if (err == B_OK)
145 err = archive->AddSize(kSizesField, preferredSize);
146 if (err == B_OK)
147 err = archive->AddAlignment(kAlignmentField, alignment);
148 if (err == B_OK)
149 err = archive->AddRect(kFrameField, frame);
150 if (err == B_OK)
151 err = archive->AddBool(kVisibleField, visible);
152
153 return err;
154 }
155
RestoreDataFromArchiveBAbstractLayout::DataProxy156 status_t RestoreDataFromArchive(const BMessage* archive)
157 {
158 status_t err = archive->FindSize(kSizesField, 0, &minSize);
159 if (err == B_OK)
160 err = archive->FindSize(kSizesField, 1, &maxSize);
161 if (err == B_OK)
162 err = archive->FindSize(kSizesField, 2, &preferredSize);
163 if (err == B_OK)
164 err = archive->FindAlignment(kAlignmentField, &alignment);
165 if (err == B_OK)
166 err = archive->FindRect(kFrameField, &frame);
167 if (err == B_OK)
168 err = archive->FindBool(kVisibleField, &visible);
169
170 return err;
171 }
172
173 BSize minSize;
174 BSize maxSize;
175 BSize preferredSize;
176 BAlignment alignment;
177 BRect frame;
178 bool visible;
179 };
180
181
182 struct BAbstractLayout::ViewProxy : Proxy {
ViewProxyBAbstractLayout::ViewProxy183 ViewProxy(BView* target)
184 :
185 Proxy(VIEW_PROXY_TYPE),
186 view(target)
187 {
188 }
189
MinSizeBAbstractLayout::ViewProxy190 BSize MinSize() const
191 {
192 return view->ExplicitMinSize();
193 }
194
SetMinSizeBAbstractLayout::ViewProxy195 void SetMinSize(const BSize& min)
196 {
197 view->SetExplicitMinSize(min);
198 }
199
MaxSizeBAbstractLayout::ViewProxy200 BSize MaxSize() const
201 {
202 return view->ExplicitMaxSize();
203 }
204
SetMaxSizeBAbstractLayout::ViewProxy205 void SetMaxSize(const BSize& min)
206 {
207 view->SetExplicitMaxSize(min);
208 }
209
PreferredSizeBAbstractLayout::ViewProxy210 BSize PreferredSize() const
211 {
212 return view->ExplicitPreferredSize();
213 }
214
SetPreferredSizeBAbstractLayout::ViewProxy215 void SetPreferredSize(const BSize& preferred)
216 {
217 view->SetExplicitPreferredSize(preferred);
218 }
219
AlignmentBAbstractLayout::ViewProxy220 BAlignment Alignment() const
221 {
222 return view->ExplicitAlignment();
223 }
224
SetAlignmentBAbstractLayout::ViewProxy225 void SetAlignment(const BAlignment& alignment)
226 {
227 view->SetExplicitAlignment(alignment);
228 }
229
FrameBAbstractLayout::ViewProxy230 BRect Frame() const
231 {
232 return view->Frame();
233 }
234
SetFrameBAbstractLayout::ViewProxy235 void SetFrame(const BRect& frame)
236 {
237 view->MoveTo(frame.LeftTop());
238 view->ResizeTo(frame.Width(), frame.Height());
239 }
240
IsVisibleBAbstractLayout::ViewProxy241 bool IsVisible(bool ancestorsVisible) const
242 {
243 int16 showLevel = BView::Private(view).ShowLevel();
244 return (showLevel - (ancestorsVisible ? 0 : 1)) <= 0;
245 }
246
SetVisibleBAbstractLayout::ViewProxy247 void SetVisible(bool visible)
248 {
249 // No need to check that we are not re-hiding, that is done
250 // for us.
251 if (visible)
252 view->Show();
253 else
254 view->Hide();
255 }
256
AddDataToArchiveBAbstractLayout::ViewProxy257 status_t AddDataToArchive(BMessage* archive, bool ancestorHidden)
258 {
259 return B_OK;
260 }
261
RestoreDataFromArchiveBAbstractLayout::ViewProxy262 status_t RestoreDataFromArchive(const BMessage* archive)
263 {
264 return B_OK;
265 }
266
267 BView* view;
268 };
269
270
BAbstractLayout()271 BAbstractLayout::BAbstractLayout()
272 :
273 fExplicitData(new BAbstractLayout::DataProxy())
274 {
275 }
276
277
BAbstractLayout(BMessage * from)278 BAbstractLayout::BAbstractLayout(BMessage* from)
279 :
280 BLayout(BUnarchiver::PrepareArchive(from)),
281 fExplicitData(new DataProxy())
282 {
283 BUnarchiver(from).Finish();
284 }
285
286
~BAbstractLayout()287 BAbstractLayout::~BAbstractLayout()
288 {
289 delete fExplicitData;
290 }
291
292
293 BSize
MinSize()294 BAbstractLayout::MinSize()
295 {
296 return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize());
297 }
298
299
300 BSize
MaxSize()301 BAbstractLayout::MaxSize()
302 {
303 return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize());
304 }
305
306
307 BSize
PreferredSize()308 BAbstractLayout::PreferredSize()
309 {
310 return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(),
311 BasePreferredSize());
312 }
313
314
315 BAlignment
Alignment()316 BAbstractLayout::Alignment()
317 {
318 return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(),
319 BaseAlignment());
320 }
321
322
323 void
SetExplicitMinSize(BSize size)324 BAbstractLayout::SetExplicitMinSize(BSize size)
325 {
326 fExplicitData->SetMinSize(size);
327 }
328
329
330 void
SetExplicitMaxSize(BSize size)331 BAbstractLayout::SetExplicitMaxSize(BSize size)
332 {
333 fExplicitData->SetMaxSize(size);
334 }
335
336
337 void
SetExplicitPreferredSize(BSize size)338 BAbstractLayout::SetExplicitPreferredSize(BSize size)
339 {
340 fExplicitData->SetPreferredSize(size);
341 }
342
343
344 void
SetExplicitAlignment(BAlignment alignment)345 BAbstractLayout::SetExplicitAlignment(BAlignment alignment)
346 {
347 fExplicitData->SetAlignment(alignment);
348 }
349
350
351 BSize
BaseMinSize()352 BAbstractLayout::BaseMinSize()
353 {
354 return BSize(0, 0);
355 }
356
357
358 BSize
BaseMaxSize()359 BAbstractLayout::BaseMaxSize()
360 {
361 return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
362 }
363
364
365 BSize
BasePreferredSize()366 BAbstractLayout::BasePreferredSize()
367 {
368 return BSize(0, 0);
369 }
370
371
372 BAlignment
BaseAlignment()373 BAbstractLayout::BaseAlignment()
374 {
375 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
376 }
377
378
379 BRect
Frame()380 BAbstractLayout::Frame()
381 {
382 return fExplicitData->Frame();
383 }
384
385
386 void
SetFrame(BRect frame)387 BAbstractLayout::SetFrame(BRect frame)
388 {
389 if (frame != fExplicitData->Frame()) {
390 fExplicitData->SetFrame(frame);
391 if (!Owner())
392 Relayout();
393 }
394 }
395
396
397 bool
IsVisible()398 BAbstractLayout::IsVisible()
399 {
400 return fExplicitData->IsVisible(AncestorsVisible());
401 }
402
403
404 void
SetVisible(bool visible)405 BAbstractLayout::SetVisible(bool visible)
406 {
407 if (visible != fExplicitData->IsVisible(AncestorsVisible())) {
408 fExplicitData->SetVisible(visible);
409 if (Layout())
410 Layout()->InvalidateLayout(false);
411 VisibilityChanged(visible);
412 }
413 }
414
415
416 status_t
Archive(BMessage * into,bool deep) const417 BAbstractLayout::Archive(BMessage* into, bool deep) const
418 {
419 BArchiver archiver(into);
420 status_t err = BLayout::Archive(into, deep);
421
422 return archiver.Finish(err);
423 }
424
425
426 status_t
AllArchived(BMessage * archive) const427 BAbstractLayout::AllArchived(BMessage* archive) const
428 {
429 return BLayout::AllArchived(archive);
430 }
431
432
433 status_t
AllUnarchived(const BMessage * from)434 BAbstractLayout::AllUnarchived(const BMessage* from)
435 {
436 status_t err = fExplicitData->RestoreDataFromArchive(from);
437 if (err != B_OK)
438 return err;
439
440 return BLayout::AllUnarchived(from);
441 }
442
443
444 status_t
ItemArchived(BMessage * into,BLayoutItem * item,int32 index) const445 BAbstractLayout::ItemArchived(BMessage* into, BLayoutItem* item,
446 int32 index) const
447 {
448 return BLayout::ItemArchived(into, item, index);
449 }
450
451
452 status_t
ItemUnarchived(const BMessage * from,BLayoutItem * item,int32 index)453 BAbstractLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
454 int32 index)
455 {
456 return BLayout::ItemUnarchived(from, item, index);
457 }
458
459
460 bool
ItemAdded(BLayoutItem * item,int32 atIndex)461 BAbstractLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
462 {
463 return BLayout::ItemAdded(item, atIndex);
464 }
465
466
467 void
ItemRemoved(BLayoutItem * item,int32 fromIndex)468 BAbstractLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
469 {
470 BLayout::ItemRemoved(item, fromIndex);
471 }
472
473
474 void
LayoutInvalidated(bool children)475 BAbstractLayout::LayoutInvalidated(bool children)
476 {
477 BLayout::LayoutInvalidated(children);
478 }
479
480
481 void
OwnerChanged(BView * was)482 BAbstractLayout::OwnerChanged(BView* was)
483 {
484 if (was) {
485 static_cast<ViewProxy*>(fExplicitData)->view = Owner();
486 return;
487 }
488
489 delete fExplicitData;
490 fExplicitData = new ViewProxy(Owner());
491 }
492
493
494 void
AttachedToLayout()495 BAbstractLayout::AttachedToLayout()
496 {
497 BLayout::AttachedToLayout();
498 }
499
500
501 void
DetachedFromLayout(BLayout * layout)502 BAbstractLayout::DetachedFromLayout(BLayout* layout)
503 {
504 BLayout::DetachedFromLayout(layout);
505 }
506
507
508 void
AncestorVisibilityChanged(bool shown)509 BAbstractLayout::AncestorVisibilityChanged(bool shown)
510 {
511 if (AncestorsVisible() == shown)
512 return;
513
514 if (BView* owner = Owner()) {
515 if (shown)
516 owner->Show();
517 else
518 owner->Hide();
519 }
520 BLayout::AncestorVisibilityChanged(shown);
521 }
522
523
524 // Binary compatibility stuff
525
526
527 status_t
Perform(perform_code code,void * _data)528 BAbstractLayout::Perform(perform_code code, void* _data)
529 {
530 return BLayout::Perform(code, _data);
531 }
532
533
_ReservedAbstractLayout1()534 void BAbstractLayout::_ReservedAbstractLayout1() {}
_ReservedAbstractLayout2()535 void BAbstractLayout::_ReservedAbstractLayout2() {}
_ReservedAbstractLayout3()536 void BAbstractLayout::_ReservedAbstractLayout3() {}
_ReservedAbstractLayout4()537 void BAbstractLayout::_ReservedAbstractLayout4() {}
_ReservedAbstractLayout5()538 void BAbstractLayout::_ReservedAbstractLayout5() {}
_ReservedAbstractLayout6()539 void BAbstractLayout::_ReservedAbstractLayout6() {}
_ReservedAbstractLayout7()540 void BAbstractLayout::_ReservedAbstractLayout7() {}
_ReservedAbstractLayout8()541 void BAbstractLayout::_ReservedAbstractLayout8() {}
_ReservedAbstractLayout9()542 void BAbstractLayout::_ReservedAbstractLayout9() {}
_ReservedAbstractLayout10()543 void BAbstractLayout::_ReservedAbstractLayout10() {}
544
545