xref: /haiku/src/kits/interface/LayoutUtils.cpp (revision e439b003978b9554e034bb4cfc59e164a7215b31)
19ecf9d1cSIngo Weinhold /*
24a8da960SIngo Weinhold  * Copyright 2006-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3*e439b003SJohn Scipione  * Copyright 2014 Haiku, Inc. All rights reserved.
4*e439b003SJohn Scipione  *
539c1cc12SIngo Weinhold  * Distributed under the terms of the MIT License.
6*e439b003SJohn Scipione  *
7*e439b003SJohn Scipione  * Authors:
8*e439b003SJohn Scipione  *		John Scipione, jscipione@gmail.com
9*e439b003SJohn Scipione  *		Ingo Weinhold, ingo_weinhold@gmx.de
109ecf9d1cSIngo Weinhold  */
119ecf9d1cSIngo Weinhold 
129ecf9d1cSIngo Weinhold #include <LayoutUtils.h>
139ecf9d1cSIngo Weinhold 
146ecc270fSJohn Scipione #include <algorithm>
154a8da960SIngo Weinhold #include <typeinfo>
164a8da960SIngo Weinhold 
174a8da960SIngo Weinhold #include <Layout.h>
18dd5ac13bSIngo Weinhold #include <View.h>
19dd5ac13bSIngo Weinhold 
204a8da960SIngo Weinhold #include "ViewLayoutItem.h"
214a8da960SIngo Weinhold 
229ecf9d1cSIngo Weinhold 
239ecf9d1cSIngo Weinhold // // AddSizesFloat
249ecf9d1cSIngo Weinhold // float
259ecf9d1cSIngo Weinhold // BLayoutUtils::AddSizesFloat(float a, float b)
269ecf9d1cSIngo Weinhold // {
279ecf9d1cSIngo Weinhold // 	float sum = a + b + 1;
289ecf9d1cSIngo Weinhold // 	if (sum >= B_SIZE_UNLIMITED)
299ecf9d1cSIngo Weinhold // 		return B_SIZE_UNLIMITED;
309ecf9d1cSIngo Weinhold //
319ecf9d1cSIngo Weinhold // 	return sum;
329ecf9d1cSIngo Weinhold // }
339ecf9d1cSIngo Weinhold //
349ecf9d1cSIngo Weinhold // // AddSizesFloat
359ecf9d1cSIngo Weinhold // float
369ecf9d1cSIngo Weinhold // BLayoutUtils::AddSizesFloat(float a, float b, float c)
379ecf9d1cSIngo Weinhold // {
389ecf9d1cSIngo Weinhold // 	return AddSizesFloat(AddSizesFloat(a, b), c);
399ecf9d1cSIngo Weinhold // }
409ecf9d1cSIngo Weinhold 
41dd5ac13bSIngo Weinhold 
429ecf9d1cSIngo Weinhold // AddSizesInt32
439ecf9d1cSIngo Weinhold int32
449ecf9d1cSIngo Weinhold BLayoutUtils::AddSizesInt32(int32 a, int32 b)
459ecf9d1cSIngo Weinhold {
469ecf9d1cSIngo Weinhold 	if (a >= B_SIZE_UNLIMITED - b)
479ecf9d1cSIngo Weinhold 		return B_SIZE_UNLIMITED;
489ecf9d1cSIngo Weinhold 	return a + b;
499ecf9d1cSIngo Weinhold }
509ecf9d1cSIngo Weinhold 
51dd5ac13bSIngo Weinhold 
529ecf9d1cSIngo Weinhold // AddSizesInt32
539ecf9d1cSIngo Weinhold int32
549ecf9d1cSIngo Weinhold BLayoutUtils::AddSizesInt32(int32 a, int32 b, int32 c)
559ecf9d1cSIngo Weinhold {
569ecf9d1cSIngo Weinhold 	return AddSizesInt32(AddSizesInt32(a, b), c);
579ecf9d1cSIngo Weinhold }
589ecf9d1cSIngo Weinhold 
59dd5ac13bSIngo Weinhold 
609ecf9d1cSIngo Weinhold // AddDistances
619ecf9d1cSIngo Weinhold float
629ecf9d1cSIngo Weinhold BLayoutUtils::AddDistances(float a, float b)
639ecf9d1cSIngo Weinhold {
649ecf9d1cSIngo Weinhold 	float sum = a + b + 1;
659ecf9d1cSIngo Weinhold 	if (sum >= B_SIZE_UNLIMITED)
669ecf9d1cSIngo Weinhold 		return B_SIZE_UNLIMITED;
679ecf9d1cSIngo Weinhold 
689ecf9d1cSIngo Weinhold 	return sum;
699ecf9d1cSIngo Weinhold }
709ecf9d1cSIngo Weinhold 
71dd5ac13bSIngo Weinhold 
729ecf9d1cSIngo Weinhold // AddDistances
739ecf9d1cSIngo Weinhold float
749ecf9d1cSIngo Weinhold BLayoutUtils::AddDistances(float a, float b, float c)
759ecf9d1cSIngo Weinhold {
769ecf9d1cSIngo Weinhold 	return AddDistances(AddDistances(a, b), c);
779ecf9d1cSIngo Weinhold }
789ecf9d1cSIngo Weinhold 
79dd5ac13bSIngo Weinhold 
809ecf9d1cSIngo Weinhold // // SubtractSizesFloat
819ecf9d1cSIngo Weinhold // float
829ecf9d1cSIngo Weinhold // BLayoutUtils::SubtractSizesFloat(float a, float b)
839ecf9d1cSIngo Weinhold // {
849ecf9d1cSIngo Weinhold // 	if (a < b)
859ecf9d1cSIngo Weinhold // 		return -1;
869ecf9d1cSIngo Weinhold // 	return a - b - 1;
879ecf9d1cSIngo Weinhold // }
889ecf9d1cSIngo Weinhold 
89dd5ac13bSIngo Weinhold 
909ecf9d1cSIngo Weinhold // SubtractSizesInt32
919ecf9d1cSIngo Weinhold int32
929ecf9d1cSIngo Weinhold BLayoutUtils::SubtractSizesInt32(int32 a, int32 b)
939ecf9d1cSIngo Weinhold {
949ecf9d1cSIngo Weinhold 	if (a < b)
959ecf9d1cSIngo Weinhold 		return 0;
969ecf9d1cSIngo Weinhold 	return a - b;
979ecf9d1cSIngo Weinhold }
989ecf9d1cSIngo Weinhold 
99dd5ac13bSIngo Weinhold 
1009ecf9d1cSIngo Weinhold // SubtractDistances
1019ecf9d1cSIngo Weinhold float
1029ecf9d1cSIngo Weinhold BLayoutUtils::SubtractDistances(float a, float b)
1039ecf9d1cSIngo Weinhold {
1049ecf9d1cSIngo Weinhold 	if (a < b)
1059ecf9d1cSIngo Weinhold 		return -1;
1069ecf9d1cSIngo Weinhold 	return a - b - 1;
1079ecf9d1cSIngo Weinhold }
1089ecf9d1cSIngo Weinhold 
109dd5ac13bSIngo Weinhold 
110dd5ac13bSIngo Weinhold // FixSizeConstraints
111dd5ac13bSIngo Weinhold void
112dd5ac13bSIngo Weinhold BLayoutUtils::FixSizeConstraints(float& min, float& max, float& preferred)
113dd5ac13bSIngo Weinhold {
114dd5ac13bSIngo Weinhold 	if (max < min)
115dd5ac13bSIngo Weinhold 		max = min;
116dd5ac13bSIngo Weinhold 	if (preferred < min)
117dd5ac13bSIngo Weinhold 		preferred = min;
118dd5ac13bSIngo Weinhold 	else if (preferred > max)
119dd5ac13bSIngo Weinhold 		preferred = max;
120dd5ac13bSIngo Weinhold }
121dd5ac13bSIngo Weinhold 
122dd5ac13bSIngo Weinhold 
123dd5ac13bSIngo Weinhold // FixSizeConstraints
124dd5ac13bSIngo Weinhold void
125dd5ac13bSIngo Weinhold BLayoutUtils::FixSizeConstraints(BSize& min, BSize& max, BSize& preferred)
126dd5ac13bSIngo Weinhold {
127dd5ac13bSIngo Weinhold 	FixSizeConstraints(min.width, max.width, preferred.width);
128dd5ac13bSIngo Weinhold 	FixSizeConstraints(min.height, max.height, preferred.height);
129dd5ac13bSIngo Weinhold }
130dd5ac13bSIngo Weinhold 
131dd5ac13bSIngo Weinhold 
1329ecf9d1cSIngo Weinhold // ComposeSize
1339ecf9d1cSIngo Weinhold BSize
1349ecf9d1cSIngo Weinhold BLayoutUtils::ComposeSize(BSize size, BSize layoutSize)
1359ecf9d1cSIngo Weinhold {
1369ecf9d1cSIngo Weinhold 	if (!size.IsWidthSet())
1379ecf9d1cSIngo Weinhold 		size.width = layoutSize.width;
1389ecf9d1cSIngo Weinhold 	if (!size.IsHeightSet())
1399ecf9d1cSIngo Weinhold 		size.height = layoutSize.height;
1409ecf9d1cSIngo Weinhold 
1419ecf9d1cSIngo Weinhold 	return size;
1429ecf9d1cSIngo Weinhold }
1439ecf9d1cSIngo Weinhold 
144dd5ac13bSIngo Weinhold 
1459ecf9d1cSIngo Weinhold // ComposeAlignment
1469ecf9d1cSIngo Weinhold BAlignment
1479ecf9d1cSIngo Weinhold BLayoutUtils::ComposeAlignment(BAlignment alignment, BAlignment layoutAlignment)
1489ecf9d1cSIngo Weinhold {
1499ecf9d1cSIngo Weinhold 	if (!alignment.IsHorizontalSet())
1509ecf9d1cSIngo Weinhold 		alignment.horizontal = layoutAlignment.horizontal;
1519ecf9d1cSIngo Weinhold 	if (!alignment.IsVerticalSet())
1529ecf9d1cSIngo Weinhold 		alignment.vertical = layoutAlignment.vertical;
1539ecf9d1cSIngo Weinhold 
1549ecf9d1cSIngo Weinhold 	return alignment;
1559ecf9d1cSIngo Weinhold }
1569ecf9d1cSIngo Weinhold 
157dd5ac13bSIngo Weinhold 
1589ecf9d1cSIngo Weinhold // AlignInFrame
159*e439b003SJohn Scipione // This method restricts the dimensions of the resulting rectangle according
160*e439b003SJohn Scipione // to the available size specified by maxSize.
1619ecf9d1cSIngo Weinhold BRect
1629ecf9d1cSIngo Weinhold BLayoutUtils::AlignInFrame(BRect frame, BSize maxSize, BAlignment alignment)
1639ecf9d1cSIngo Weinhold {
1649ecf9d1cSIngo Weinhold 	// align according to the given alignment
1659ecf9d1cSIngo Weinhold 	if (maxSize.width < frame.Width()
1669ecf9d1cSIngo Weinhold 		&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
1679ecf9d1cSIngo Weinhold 		frame.left += (int)((frame.Width() - maxSize.width)
1689ecf9d1cSIngo Weinhold 			* alignment.RelativeHorizontal());
1699ecf9d1cSIngo Weinhold 		frame.right = frame.left + maxSize.width;
1709ecf9d1cSIngo Weinhold 	}
1719ecf9d1cSIngo Weinhold 	if (maxSize.height < frame.Height()
1729ecf9d1cSIngo Weinhold 		&& alignment.vertical != B_ALIGN_USE_FULL_HEIGHT) {
1739ecf9d1cSIngo Weinhold 		frame.top += (int)((frame.Height() - maxSize.height)
1749ecf9d1cSIngo Weinhold 			* alignment.RelativeVertical());
1759ecf9d1cSIngo Weinhold 		frame.bottom = frame.top + maxSize.height;
1769ecf9d1cSIngo Weinhold 	}
1779ecf9d1cSIngo Weinhold 
1789ecf9d1cSIngo Weinhold 	return frame;
1799ecf9d1cSIngo Weinhold }
1809ecf9d1cSIngo Weinhold 
181dd5ac13bSIngo Weinhold 
1829ecf9d1cSIngo Weinhold // AlignInFrame
1839ecf9d1cSIngo Weinhold void
1849ecf9d1cSIngo Weinhold BLayoutUtils::AlignInFrame(BView* view, BRect frame)
1859ecf9d1cSIngo Weinhold {
186dd5ac13bSIngo Weinhold 	BSize maxSize = view->MaxSize();
18752e06f98SStephan Aßmus 	BAlignment alignment = view->LayoutAlignment();
188dd5ac13bSIngo Weinhold 	if (view->HasHeightForWidth()) {
189dd5ac13bSIngo Weinhold 		// The view has height for width, so we do the horizontal alignment
190dd5ac13bSIngo Weinhold 		// ourselves and restrict the height max constraint respectively.
191dd5ac13bSIngo Weinhold 		if (maxSize.width < frame.Width()
192dd5ac13bSIngo Weinhold 			&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
193f0fdd7b9SJohn Scipione 			frame.OffsetBy(floorf((frame.Width() - maxSize.width)
194dd5ac13bSIngo Weinhold 				* alignment.RelativeHorizontal()), 0);
195dd5ac13bSIngo Weinhold 			frame.right = frame.left + maxSize.width;
196dd5ac13bSIngo Weinhold 		}
197dd5ac13bSIngo Weinhold 		alignment.horizontal = B_ALIGN_USE_FULL_WIDTH;
198dd5ac13bSIngo Weinhold 		float minHeight;
199dd5ac13bSIngo Weinhold 		float maxHeight;
200dd5ac13bSIngo Weinhold 		float preferredHeight;
201dd5ac13bSIngo Weinhold 		view->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
202dd5ac13bSIngo Weinhold 			&preferredHeight);
2036ecc270fSJohn Scipione 		frame.bottom = frame.top + std::max(frame.Height(), minHeight);
204dd5ac13bSIngo Weinhold 		maxSize.height = minHeight;
205dd5ac13bSIngo Weinhold 	}
206dd5ac13bSIngo Weinhold 	frame = AlignInFrame(frame, maxSize, alignment);
207dd5ac13bSIngo Weinhold 	view->MoveTo(frame.LeftTop());
208dd5ac13bSIngo Weinhold 	view->ResizeTo(frame.Size());
2099ecf9d1cSIngo Weinhold }
2109ecf9d1cSIngo Weinhold 
21139c1cc12SIngo Weinhold 
212*e439b003SJohn Scipione // AlignOnRect
213*e439b003SJohn Scipione // This method, unlike AlignInFrame(), provides the possibility to return
214*e439b003SJohn Scipione // a rectangle with dimensions greater than the available size.
215*e439b003SJohn Scipione BRect
216*e439b003SJohn Scipione BLayoutUtils::AlignOnRect(BRect rect, BSize size, BAlignment alignment)
217*e439b003SJohn Scipione {
218*e439b003SJohn Scipione 	rect.left += (int)((rect.Width() - size.width)
219*e439b003SJohn Scipione 		* alignment.RelativeHorizontal());
220*e439b003SJohn Scipione 	rect.top += (int)(((rect.Height() - size.height))
221*e439b003SJohn Scipione 		* alignment.RelativeVertical());
222*e439b003SJohn Scipione 	rect.right = rect.left + size.width;
223*e439b003SJohn Scipione 	rect.bottom = rect.top + size.height;
224*e439b003SJohn Scipione 
225*e439b003SJohn Scipione 	return rect;
226*e439b003SJohn Scipione }
227*e439b003SJohn Scipione 
228*e439b003SJohn Scipione 
22939c1cc12SIngo Weinhold /*!	Offsets a rectangle's location so that it lies fully in a given rectangular
23039c1cc12SIngo Weinhold 	frame.
23139c1cc12SIngo Weinhold 
23239c1cc12SIngo Weinhold 	If the rectangle is too wide/high to fully fit in the frame, its left/top
23339c1cc12SIngo Weinhold 	edge is offset to 0. The rect's size always remains unchanged.
23439c1cc12SIngo Weinhold 
23539c1cc12SIngo Weinhold 	\param rect The rectangle to be moved.
23639c1cc12SIngo Weinhold 	\param frameSize The size of the frame the rect shall be moved into. The
23739c1cc12SIngo Weinhold 		frame's left-top is (0, 0).
23839c1cc12SIngo Weinhold 	\return The modified rect.
23939c1cc12SIngo Weinhold */
24039c1cc12SIngo Weinhold /*static*/ BRect
24139c1cc12SIngo Weinhold BLayoutUtils::MoveIntoFrame(BRect rect, BSize frameSize)
24239c1cc12SIngo Weinhold {
24339c1cc12SIngo Weinhold 	BPoint leftTop(rect.LeftTop());
24439c1cc12SIngo Weinhold 
24539c1cc12SIngo Weinhold 	// enforce horizontal limits; favor left edge
24639c1cc12SIngo Weinhold 	if (rect.right > frameSize.width)
24739c1cc12SIngo Weinhold 		leftTop.x -= rect.right - frameSize.width;
248df2b4726SIngo Weinhold 	if (leftTop.x < 0)
24939c1cc12SIngo Weinhold 		leftTop.x = 0;
25039c1cc12SIngo Weinhold 
25139c1cc12SIngo Weinhold 	// enforce vertical limits; favor top edge
25239c1cc12SIngo Weinhold 	if (rect.bottom > frameSize.height)
25339c1cc12SIngo Weinhold 		leftTop.y -= rect.bottom - frameSize.height;
254df2b4726SIngo Weinhold 	if (leftTop.y < 0)
25539c1cc12SIngo Weinhold 		leftTop.y = 0;
25639c1cc12SIngo Weinhold 
25739c1cc12SIngo Weinhold 	return rect.OffsetToSelf(leftTop);
25839c1cc12SIngo Weinhold }
2594a8da960SIngo Weinhold 
2604a8da960SIngo Weinhold 
2614a8da960SIngo Weinhold /*static*/ BString
2624a8da960SIngo Weinhold BLayoutUtils::GetLayoutTreeDump(BView* view)
2634a8da960SIngo Weinhold {
2644a8da960SIngo Weinhold 	BString result;
2654a8da960SIngo Weinhold 	_GetLayoutTreeDump(view, 0, result);
2664a8da960SIngo Weinhold 	return result;
2674a8da960SIngo Weinhold }
2684a8da960SIngo Weinhold 
2694a8da960SIngo Weinhold 
2704a8da960SIngo Weinhold /*static*/ BString
2714a8da960SIngo Weinhold BLayoutUtils::GetLayoutTreeDump(BLayoutItem* item)
2724a8da960SIngo Weinhold {
2734a8da960SIngo Weinhold 	BString result;
2744a8da960SIngo Weinhold 	_GetLayoutTreeDump(item, 0, false, result);
2754a8da960SIngo Weinhold 	return result;
2764a8da960SIngo Weinhold }
2774a8da960SIngo Weinhold 
2784a8da960SIngo Weinhold 
2794a8da960SIngo Weinhold /*static*/ void
2804a8da960SIngo Weinhold BLayoutUtils::_GetLayoutTreeDump(BView* view, int level, BString& _output)
2814a8da960SIngo Weinhold {
2824a8da960SIngo Weinhold 	BString indent;
2834a8da960SIngo Weinhold 	indent.SetTo(' ', level * 2);
2844a8da960SIngo Weinhold 
2854a8da960SIngo Weinhold 	if (view == NULL) {
2864a8da960SIngo Weinhold 		_output << indent << "<null view>\n";
2874a8da960SIngo Weinhold 		return;
2884a8da960SIngo Weinhold 	}
2894a8da960SIngo Weinhold 
2904a8da960SIngo Weinhold 	BRect frame = view->Frame();
2914a8da960SIngo Weinhold 	BSize min = view->MinSize();
2924a8da960SIngo Weinhold 	BSize max = view->MinSize();
2934a8da960SIngo Weinhold 	BSize preferred = view->PreferredSize();
2944a8da960SIngo Weinhold 	_output << BString().SetToFormat(
2954a8da960SIngo Weinhold 		"%sview %p (%s):\n"
2964a8da960SIngo Weinhold 		"%s  frame: (%f, %f, %f, %f)\n"
2974a8da960SIngo Weinhold 		"%s  min:   (%f, %f)\n"
2984a8da960SIngo Weinhold 		"%s  max:   (%f, %f)\n"
2994a8da960SIngo Weinhold 		"%s  pref:  (%f, %f)\n",
3004a8da960SIngo Weinhold 		indent.String(), view, typeid(*view).name(),
3014a8da960SIngo Weinhold 		indent.String(), frame.left, frame.top, frame.right, frame.bottom,
3024a8da960SIngo Weinhold 		indent.String(), min.width, min.height,
3034a8da960SIngo Weinhold 		indent.String(), max.width, max.height,
3044a8da960SIngo Weinhold 		indent.String(), preferred.width, preferred.height);
3054a8da960SIngo Weinhold 
3064a8da960SIngo Weinhold 	if (BLayout* layout = view->GetLayout()) {
3074a8da960SIngo Weinhold 		_GetLayoutTreeDump(layout, level, true, _output);
3084a8da960SIngo Weinhold 		return;
3094a8da960SIngo Weinhold 	}
3104a8da960SIngo Weinhold 
3114a8da960SIngo Weinhold 	int32 count = view->CountChildren();
3124a8da960SIngo Weinhold 	for (int32 i = 0; i < count; i++) {
3134a8da960SIngo Weinhold 		_output << indent << "  ---\n";
3144a8da960SIngo Weinhold 		_GetLayoutTreeDump(view->ChildAt(i), level + 1, _output);
3154a8da960SIngo Weinhold 	}
3164a8da960SIngo Weinhold }
3174a8da960SIngo Weinhold 
3184a8da960SIngo Weinhold 
3194a8da960SIngo Weinhold /*static*/ void
3204a8da960SIngo Weinhold BLayoutUtils::_GetLayoutTreeDump(BLayoutItem* item, int level,
3214a8da960SIngo Weinhold 	bool isViewLayout, BString& _output)
3224a8da960SIngo Weinhold {
3234a8da960SIngo Weinhold 	if (BViewLayoutItem* viewItem = dynamic_cast<BViewLayoutItem*>(item)) {
3244a8da960SIngo Weinhold 		_GetLayoutTreeDump(viewItem->View(), level, _output);
3254a8da960SIngo Weinhold 		return;
3264a8da960SIngo Weinhold 	}
3274a8da960SIngo Weinhold 
3284a8da960SIngo Weinhold 	BString indent;
3294a8da960SIngo Weinhold 	indent.SetTo(' ', level * 2);
3304a8da960SIngo Weinhold 
3314a8da960SIngo Weinhold 	if (item == NULL) {
3324a8da960SIngo Weinhold 		_output << indent << "<null item>\n";
3334a8da960SIngo Weinhold 		return;
3344a8da960SIngo Weinhold 	}
3354a8da960SIngo Weinhold 
3364a8da960SIngo Weinhold 	BLayout* layout = dynamic_cast<BLayout*>(item);
3374a8da960SIngo Weinhold 	BRect frame = item->Frame();
3384a8da960SIngo Weinhold 	BSize min = item->MinSize();
3394a8da960SIngo Weinhold 	BSize max = item->MinSize();
3404a8da960SIngo Weinhold 	BSize preferred = item->PreferredSize();
3414a8da960SIngo Weinhold 	if (isViewLayout) {
3424a8da960SIngo Weinhold 		_output << indent << BString().SetToFormat("  [layout %p (%s)]\n",
3434a8da960SIngo Weinhold 			layout, typeid(*layout).name());
3444a8da960SIngo Weinhold 	} else {
3454a8da960SIngo Weinhold 		_output << indent << BString().SetToFormat("item %p (%s):\n",
3464a8da960SIngo Weinhold 			item, typeid(*item).name());
3474a8da960SIngo Weinhold 	}
3484a8da960SIngo Weinhold 	_output << BString().SetToFormat(
3494a8da960SIngo Weinhold 		"%s  frame: (%f, %f, %f, %f)\n"
3504a8da960SIngo Weinhold 		"%s  min:   (%f, %f)\n"
3514a8da960SIngo Weinhold 		"%s  max:   (%f, %f)\n"
3524a8da960SIngo Weinhold 		"%s  pref:  (%f, %f)\n",
3534a8da960SIngo Weinhold 		indent.String(), frame.left, frame.top, frame.right, frame.bottom,
3544a8da960SIngo Weinhold 		indent.String(), min.width, min.height,
3554a8da960SIngo Weinhold 		indent.String(), max.width, max.height,
3564a8da960SIngo Weinhold 		indent.String(), preferred.width, preferred.height);
3574a8da960SIngo Weinhold 
3584a8da960SIngo Weinhold 	if (layout == NULL)
3594a8da960SIngo Weinhold 		return;
3604a8da960SIngo Weinhold 
3614a8da960SIngo Weinhold 	int32 count = layout->CountItems();
3624a8da960SIngo Weinhold 	for (int32 i = 0; i < count; i++) {
3634a8da960SIngo Weinhold 		_output << indent << "  ---\n";
3644a8da960SIngo Weinhold 		_GetLayoutTreeDump(layout->ItemAt(i), level + 1, false, _output);
3654a8da960SIngo Weinhold 	}
3664a8da960SIngo Weinhold }
367