19ecf9d1cSIngo Weinhold/*
2a0747aadSIngo Weinhold * Copyright 2006-2009, Ingo Weinhold <ingo_weinhold@gmx.de>.
39ecf9d1cSIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License.
49ecf9d1cSIngo Weinhold */
59ecf9d1cSIngo Weinhold
69ecf9d1cSIngo Weinhold#include <CardLayout.h>
79ecf9d1cSIngo Weinhold
89ecf9d1cSIngo Weinhold#include <LayoutItem.h>
981405788SIngo Weinhold#include <Message.h>
109ecf9d1cSIngo Weinhold#include <View.h>
119ecf9d1cSIngo Weinhold
1281405788SIngo Weinhold
1381405788SIngo Weinholdnamespace {
1481405788SIngo Weinhold	const char* kVisibleItemField = "BCardLayout:visibleItem";
1581405788SIngo Weinhold}
1681405788SIngo Weinhold
1781405788SIngo Weinhold
189ecf9d1cSIngo WeinholdBCardLayout::BCardLayout()
1981405788SIngo Weinhold	:
201d6c7b6cSAlex Wilson	BAbstractLayout(),
2181405788SIngo Weinhold	fMin(0, 0),
2281405788SIngo Weinhold	fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
2381405788SIngo Weinhold	fPreferred(0, 0),
2481405788SIngo Weinhold	fVisibleItem(NULL),
2581405788SIngo Weinhold	fMinMaxValid(false)
2681405788SIngo Weinhold{
2781405788SIngo Weinhold}
2881405788SIngo Weinhold
2981405788SIngo Weinhold
3081405788SIngo WeinholdBCardLayout::BCardLayout(BMessage* from)
3181405788SIngo Weinhold	:
321d6c7b6cSAlex Wilson	BAbstractLayout(BUnarchiver::PrepareArchive(from)),
3381405788SIngo Weinhold	fMin(0, 0),
3481405788SIngo Weinhold	fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
3581405788SIngo Weinhold	fPreferred(0, 0),
3681405788SIngo Weinhold	fVisibleItem(NULL),
3781405788SIngo Weinhold	fMinMaxValid(false)
389ecf9d1cSIngo Weinhold{
3981405788SIngo Weinhold	BUnarchiver(from).Finish();
409ecf9d1cSIngo Weinhold}
419ecf9d1cSIngo Weinhold
4281405788SIngo Weinhold
439ecf9d1cSIngo WeinholdBCardLayout::~BCardLayout()
449ecf9d1cSIngo Weinhold{
459ecf9d1cSIngo Weinhold}
469ecf9d1cSIngo Weinhold
4781405788SIngo Weinhold
489ecf9d1cSIngo WeinholdBLayoutItem*
499ecf9d1cSIngo WeinholdBCardLayout::VisibleItem() const
509ecf9d1cSIngo Weinhold{
519ecf9d1cSIngo Weinhold	return fVisibleItem;
529ecf9d1cSIngo Weinhold}
539ecf9d1cSIngo Weinhold
5481405788SIngo Weinhold
559ecf9d1cSIngo Weinholdint32
569ecf9d1cSIngo WeinholdBCardLayout::VisibleIndex() const
579ecf9d1cSIngo Weinhold{
589ecf9d1cSIngo Weinhold	return IndexOfItem(fVisibleItem);
599ecf9d1cSIngo Weinhold}
609ecf9d1cSIngo Weinhold
6181405788SIngo Weinhold
629ecf9d1cSIngo Weinholdvoid
639ecf9d1cSIngo WeinholdBCardLayout::SetVisibleItem(int32 index)
649ecf9d1cSIngo Weinhold{
659ecf9d1cSIngo Weinhold	SetVisibleItem(ItemAt(index));
669ecf9d1cSIngo Weinhold}
679ecf9d1cSIngo Weinhold
6881405788SIngo Weinhold
699ecf9d1cSIngo Weinholdvoid
709ecf9d1cSIngo WeinholdBCardLayout::SetVisibleItem(BLayoutItem* item)
719ecf9d1cSIngo Weinhold{
729ecf9d1cSIngo Weinhold	if (item == fVisibleItem)
739ecf9d1cSIngo Weinhold		return;
749ecf9d1cSIngo Weinhold
759ecf9d1cSIngo Weinhold	if (item != NULL && IndexOfItem(item) < 0)
769ecf9d1cSIngo Weinhold		return;
77a0747aadSIngo Weinhold
789ecf9d1cSIngo Weinhold	if (fVisibleItem != NULL)
799ecf9d1cSIngo Weinhold		fVisibleItem->SetVisible(false);
809ecf9d1cSIngo Weinhold
819ecf9d1cSIngo Weinhold	fVisibleItem = item;
829ecf9d1cSIngo Weinhold
839ecf9d1cSIngo Weinhold	if (fVisibleItem != NULL) {
849ecf9d1cSIngo Weinhold		fVisibleItem->SetVisible(true);
859ecf9d1cSIngo Weinhold
861d6c7b6cSAlex Wilson		Relayout();
879ecf9d1cSIngo Weinhold	}
889ecf9d1cSIngo Weinhold}
899ecf9d1cSIngo Weinhold
9081405788SIngo Weinhold
919ecf9d1cSIngo WeinholdBSize
921d6c7b6cSAlex WilsonBCardLayout::BaseMinSize()
939ecf9d1cSIngo Weinhold{
949ecf9d1cSIngo Weinhold	_ValidateMinMax();
959ecf9d1cSIngo Weinhold	return fMin;
969ecf9d1cSIngo Weinhold}
979ecf9d1cSIngo Weinhold
9881405788SIngo Weinhold
999ecf9d1cSIngo WeinholdBSize
1001d6c7b6cSAlex WilsonBCardLayout::BaseMaxSize()
1019ecf9d1cSIngo Weinhold{
1029ecf9d1cSIngo Weinhold	_ValidateMinMax();
1039ecf9d1cSIngo Weinhold	return fMax;
1049ecf9d1cSIngo Weinhold}
1059ecf9d1cSIngo Weinhold
10681405788SIngo Weinhold
1079ecf9d1cSIngo WeinholdBSize
1081d6c7b6cSAlex WilsonBCardLayout::BasePreferredSize()
1099ecf9d1cSIngo Weinhold{
1109ecf9d1cSIngo Weinhold	_ValidateMinMax();
1119ecf9d1cSIngo Weinhold	return fPreferred;
1129ecf9d1cSIngo Weinhold}
1139ecf9d1cSIngo Weinhold
11481405788SIngo Weinhold
1159ecf9d1cSIngo WeinholdBAlignment
1161d6c7b6cSAlex WilsonBCardLayout::BaseAlignment()
1179ecf9d1cSIngo Weinhold{
1189ecf9d1cSIngo Weinhold	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
1199ecf9d1cSIngo Weinhold}
1209ecf9d1cSIngo Weinhold
12181405788SIngo Weinhold
1229ecf9d1cSIngo Weinholdbool
1239ecf9d1cSIngo WeinholdBCardLayout::HasHeightForWidth()
1249ecf9d1cSIngo Weinhold{
1259ecf9d1cSIngo Weinhold	int32 count = CountItems();
1269ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
1279ecf9d1cSIngo Weinhold		if (ItemAt(i)->HasHeightForWidth())
1289ecf9d1cSIngo Weinhold			return true;
1299ecf9d1cSIngo Weinhold	}
130a0747aadSIngo Weinhold
1319ecf9d1cSIngo Weinhold	return false;
1329ecf9d1cSIngo Weinhold}
1339ecf9d1cSIngo Weinhold
13481405788SIngo Weinhold
1359ecf9d1cSIngo Weinholdvoid
1369ecf9d1cSIngo WeinholdBCardLayout::GetHeightForWidth(float width, float* min, float* max,
1379ecf9d1cSIngo Weinhold	float* preferred)
1389ecf9d1cSIngo Weinhold{
1399ecf9d1cSIngo Weinhold	_ValidateMinMax();
1409ecf9d1cSIngo Weinhold
1419ecf9d1cSIngo Weinhold	// init with useful values
1429ecf9d1cSIngo Weinhold	float minHeight = fMin.height;
1439ecf9d1cSIngo Weinhold	float maxHeight = fMax.height;
1449ecf9d1cSIngo Weinhold	float preferredHeight = fPreferred.height;
1459ecf9d1cSIngo Weinhold
1469ecf9d1cSIngo Weinhold	// apply the items' constraints
1479ecf9d1cSIngo Weinhold	int32 count = CountItems();
1489ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
1499ecf9d1cSIngo Weinhold		BLayoutItem* item = ItemAt(i);
1509ecf9d1cSIngo Weinhold		if (item->HasHeightForWidth()) {
1519ecf9d1cSIngo Weinhold			float itemMinHeight;
1529ecf9d1cSIngo Weinhold			float itemMaxHeight;
1539ecf9d1cSIngo Weinhold			float itemPreferredHeight;
1549ecf9d1cSIngo Weinhold			item->GetHeightForWidth(width, &itemMinHeight, &itemMaxHeight,
1559ecf9d1cSIngo Weinhold				&itemPreferredHeight);
1569ecf9d1cSIngo Weinhold			minHeight = max_c(minHeight, itemMinHeight);
1579ecf9d1cSIngo Weinhold			maxHeight = min_c(maxHeight, itemMaxHeight);
1589ecf9d1cSIngo Weinhold			preferredHeight = min_c(preferredHeight, itemPreferredHeight);
1599ecf9d1cSIngo Weinhold		}
1609ecf9d1cSIngo Weinhold	}
1619ecf9d1cSIngo Weinhold
1629ecf9d1cSIngo Weinhold	// adjust max and preferred, if necessary
1639ecf9d1cSIngo Weinhold	maxHeight = max_c(maxHeight, minHeight);
1649ecf9d1cSIngo Weinhold	preferredHeight = max_c(preferredHeight, minHeight);
1659ecf9d1cSIngo Weinhold	preferredHeight = min_c(preferredHeight, maxHeight);
1669ecf9d1cSIngo Weinhold
1679ecf9d1cSIngo Weinhold	if (min)
1689ecf9d1cSIngo Weinhold		*min = minHeight;
1699ecf9d1cSIngo Weinhold	if (max)
1709ecf9d1cSIngo Weinhold		*max = maxHeight;
1719ecf9d1cSIngo Weinhold	if (preferred)
1729ecf9d1cSIngo Weinhold		*preferred = preferredHeight;
1739ecf9d1cSIngo Weinhold}
1749ecf9d1cSIngo Weinhold
17581405788SIngo Weinhold
1769ecf9d1cSIngo Weinholdvoid
177b38ea98fSAlex WilsonBCardLayout::LayoutInvalidated(bool children)
1789ecf9d1cSIngo Weinhold{
1799ecf9d1cSIngo Weinhold	fMinMaxValid = false;
1809ecf9d1cSIngo Weinhold}
1819ecf9d1cSIngo Weinhold
18281405788SIngo Weinhold
1839ecf9d1cSIngo Weinholdvoid
1844e0131f5SAlex WilsonBCardLayout::DoLayout()
1859ecf9d1cSIngo Weinhold{
1869ecf9d1cSIngo Weinhold	_ValidateMinMax();
1879ecf9d1cSIngo Weinhold
1881d6c7b6cSAlex Wilson	BSize size(LayoutArea().Size());
1899ecf9d1cSIngo Weinhold
1901d6c7b6cSAlex Wilson	// this cannot be done when we are viewless, as our children
1911d6c7b6cSAlex Wilson	// would not get cut off in the right place.
1921d6c7b6cSAlex Wilson	if (Owner()) {
1931d6c7b6cSAlex Wilson		size.width = max_c(size.width, fMin.width);
1941d6c7b6cSAlex Wilson		size.height = max_c(size.height, fMin.height);
1951d6c7b6cSAlex Wilson	}
196e01de522SMichael Lotz
197e01de522SMichael Lotz	if (fVisibleItem != NULL)
1981d6c7b6cSAlex Wilson		fVisibleItem->AlignInFrame(BRect(LayoutArea().LeftTop(), size));
1999ecf9d1cSIngo Weinhold}
2009ecf9d1cSIngo Weinhold
20181405788SIngo Weinhold
20281405788SIngo Weinholdstatus_t
20381405788SIngo WeinholdBCardLayout::Archive(BMessage* into, bool deep) const
20481405788SIngo Weinhold{
20581405788SIngo Weinhold	BArchiver archiver(into);
2061d6c7b6cSAlex Wilson	status_t err = BAbstractLayout::Archive(into, deep);
20781405788SIngo Weinhold
20881405788SIngo Weinhold	if (err == B_OK && deep)
20981405788SIngo Weinhold		err = into->AddInt32(kVisibleItemField, IndexOfItem(fVisibleItem));
21081405788SIngo Weinhold
21181405788SIngo Weinhold	return archiver.Finish(err);
21281405788SIngo Weinhold}
21381405788SIngo Weinhold
21481405788SIngo Weinhold
21553617d36SAlex Wilsonstatus_t
21653617d36SAlex WilsonBCardLayout::AllArchived(BMessage* archive) const
21753617d36SAlex Wilson{
21853617d36SAlex Wilson	return BAbstractLayout::AllArchived(archive);
21953617d36SAlex Wilson}
22053617d36SAlex Wilson
22153617d36SAlex Wilson
22281405788SIngo Weinholdstatus_t
22381405788SIngo WeinholdBCardLayout::AllUnarchived(const BMessage* from)
22481405788SIngo Weinhold{
22581405788SIngo Weinhold	status_t err = BLayout::AllUnarchived(from);
22681405788SIngo Weinhold	if (err != B_OK)
22781405788SIngo Weinhold		return err;
22881405788SIngo Weinhold
22981405788SIngo Weinhold	int32 visibleIndex;
23081405788SIngo Weinhold	err = from->FindInt32(kVisibleItemField, &visibleIndex);
23181405788SIngo Weinhold	if (err == B_OK)
23281405788SIngo Weinhold		SetVisibleItem(visibleIndex);
23381405788SIngo Weinhold
23481405788SIngo Weinhold	return err;
23581405788SIngo Weinhold}
23681405788SIngo Weinhold
23781405788SIngo Weinhold
238182e2ee9SAlex Wilsonstatus_t
239182e2ee9SAlex WilsonBCardLayout::ItemArchived(BMessage* into, BLayoutItem* item, int32 index) const
240182e2ee9SAlex Wilson{
241182e2ee9SAlex Wilson	return BAbstractLayout::ItemArchived(into, item, index);
242182e2ee9SAlex Wilson}
243182e2ee9SAlex Wilson
244182e2ee9SAlex Wilson
245182e2ee9SAlex Wilsonstatus_t
246182e2ee9SAlex WilsonBCardLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
247182e2ee9SAlex Wilson	int32 index)
248182e2ee9SAlex Wilson{
249182e2ee9SAlex Wilson	return BAbstractLayout::ItemUnarchived(from, item, index);
250182e2ee9SAlex Wilson}
251182e2ee9SAlex Wilson
252182e2ee9SAlex Wilson
253182e2ee9SAlex Wilson
25481405788SIngo WeinholdBArchivable*
25581405788SIngo WeinholdBCardLayout::Instantiate(BMessage* from)
25681405788SIngo Weinhold{
25781405788SIngo Weinhold	if (validate_instantiation(from, "BCardLayout"))
25881405788SIngo Weinhold		return new BCardLayout(from);
25981405788SIngo Weinhold	return NULL;
26081405788SIngo Weinhold}
261e01de522SMichael Lotz
26281405788SIngo Weinhold
2636829d417SAlex Wilsonbool
2646829d417SAlex WilsonBCardLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
2659ecf9d1cSIngo Weinhold{
2669ecf9d1cSIngo Weinhold	item->SetVisible(false);
2676829d417SAlex Wilson	return true;
2689ecf9d1cSIngo Weinhold}
2699ecf9d1cSIngo Weinhold
27081405788SIngo Weinhold
2719ecf9d1cSIngo Weinholdvoid
2726829d417SAlex WilsonBCardLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
2739ecf9d1cSIngo Weinhold{
2749ecf9d1cSIngo Weinhold	if (fVisibleItem == item) {
2759ecf9d1cSIngo Weinhold		BLayoutItem* newVisibleItem = NULL;
2769ecf9d1cSIngo Weinhold		SetVisibleItem(newVisibleItem);
2779ecf9d1cSIngo Weinhold	}
2789ecf9d1cSIngo Weinhold}
2799ecf9d1cSIngo Weinhold
28081405788SIngo Weinhold
2819ecf9d1cSIngo Weinholdvoid
2829ecf9d1cSIngo WeinholdBCardLayout::_ValidateMinMax()
2839ecf9d1cSIngo Weinhold{
2849ecf9d1cSIngo Weinhold	if (fMinMaxValid)
2859ecf9d1cSIngo Weinhold		return;
2869ecf9d1cSIngo Weinhold
2879ecf9d1cSIngo Weinhold	fMin.width = 0;
2889ecf9d1cSIngo Weinhold	fMin.height = 0;
2899ecf9d1cSIngo Weinhold	fMax.width = B_SIZE_UNLIMITED;
2909ecf9d1cSIngo Weinhold	fMax.height = B_SIZE_UNLIMITED;
2919ecf9d1cSIngo Weinhold	fPreferred.width = 0;
2929ecf9d1cSIngo Weinhold	fPreferred.height = 0;
2939ecf9d1cSIngo Weinhold
2949ecf9d1cSIngo Weinhold	int32 itemCount = CountItems();
2959ecf9d1cSIngo Weinhold	for (int32 i = 0; i < itemCount; i++) {
2969ecf9d1cSIngo Weinhold		BLayoutItem* item = ItemAt(i);
2979ecf9d1cSIngo Weinhold
2989ecf9d1cSIngo Weinhold		BSize min = item->MinSize();
2999ecf9d1cSIngo Weinhold		BSize max = item->MaxSize();
3009ecf9d1cSIngo Weinhold		BSize preferred = item->PreferredSize();
3019ecf9d1cSIngo Weinhold
3029ecf9d1cSIngo Weinhold		fMin.width = max_c(fMin.width, min.width);
3039ecf9d1cSIngo Weinhold		fMin.height = max_c(fMin.height, min.height);
3049ecf9d1cSIngo Weinhold
3059ecf9d1cSIngo Weinhold		fMax.width = min_c(fMax.width, max.width);
3069ecf9d1cSIngo Weinhold		fMax.height = min_c(fMax.height, max.height);
3079ecf9d1cSIngo Weinhold
3089ecf9d1cSIngo Weinhold		fPreferred.width = max_c(fPreferred.width, preferred.width);
3099ecf9d1cSIngo Weinhold		fPreferred.height = max_c(fPreferred.height, preferred.height);
3109ecf9d1cSIngo Weinhold	}
3119ecf9d1cSIngo Weinhold
3129ecf9d1cSIngo Weinhold	fMax.width = max_c(fMax.width, fMin.width);
3139ecf9d1cSIngo Weinhold	fMax.height = max_c(fMax.height, fMin.height);
3149ecf9d1cSIngo Weinhold
3159ecf9d1cSIngo Weinhold	fPreferred.width = max_c(fPreferred.width, fMin.width);
3169ecf9d1cSIngo Weinhold	fPreferred.height = max_c(fPreferred.height, fMin.height);
3179ecf9d1cSIngo Weinhold	fPreferred.width = min_c(fPreferred.width, fMax.width);
3189ecf9d1cSIngo Weinhold	fPreferred.height = min_c(fPreferred.height, fMax.height);
319a0747aadSIngo Weinhold
3209ecf9d1cSIngo Weinhold	fMinMaxValid = true;
3211d6c7b6cSAlex Wilson	ResetLayoutInvalidation();
3229ecf9d1cSIngo Weinhold}
323a851b3adSAlex Wilson
324a851b3adSAlex Wilson
325a851b3adSAlex Wilsonstatus_t
326a851b3adSAlex WilsonBCardLayout::Perform(perform_code d, void* arg)
327a851b3adSAlex Wilson{
328a851b3adSAlex Wilson	return BAbstractLayout::Perform(d, arg);
329a851b3adSAlex Wilson}
330a851b3adSAlex Wilson
3318151838eSAlex Wilson
3328151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout1() {}
3338151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout2() {}
3348151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout3() {}
3358151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout4() {}
3368151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout5() {}
3378151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout6() {}
3388151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout7() {}
3398151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout8() {}
3408151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout9() {}
3418151838eSAlex Wilsonvoid BCardLayout::_ReservedCardLayout10() {}
3428151838eSAlex Wilson
343