xref: /haiku/src/kits/interface/AbstractLayout.cpp (revision 85892ec52f476b254d75e2bb2e6560e72faa567c)
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 
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 
63 struct 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 
182 struct 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 
271 BAbstractLayout::BAbstractLayout()
272 	:
273 	fExplicitData(new BAbstractLayout::DataProxy())
274 {
275 }
276 
277 
278 BAbstractLayout::BAbstractLayout(BMessage* from)
279 	:
280 	BLayout(BUnarchiver::PrepareArchive(from)),
281 	fExplicitData(new DataProxy())
282 {
283 	BUnarchiver(from).Finish();
284 }
285 
286 
287 BAbstractLayout::~BAbstractLayout()
288 {
289 	delete fExplicitData;
290 }
291 
292 
293 BSize
294 BAbstractLayout::MinSize()
295 {
296 	return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize());
297 }
298 
299 
300 BSize
301 BAbstractLayout::MaxSize()
302 {
303 	return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize());
304 }
305 
306 
307 BSize
308 BAbstractLayout::PreferredSize()
309 {
310 	return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(),
311 		BasePreferredSize());
312 }
313 
314 
315 BAlignment
316 BAbstractLayout::Alignment()
317 {
318 	return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(),
319 		BaseAlignment());
320 }
321 
322 
323 void
324 BAbstractLayout::SetExplicitMinSize(BSize size)
325 {
326 	fExplicitData->SetMinSize(size);
327 }
328 
329 
330 void
331 BAbstractLayout::SetExplicitMaxSize(BSize size)
332 {
333 	fExplicitData->SetMaxSize(size);
334 }
335 
336 
337 void
338 BAbstractLayout::SetExplicitPreferredSize(BSize size)
339 {
340 	fExplicitData->SetPreferredSize(size);
341 }
342 
343 
344 void
345 BAbstractLayout::SetExplicitAlignment(BAlignment alignment)
346 {
347 	fExplicitData->SetAlignment(alignment);
348 }
349 
350 
351 BSize
352 BAbstractLayout::BaseMinSize()
353 {
354 	return BSize(0, 0);
355 }
356 
357 
358 BSize
359 BAbstractLayout::BaseMaxSize()
360 {
361 	return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
362 }
363 
364 
365 BSize
366 BAbstractLayout::BasePreferredSize()
367 {
368 	return BSize(0, 0);
369 }
370 
371 
372 BAlignment
373 BAbstractLayout::BaseAlignment()
374 {
375 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
376 }
377 
378 
379 BRect
380 BAbstractLayout::Frame()
381 {
382 	return fExplicitData->Frame();
383 }
384 
385 
386 void
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
398 BAbstractLayout::IsVisible()
399 {
400 	return fExplicitData->IsVisible(AncestorsVisible());
401 }
402 
403 
404 void
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
417 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
427 BAbstractLayout::AllArchived(BMessage* archive) const
428 {
429 	return BLayout::AllArchived(archive);
430 }
431 
432 
433 status_t
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
445 BAbstractLayout::ItemArchived(BMessage* into, BLayoutItem* item,
446 	int32 index) const
447 {
448 	return BLayout::ItemArchived(into, item, index);
449 }
450 
451 
452 status_t
453 BAbstractLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
454 	int32 index)
455 {
456 	return BLayout::ItemUnarchived(from, item, index);
457 }
458 
459 
460 bool
461 BAbstractLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
462 {
463 	return BLayout::ItemAdded(item, atIndex);
464 }
465 
466 
467 void
468 BAbstractLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
469 {
470 	BLayout::ItemRemoved(item, fromIndex);
471 }
472 
473 
474 void
475 BAbstractLayout::LayoutInvalidated(bool children)
476 {
477 	BLayout::LayoutInvalidated(children);
478 }
479 
480 
481 void
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
495 BAbstractLayout::AttachedToLayout()
496 {
497 	BLayout::AttachedToLayout();
498 }
499 
500 
501 void
502 BAbstractLayout::DetachedFromLayout(BLayout* layout)
503 {
504 	BLayout::DetachedFromLayout(layout);
505 }
506 
507 
508 void
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
528 BAbstractLayout::Perform(perform_code code, void* _data)
529 {
530 	return BLayout::Perform(code, _data);
531 }
532 
533 
534 void BAbstractLayout::_ReservedAbstractLayout1() {}
535 void BAbstractLayout::_ReservedAbstractLayout2() {}
536 void BAbstractLayout::_ReservedAbstractLayout3() {}
537 void BAbstractLayout::_ReservedAbstractLayout4() {}
538 void BAbstractLayout::_ReservedAbstractLayout5() {}
539 void BAbstractLayout::_ReservedAbstractLayout6() {}
540 void BAbstractLayout::_ReservedAbstractLayout7() {}
541 void BAbstractLayout::_ReservedAbstractLayout8() {}
542 void BAbstractLayout::_ReservedAbstractLayout9() {}
543 void BAbstractLayout::_ReservedAbstractLayout10() {}
544 
545