xref: /haiku/src/kits/interface/CardLayout.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright 2006-2009, Ingo Weinhold <ingo_weinhold@gmx.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include <CardLayout.h>
7 
8 #include <LayoutItem.h>
9 #include <View.h>
10 
11 // constructor
12 BCardLayout::BCardLayout()
13 	: BLayout(),
14 	  fMin(0, 0),
15 	  fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
16 	  fPreferred(0, 0),
17 	  fVisibleItem(NULL),
18 	  fMinMaxValid(false)
19 {
20 }
21 
22 // destructor
23 BCardLayout::~BCardLayout()
24 {
25 }
26 
27 // VisibleItem
28 BLayoutItem*
29 BCardLayout::VisibleItem() const
30 {
31 	return fVisibleItem;
32 }
33 
34 // VisibleIndex
35 int32
36 BCardLayout::VisibleIndex() const
37 {
38 	return IndexOfItem(fVisibleItem);
39 }
40 
41 // SetVisibleItem
42 void
43 BCardLayout::SetVisibleItem(int32 index)
44 {
45 	SetVisibleItem(ItemAt(index));
46 }
47 
48 // SetVisibleItem
49 void
50 BCardLayout::SetVisibleItem(BLayoutItem* item)
51 {
52 	if (item == fVisibleItem)
53 		return;
54 
55 	if (item != NULL && IndexOfItem(item) < 0)
56 		return;
57 
58 	if (fVisibleItem != NULL)
59 		fVisibleItem->SetVisible(false);
60 
61 	fVisibleItem = item;
62 
63 	if (fVisibleItem != NULL) {
64 		fVisibleItem->SetVisible(true);
65 
66 		LayoutView();
67 	}
68 }
69 
70 // MinSize
71 BSize
72 BCardLayout::MinSize()
73 {
74 	_ValidateMinMax();
75 	return fMin;
76 }
77 
78 // MaxSize
79 BSize
80 BCardLayout::MaxSize()
81 {
82 	_ValidateMinMax();
83 	return fMax;
84 }
85 
86 // PreferredSize
87 BSize
88 BCardLayout::PreferredSize()
89 {
90 	_ValidateMinMax();
91 	return fPreferred;
92 }
93 
94 // Alignment
95 BAlignment
96 BCardLayout::Alignment()
97 {
98 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
99 }
100 
101 // HasHeightForWidth
102 bool
103 BCardLayout::HasHeightForWidth()
104 {
105 	int32 count = CountItems();
106 	for (int32 i = 0; i < count; i++) {
107 		if (ItemAt(i)->HasHeightForWidth())
108 			return true;
109 	}
110 
111 	return false;
112 }
113 
114 // GetHeightForWidth
115 void
116 BCardLayout::GetHeightForWidth(float width, float* min, float* max,
117 	float* preferred)
118 {
119 	_ValidateMinMax();
120 
121 	// init with useful values
122 	float minHeight = fMin.height;
123 	float maxHeight = fMax.height;
124 	float preferredHeight = fPreferred.height;
125 
126 	// apply the items' constraints
127 	int32 count = CountItems();
128 	for (int32 i = 0; i < count; i++) {
129 		BLayoutItem* item = ItemAt(i);
130 		if (item->HasHeightForWidth()) {
131 			float itemMinHeight;
132 			float itemMaxHeight;
133 			float itemPreferredHeight;
134 			item->GetHeightForWidth(width, &itemMinHeight, &itemMaxHeight,
135 				&itemPreferredHeight);
136 			minHeight = max_c(minHeight, itemMinHeight);
137 			maxHeight = min_c(maxHeight, itemMaxHeight);
138 			preferredHeight = min_c(preferredHeight, itemPreferredHeight);
139 		}
140 	}
141 
142 	// adjust max and preferred, if necessary
143 	maxHeight = max_c(maxHeight, minHeight);
144 	preferredHeight = max_c(preferredHeight, minHeight);
145 	preferredHeight = min_c(preferredHeight, maxHeight);
146 
147 	if (min)
148 		*min = minHeight;
149 	if (max)
150 		*max = maxHeight;
151 	if (preferred)
152 		*preferred = preferredHeight;
153 }
154 
155 // InvalidateLayout
156 void
157 BCardLayout::InvalidateLayout()
158 {
159 	BLayout::InvalidateLayout();
160 
161 	fMinMaxValid = false;
162 }
163 
164 // LayoutView
165 void
166 BCardLayout::LayoutView()
167 {
168 	_ValidateMinMax();
169 
170 	BSize size = View()->Bounds().Size();
171 	size.width = max_c(size.width, fMin.width);
172 	size.height = max_c(size.height, fMin.height);
173 
174 	if (fVisibleItem != NULL)
175 		fVisibleItem->AlignInFrame(BRect(0, 0, size.width, size.height));
176 }
177 
178 // ItemAdded
179 void
180 BCardLayout::ItemAdded(BLayoutItem* item)
181 {
182 	item->SetVisible(false);
183 }
184 
185 // ItemRemoved
186 void
187 BCardLayout::ItemRemoved(BLayoutItem* item)
188 {
189 	if (fVisibleItem == item) {
190 		BLayoutItem* newVisibleItem = NULL;
191 		SetVisibleItem(newVisibleItem);
192 	}
193 }
194 
195 // _ValidateMinMax
196 void
197 BCardLayout::_ValidateMinMax()
198 {
199 	if (fMinMaxValid)
200 		return;
201 
202 	fMin.width = 0;
203 	fMin.height = 0;
204 	fMax.width = B_SIZE_UNLIMITED;
205 	fMax.height = B_SIZE_UNLIMITED;
206 	fPreferred.width = 0;
207 	fPreferred.height = 0;
208 
209 	int32 itemCount = CountItems();
210 	for (int32 i = 0; i < itemCount; i++) {
211 		BLayoutItem* item = ItemAt(i);
212 
213 		BSize min = item->MinSize();
214 		BSize max = item->MaxSize();
215 		BSize preferred = item->PreferredSize();
216 
217 		fMin.width = max_c(fMin.width, min.width);
218 		fMin.height = max_c(fMin.height, min.height);
219 
220 		fMax.width = min_c(fMax.width, max.width);
221 		fMax.height = min_c(fMax.height, max.height);
222 
223 		fPreferred.width = max_c(fPreferred.width, preferred.width);
224 		fPreferred.height = max_c(fPreferred.height, preferred.height);
225 	}
226 
227 	fMax.width = max_c(fMax.width, fMin.width);
228 	fMax.height = max_c(fMax.height, fMin.height);
229 
230 	fPreferred.width = max_c(fPreferred.width, fMin.width);
231 	fPreferred.height = max_c(fPreferred.height, fMin.height);
232 	fPreferred.width = min_c(fPreferred.width, fMax.width);
233 	fPreferred.height = min_c(fPreferred.height, fMax.height);
234 
235 	fMinMaxValid = true;
236 
237 	if (BView* view = View())
238 		view->ResetLayoutInvalidation();
239 }
240