xref: /haiku/src/kits/interface/AbstractLayout.cpp (revision e3becd53eef5c093ee8c8f32bab51d40b0f2b8d4)
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