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
14namespace {
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
25struct BAbstractLayout::Proxy {
26
27	Proxy(proxy_type type)
28		:
29		type(type)
30	{
31	}
32
33	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
63struct BAbstractLayout::DataProxy : Proxy {
64
65	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
77	BSize MinSize() const
78	{
79		return minSize;
80	}
81
82	void SetMinSize(const BSize& min)
83	{
84		minSize = min;
85	}
86
87	BSize MaxSize() const
88	{
89		return maxSize;
90	}
91
92	void SetMaxSize(const BSize& max)
93	{
94		maxSize = max;
95	}
96
97	BSize PreferredSize() const
98	{
99		return preferredSize;
100	}
101
102	void SetPreferredSize(const BSize& preferred)
103	{
104		preferredSize = preferred;
105	}
106
107	BAlignment Alignment() const
108	{
109		return this->alignment;
110	}
111
112	void SetAlignment(const BAlignment& align)
113	{
114		this->alignment = align;
115	}
116
117	BRect Frame() const
118	{
119		return frame;
120	}
121
122	void SetFrame(const BRect& frame)
123	{
124		if (frame == this->frame)
125			return;
126		this->frame = frame;
127	}
128
129	bool IsVisible(bool) const
130	{
131		return visible;
132	}
133
134	void SetVisible(bool visible)
135	{
136		this->visible = visible;
137	}
138
139	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
156	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
182struct BAbstractLayout::ViewProxy : Proxy {
183	ViewProxy(BView* target)
184		:
185		Proxy(VIEW_PROXY_TYPE),
186		view(target)
187	{
188	}
189
190	BSize MinSize() const
191	{
192		return view->ExplicitMinSize();
193	}
194
195	void SetMinSize(const BSize& min)
196	{
197		view->SetExplicitMinSize(min);
198	}
199
200	BSize MaxSize() const
201	{
202		return view->ExplicitMaxSize();
203	}
204
205	void SetMaxSize(const BSize& min)
206	{
207		view->SetExplicitMaxSize(min);
208	}
209
210	BSize PreferredSize() const
211	{
212		return view->ExplicitPreferredSize();
213	}
214
215	void SetPreferredSize(const BSize& preferred)
216	{
217		view->SetExplicitPreferredSize(preferred);
218	}
219
220	BAlignment Alignment() const
221	{
222		return view->ExplicitAlignment();
223	}
224
225	void SetAlignment(const BAlignment& alignment)
226	{
227		view->SetExplicitAlignment(alignment);
228	}
229
230	BRect Frame() const
231	{
232		return view->Frame();
233	}
234
235	void SetFrame(const BRect& frame)
236	{
237		view->MoveTo(frame.LeftTop());
238		view->ResizeTo(frame.Width(), frame.Height());
239	}
240
241	bool IsVisible(bool ancestorsVisible) const
242	{
243		int16 showLevel = BView::Private(view).ShowLevel();
244		return (showLevel - (ancestorsVisible ? 0 : 1)) <= 0;
245	}
246
247	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
257	status_t AddDataToArchive(BMessage* archive, bool ancestorHidden)
258	{
259		return B_OK;
260	}
261
262	status_t RestoreDataFromArchive(const BMessage* archive)
263	{
264		return B_OK;
265	}
266
267	BView*	view;
268};
269
270
271BAbstractLayout::BAbstractLayout()
272	:
273	fExplicitData(new BAbstractLayout::DataProxy())
274{
275}
276
277
278BAbstractLayout::BAbstractLayout(BMessage* from)
279	:
280	BLayout(BUnarchiver::PrepareArchive(from)),
281	fExplicitData(new DataProxy())
282{
283	BUnarchiver(from).Finish();
284}
285
286
287BAbstractLayout::~BAbstractLayout()
288{
289	delete fExplicitData;
290}
291
292
293BSize
294BAbstractLayout::MinSize()
295{
296	return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize());
297}
298
299
300BSize
301BAbstractLayout::MaxSize()
302{
303	return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize());
304}
305
306
307BSize
308BAbstractLayout::PreferredSize()
309{
310	return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(),
311		BasePreferredSize());
312}
313
314
315BAlignment
316BAbstractLayout::Alignment()
317{
318	return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(),
319		BaseAlignment());
320}
321
322
323void
324BAbstractLayout::SetExplicitMinSize(BSize size)
325{
326	fExplicitData->SetMinSize(size);
327}
328
329
330void
331BAbstractLayout::SetExplicitMaxSize(BSize size)
332{
333	fExplicitData->SetMaxSize(size);
334}
335
336
337void
338BAbstractLayout::SetExplicitPreferredSize(BSize size)
339{
340	fExplicitData->SetPreferredSize(size);
341}
342
343
344void
345BAbstractLayout::SetExplicitAlignment(BAlignment alignment)
346{
347	fExplicitData->SetAlignment(alignment);
348}
349
350
351BSize
352BAbstractLayout::BaseMinSize()
353{
354	return BSize(0, 0);
355}
356
357
358BSize
359BAbstractLayout::BaseMaxSize()
360{
361	return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
362}
363
364
365BSize
366BAbstractLayout::BasePreferredSize()
367{
368	return BSize(0, 0);
369}
370
371
372BAlignment
373BAbstractLayout::BaseAlignment()
374{
375	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
376}
377
378
379BRect
380BAbstractLayout::Frame()
381{
382	return fExplicitData->Frame();
383}
384
385
386void
387BAbstractLayout::SetFrame(BRect frame)
388{
389	if (frame != fExplicitData->Frame()) {
390		fExplicitData->SetFrame(frame);
391		if (!Owner())
392			Relayout();
393	}
394}
395
396
397bool
398BAbstractLayout::IsVisible()
399{
400	return fExplicitData->IsVisible(AncestorsVisible());
401}
402
403
404void
405BAbstractLayout::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
416status_t
417BAbstractLayout::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
426status_t
427BAbstractLayout::AllArchived(BMessage* archive) const
428{
429	return BLayout::AllArchived(archive);
430}
431
432
433status_t
434BAbstractLayout::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
444status_t
445BAbstractLayout::ItemArchived(BMessage* into, BLayoutItem* item,
446	int32 index) const
447{
448	return BLayout::ItemArchived(into, item, index);
449}
450
451
452status_t
453BAbstractLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
454	int32 index)
455{
456	return BLayout::ItemUnarchived(from, item, index);
457}
458
459
460bool
461BAbstractLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
462{
463	return BLayout::ItemAdded(item, atIndex);
464}
465
466
467void
468BAbstractLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
469{
470	BLayout::ItemRemoved(item, fromIndex);
471}
472
473
474void
475BAbstractLayout::LayoutInvalidated(bool children)
476{
477	BLayout::LayoutInvalidated(children);
478}
479
480
481void
482BAbstractLayout::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
494void
495BAbstractLayout::AttachedToLayout()
496{
497	BLayout::AttachedToLayout();
498}
499
500
501void
502BAbstractLayout::DetachedFromLayout(BLayout* layout)
503{
504	BLayout::DetachedFromLayout(layout);
505}
506
507
508void
509BAbstractLayout::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
527status_t
528BAbstractLayout::Perform(perform_code code, void* _data)
529{
530	return BLayout::Perform(code, _data);
531}
532
533
534void BAbstractLayout::_ReservedAbstractLayout1() {}
535void BAbstractLayout::_ReservedAbstractLayout2() {}
536void BAbstractLayout::_ReservedAbstractLayout3() {}
537void BAbstractLayout::_ReservedAbstractLayout4() {}
538void BAbstractLayout::_ReservedAbstractLayout5() {}
539void BAbstractLayout::_ReservedAbstractLayout6() {}
540void BAbstractLayout::_ReservedAbstractLayout7() {}
541void BAbstractLayout::_ReservedAbstractLayout8() {}
542void BAbstractLayout::_ReservedAbstractLayout9() {}
543void BAbstractLayout::_ReservedAbstractLayout10() {}
544
545