1/*
2 * Copyright 2010-2012, 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 <LayoutItem.h>
9
10#include <Layout.h>
11#include <LayoutUtils.h>
12#include <View.h>
13#include <ViewPrivate.h>
14
15#include <algorithm>
16
17
18BLayoutItem::BLayoutItem()
19	:
20	fLayout(NULL),
21	fLayoutData(NULL)
22{
23}
24
25
26BLayoutItem::BLayoutItem(BMessage* from)
27	:
28	BArchivable(BUnarchiver::PrepareArchive(from)),
29	fLayout(NULL),
30	fLayoutData(NULL)
31{
32	BUnarchiver(from).Finish();
33}
34
35
36BLayoutItem::~BLayoutItem()
37{
38	if (fLayout != NULL) {
39		debugger("Deleting a BLayoutItem that is still attached to a layout. "
40			"Call RemoveSelf first.");
41	}
42}
43
44
45BLayout*
46BLayoutItem::Layout() const
47{
48	return fLayout;
49}
50
51
52bool
53BLayoutItem::RemoveSelf()
54{
55	return Layout() != NULL && Layout()->RemoveItem(this);
56}
57
58
59void
60BLayoutItem::SetExplicitSize(BSize size)
61{
62	SetExplicitMinSize(size);
63	SetExplicitMaxSize(size);
64	SetExplicitPreferredSize(size);
65}
66
67
68bool
69BLayoutItem::HasHeightForWidth()
70{
71	// no "height for width" by default
72	return false;
73}
74
75
76void
77BLayoutItem::GetHeightForWidth(float width, float* min, float* max,
78	float* preferred)
79{
80	// no "height for width" by default
81}
82
83
84BView*
85BLayoutItem::View()
86{
87	return NULL;
88}
89
90
91void
92BLayoutItem::InvalidateLayout(bool children)
93{
94	LayoutInvalidated(children);
95	if (fLayout)
96		fLayout->InvalidateLayout(children);
97}
98
99
100void
101BLayoutItem::Relayout(bool immediate)
102{
103	BView* view = View();
104	if (view && !immediate)
105		view->Relayout();
106	else if (view && immediate)
107		view->Layout(false);
108}
109
110
111void*
112BLayoutItem::LayoutData() const
113{
114	return fLayoutData;
115}
116
117
118void
119BLayoutItem::SetLayoutData(void* data)
120{
121	fLayoutData = data;
122}
123
124
125void
126BLayoutItem::AlignInFrame(BRect frame)
127{
128	BSize maxSize = MaxSize();
129	BAlignment alignment = Alignment();
130
131	if (HasHeightForWidth()) {
132		// The item has height for width, so we do the horizontal alignment
133		// ourselves and restrict the height max constraint respectively.
134		if (maxSize.width < frame.Width()
135			&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
136			frame.left += (int)((frame.Width() - maxSize.width)
137				* alignment.horizontal);
138			frame.right = frame.left + maxSize.width;
139		}
140		alignment.horizontal = B_ALIGN_USE_FULL_WIDTH;
141
142		float minHeight;
143		GetHeightForWidth(frame.Width(), &minHeight, NULL, NULL);
144
145		frame.bottom = frame.top + max_c(frame.Height(), minHeight);
146		maxSize.height = minHeight;
147	}
148
149	SetFrame(BLayoutUtils::AlignInFrame(frame, maxSize, alignment));
150}
151
152
153status_t
154BLayoutItem::Archive(BMessage* into, bool deep) const
155{
156	BArchiver archiver(into);
157	status_t err = BArchivable::Archive(into, deep);
158
159	if (err == B_OK)
160		err = archiver.Finish();
161
162	return err;
163}
164
165
166status_t
167BLayoutItem::AllArchived(BMessage* into) const
168{
169	BArchiver archiver(into);
170	return BArchivable::AllArchived(into);
171}
172
173
174status_t
175BLayoutItem::AllUnarchived(const BMessage* from)
176{
177	return BArchivable::AllUnarchived(from);
178}
179
180
181void
182BLayoutItem::SetLayout(BLayout* layout)
183{
184	if (layout == fLayout)
185		return;
186
187	BLayout* oldLayout = fLayout;
188	fLayout = layout;
189
190	if (oldLayout)
191		DetachedFromLayout(oldLayout);
192
193	if (BView* view = View()) {
194		if (oldLayout && !fLayout) {
195			BView::Private(view).DeregisterLayoutItem(this);
196		} else if (fLayout && !oldLayout) {
197			BView::Private(view).RegisterLayoutItem(this);
198		}
199	}
200
201	if (fLayout)
202		AttachedToLayout();
203}
204
205
206status_t
207BLayoutItem::Perform(perform_code code, void* _data)
208{
209	return BArchivable::Perform(code, _data);
210}
211
212
213void
214BLayoutItem::LayoutInvalidated(bool children)
215{
216	// hook method
217}
218
219
220void
221BLayoutItem::AttachedToLayout()
222{
223	// hook method
224}
225
226
227void
228BLayoutItem::DetachedFromLayout(BLayout* oldLayout)
229{
230	// hook method
231}
232
233
234void
235BLayoutItem::AncestorVisibilityChanged(bool shown)
236{
237	// hook method
238}
239
240
241// Binary compatibility stuff
242
243
244void BLayoutItem::_ReservedLayoutItem1() {}
245void BLayoutItem::_ReservedLayoutItem2() {}
246void BLayoutItem::_ReservedLayoutItem3() {}
247void BLayoutItem::_ReservedLayoutItem4() {}
248void BLayoutItem::_ReservedLayoutItem5() {}
249void BLayoutItem::_ReservedLayoutItem6() {}
250void BLayoutItem::_ReservedLayoutItem7() {}
251void BLayoutItem::_ReservedLayoutItem8() {}
252void BLayoutItem::_ReservedLayoutItem9() {}
253void BLayoutItem::_ReservedLayoutItem10() {}
254
255