19ecf9d1cSIngo Weinhold/*
2320a5686SIngo Weinhold * Copyright 2006-2010, Ingo Weinhold <ingo_weinhold@gmx.de>.
39ecf9d1cSIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License.
49ecf9d1cSIngo Weinhold */
59ecf9d1cSIngo Weinhold
607dbd4d5SAxel Dörfler
79ecf9d1cSIngo Weinhold#include <TwoDimensionalLayout.h>
89ecf9d1cSIngo Weinhold
99ecf9d1cSIngo Weinhold#include <stdio.h>
109ecf9d1cSIngo Weinhold
1182ab3167SAlex Wilson#include <ControlLook.h>
129ecf9d1cSIngo Weinhold#include <LayoutContext.h>
139ecf9d1cSIngo Weinhold#include <LayoutItem.h>
149ecf9d1cSIngo Weinhold#include <LayoutUtils.h>
159ecf9d1cSIngo Weinhold#include <List.h>
1680c2bbd8SIngo Weinhold#include <Message.h>
179ecf9d1cSIngo Weinhold#include <View.h>
189ecf9d1cSIngo Weinhold
19320a5686SIngo Weinhold#include <Referenceable.h>
20320a5686SIngo Weinhold
21de667551SAlex Wilson#include "CollapsingLayouter.h"
229ecf9d1cSIngo Weinhold
239ecf9d1cSIngo Weinhold
249ecf9d1cSIngo Weinhold// Some words of explanation:
259ecf9d1cSIngo Weinhold//
269ecf9d1cSIngo Weinhold// This class is the base class for BLayouts that organize their items
279ecf9d1cSIngo Weinhold// on a grid, with each item covering one or more grid cells (always a
289ecf9d1cSIngo Weinhold// rectangular area). The derived classes only need to implement the
299ecf9d1cSIngo Weinhold// hooks reporting the constraints for the items and additional constraints
309ecf9d1cSIngo Weinhold// for the rows and columns. This class does all the layouting.
319ecf9d1cSIngo Weinhold//
329ecf9d1cSIngo Weinhold// The basic idea of the layout process is simple. The horizontal and the
339ecf9d1cSIngo Weinhold// vertical dimensions are laid out independently and the items are set to the
349ecf9d1cSIngo Weinhold// resulting locations and sizes. The "height for width" feature makes the
359ecf9d1cSIngo Weinhold// height depend on the width, which makes things a bit more complicated.
369ecf9d1cSIngo Weinhold// The horizontal dimension must be laid out first and and the results are
379ecf9d1cSIngo Weinhold// fed into the vertical layout process.
389ecf9d1cSIngo Weinhold//
399ecf9d1cSIngo Weinhold// The AlignLayoutWith() feature, which allows to align layouts for different
409ecf9d1cSIngo Weinhold// views with each other, causes the need for the three inner *Layouter classes.
419ecf9d1cSIngo Weinhold// For each set of layouts aligned with each other with respect to one
429ecf9d1cSIngo Weinhold// dimension that dimension must be laid out together. The class responsible
439ecf9d1cSIngo Weinhold// is CompoundLayouter; one instance exists per such set. The derived class
449ecf9d1cSIngo Weinhold// VerticalCompoundLayouter is a specialization for the vertical dimension
459ecf9d1cSIngo Weinhold// which additionally takes care of the "height for width" feature. Per layout
469ecf9d1cSIngo Weinhold// a single LocalLayouter exists, which comprises the required glue layout
479ecf9d1cSIngo Weinhold// code and serves as a proxy for the layout, providing service methods
489ecf9d1cSIngo Weinhold// needed by the CompoundLayouter.
499ecf9d1cSIngo Weinhold
509ecf9d1cSIngo Weinhold// TODO: Check for memory leaks!
519ecf9d1cSIngo Weinhold
5299238ef5SStephan Aßmus//#define DEBUG_LAYOUT
539ecf9d1cSIngo Weinhold
549ecf9d1cSIngo Weinhold// CompoundLayouter
55320a5686SIngo Weinholdclass BTwoDimensionalLayout::CompoundLayouter : public BReferenceable {
569ecf9d1cSIngo Weinholdpublic:
57e724b26fSJohn Scipione								CompoundLayouter(orientation orientation);
589ecf9d1cSIngo Weinhold	virtual						~CompoundLayouter();
599ecf9d1cSIngo Weinhold
609ecf9d1cSIngo Weinhold			orientation			Orientation();
619ecf9d1cSIngo Weinhold
629ecf9d1cSIngo Weinhold	virtual	Layouter*			GetLayouter(bool minMax);
639ecf9d1cSIngo Weinhold
649ecf9d1cSIngo Weinhold			LayoutInfo*			GetLayoutInfo();
654aeb7a3cSStephan Aßmus
669ecf9d1cSIngo Weinhold			void				AddLocalLayouter(LocalLayouter* localLayouter);
679ecf9d1cSIngo Weinhold			void				RemoveLocalLayouter(
689ecf9d1cSIngo Weinhold									LocalLayouter* localLayouter);
699ecf9d1cSIngo Weinhold
7080c2bbd8SIngo Weinhold			status_t			AddAlignedLayoutsToArchive(BArchiver* archiver,
7180c2bbd8SIngo Weinhold									LocalLayouter* requestedBy);
7280c2bbd8SIngo Weinhold
739ecf9d1cSIngo Weinhold			void				AbsorbCompoundLayouter(CompoundLayouter* other);
744aeb7a3cSStephan Aßmus
759ecf9d1cSIngo Weinhold	virtual	void				InvalidateLayout();
769ecf9d1cSIngo Weinhold			bool				IsMinMaxValid();
779ecf9d1cSIngo Weinhold			void				ValidateMinMax();
789ecf9d1cSIngo Weinhold			void				Layout(float size, LocalLayouter* localLayouter,
799ecf9d1cSIngo Weinhold									BLayoutContext* context);
809ecf9d1cSIngo Weinhold
819ecf9d1cSIngo Weinholdprotected:
829ecf9d1cSIngo Weinhold	virtual	void				DoLayout(float size,
839ecf9d1cSIngo Weinhold									LocalLayouter* localLayouter,
849ecf9d1cSIngo Weinhold									BLayoutContext* context);
859ecf9d1cSIngo Weinhold
869ecf9d1cSIngo Weinhold			Layouter*			fLayouter;
879ecf9d1cSIngo Weinhold			LayoutInfo*			fLayoutInfo;
889ecf9d1cSIngo Weinhold			orientation			fOrientation;
899ecf9d1cSIngo Weinhold			BList				fLocalLayouters;
909ecf9d1cSIngo Weinhold			BLayoutContext*		fLayoutContext;
919ecf9d1cSIngo Weinhold			float				fLastLayoutSize;
929ecf9d1cSIngo Weinhold
939ecf9d1cSIngo Weinhold			void				_PrepareItems();
949ecf9d1cSIngo Weinhold
959ecf9d1cSIngo Weinhold			int32				_CountElements();
969ecf9d1cSIngo Weinhold			bool				_HasMultiElementItems();
979ecf9d1cSIngo Weinhold
989ecf9d1cSIngo Weinhold			void				_AddConstraints(Layouter* layouter);
999ecf9d1cSIngo Weinhold
1009ecf9d1cSIngo Weinhold			float				_Spacing();
1019ecf9d1cSIngo Weinhold};
1029ecf9d1cSIngo Weinhold
1039ecf9d1cSIngo Weinhold// VerticalCompoundLayouter
1049ecf9d1cSIngo Weinholdclass BTwoDimensionalLayout::VerticalCompoundLayouter
1059ecf9d1cSIngo Weinhold	: public CompoundLayouter, private BLayoutContextListener {
1069ecf9d1cSIngo Weinholdpublic:
1079ecf9d1cSIngo Weinhold								VerticalCompoundLayouter();
1089ecf9d1cSIngo Weinhold
1099ecf9d1cSIngo Weinhold	virtual	Layouter*			GetLayouter(bool minMax);
1109ecf9d1cSIngo Weinhold
1119ecf9d1cSIngo Weinhold	virtual	void				InvalidateLayout();
1129ecf9d1cSIngo Weinhold
1139ecf9d1cSIngo Weinhold			void				InvalidateHeightForWidth();
1144aeb7a3cSStephan Aßmus
1159ecf9d1cSIngo Weinhold			void				InternalGetHeightForWidth(
1169ecf9d1cSIngo Weinhold									LocalLayouter* localLayouter,
1179ecf9d1cSIngo Weinhold									BLayoutContext* context,
1189ecf9d1cSIngo Weinhold									bool realLayout, float* minHeight,
1199ecf9d1cSIngo Weinhold									float* maxHeight, float* preferredHeight);
1209ecf9d1cSIngo Weinhold
1219ecf9d1cSIngo Weinholdprotected:
1229ecf9d1cSIngo Weinhold	virtual	void				DoLayout(float size,
1239ecf9d1cSIngo Weinhold									LocalLayouter* localLayouter,
1249ecf9d1cSIngo Weinhold									BLayoutContext* context);
1259ecf9d1cSIngo Weinhold
1269ecf9d1cSIngo Weinholdprivate:
1279ecf9d1cSIngo Weinhold			Layouter*			fHeightForWidthLayouter;
1289ecf9d1cSIngo Weinhold			float				fCachedMinHeightForWidth;
1299ecf9d1cSIngo Weinhold			float				fCachedMaxHeightForWidth;
1309ecf9d1cSIngo Weinhold			float				fCachedPreferredHeightForWidth;
1319ecf9d1cSIngo Weinhold			BLayoutContext*		fHeightForWidthLayoutContext;
1329ecf9d1cSIngo Weinhold
1339ecf9d1cSIngo Weinhold			bool				_HasHeightForWidth();
1349ecf9d1cSIngo Weinhold
1359ecf9d1cSIngo Weinhold			bool				_SetHeightForWidthLayoutContext(
1369ecf9d1cSIngo Weinhold									BLayoutContext* context);
1379ecf9d1cSIngo Weinhold
1389ecf9d1cSIngo Weinhold	// BLayoutContextListener
1399ecf9d1cSIngo Weinhold	virtual	void				LayoutContextLeft(BLayoutContext* context);
1409ecf9d1cSIngo Weinhold};
1419ecf9d1cSIngo Weinhold
1429ecf9d1cSIngo Weinhold// LocalLayouter
1439ecf9d1cSIngo Weinholdclass BTwoDimensionalLayout::LocalLayouter : private BLayoutContextListener {
1449ecf9d1cSIngo Weinholdpublic:
1459ecf9d1cSIngo Weinhold								LocalLayouter(BTwoDimensionalLayout* layout);
146320a5686SIngo Weinhold								~LocalLayouter();
1479ecf9d1cSIngo Weinhold
1489ecf9d1cSIngo Weinhold	// interface for the BTwoDimensionalLayout class
1499ecf9d1cSIngo Weinhold
1509ecf9d1cSIngo Weinhold			BSize				MinSize();
1519ecf9d1cSIngo Weinhold			BSize				MaxSize();
1529ecf9d1cSIngo Weinhold			BSize				PreferredSize();
1539ecf9d1cSIngo Weinhold
1549ecf9d1cSIngo Weinhold			void				InvalidateLayout();
1559ecf9d1cSIngo Weinhold			void				Layout(BSize size);
1569ecf9d1cSIngo Weinhold
1579ecf9d1cSIngo Weinhold			BRect				ItemFrame(Dimensions itemDimensions);
1584aeb7a3cSStephan Aßmus
1599ecf9d1cSIngo Weinhold			void				ValidateMinMax();
1609ecf9d1cSIngo Weinhold
1619ecf9d1cSIngo Weinhold			void				DoHorizontalLayout(float width);
1629ecf9d1cSIngo Weinhold
1639ecf9d1cSIngo Weinhold			void				InternalGetHeightForWidth(float width,
1649ecf9d1cSIngo Weinhold									float* minHeight, float* maxHeight,
1659ecf9d1cSIngo Weinhold									float* preferredHeight);
1669ecf9d1cSIngo Weinhold
1679ecf9d1cSIngo Weinhold			void				AlignWith(LocalLayouter* other,
168e724b26fSJohn Scipione									orientation orientation);
1694aeb7a3cSStephan Aßmus
17080c2bbd8SIngo Weinhold	// Archiving stuff
17180c2bbd8SIngo Weinhold			status_t			AddAlignedLayoutsToArchive(BArchiver* archiver);
17280c2bbd8SIngo Weinhold			status_t			AddOwnerToArchive(BArchiver* archiver,
17380c2bbd8SIngo Weinhold									CompoundLayouter* requestedBy,
17480c2bbd8SIngo Weinhold									bool& _wasAvailable);
17580c2bbd8SIngo Weinhold			status_t			AlignLayoutsFromArchive(BUnarchiver* unarchiver,
17680c2bbd8SIngo Weinhold									orientation posture);
17780c2bbd8SIngo Weinhold
1789ecf9d1cSIngo Weinhold
1799ecf9d1cSIngo Weinhold	// interface for the compound layout context
1809ecf9d1cSIngo Weinhold
1819ecf9d1cSIngo Weinhold			void				PrepareItems(
1829ecf9d1cSIngo Weinhold									CompoundLayouter* compoundLayouter);
1839ecf9d1cSIngo Weinhold			int32				CountElements(
1849ecf9d1cSIngo Weinhold									CompoundLayouter* compoundLayouter);
1859ecf9d1cSIngo Weinhold			bool				HasMultiElementItems(
1869ecf9d1cSIngo Weinhold									CompoundLayouter* compoundLayouter);
1879ecf9d1cSIngo Weinhold
1889ecf9d1cSIngo Weinhold			void				AddConstraints(
1899ecf9d1cSIngo Weinhold									CompoundLayouter* compoundLayouter,
1909ecf9d1cSIngo Weinhold									Layouter* layouter);
1919ecf9d1cSIngo Weinhold
1929ecf9d1cSIngo Weinhold			float				Spacing(CompoundLayouter* compoundLayouter);
1939ecf9d1cSIngo Weinhold
1949ecf9d1cSIngo Weinhold			bool				HasHeightForWidth();
1959ecf9d1cSIngo Weinhold
1969ecf9d1cSIngo Weinhold			bool				AddHeightForWidthConstraints(
1979ecf9d1cSIngo Weinhold									VerticalCompoundLayouter* compoundLayouter,
1989ecf9d1cSIngo Weinhold									Layouter* layouter,
1999ecf9d1cSIngo Weinhold									BLayoutContext* context);
2009ecf9d1cSIngo Weinhold			void				SetHeightForWidthConstraintsAdded(bool added);
2014aeb7a3cSStephan Aßmus
2029ecf9d1cSIngo Weinhold			void				SetCompoundLayouter(
2039ecf9d1cSIngo Weinhold									CompoundLayouter* compoundLayouter,
204e724b26fSJohn Scipione									orientation orientation);
2059ecf9d1cSIngo Weinhold
2069ecf9d1cSIngo Weinhold			void				InternalInvalidateLayout(
2079ecf9d1cSIngo Weinhold									CompoundLayouter* compoundLayouter);
2084aeb7a3cSStephan Aßmus
2099ecf9d1cSIngo Weinhold	// implementation private
2109ecf9d1cSIngo Weinholdprivate:
21180c2bbd8SIngo Weinhold			BTwoDimensionalLayout* fLayout;
2129ecf9d1cSIngo Weinhold			CompoundLayouter*	fHLayouter;
2139ecf9d1cSIngo Weinhold			VerticalCompoundLayouter* fVLayouter;
2149ecf9d1cSIngo Weinhold			BList				fHeightForWidthItems;
2159ecf9d1cSIngo Weinhold
2169ecf9d1cSIngo Weinhold	// active layout context when doing last horizontal layout
2179ecf9d1cSIngo Weinhold			BLayoutContext*		fHorizontalLayoutContext;
2189ecf9d1cSIngo Weinhold			float				fHorizontalLayoutWidth;
2199ecf9d1cSIngo Weinhold			bool				fHeightForWidthConstraintsAdded;
2204aeb7a3cSStephan Aßmus
2219ecf9d1cSIngo Weinhold			void				_SetHorizontalLayoutContext(
2229ecf9d1cSIngo Weinhold									BLayoutContext* context, float width);
2239ecf9d1cSIngo Weinhold
2249ecf9d1cSIngo Weinhold	// BLayoutContextListener
2259ecf9d1cSIngo Weinhold	virtual	void				LayoutContextLeft(BLayoutContext* context);
2269ecf9d1cSIngo Weinhold};
2279ecf9d1cSIngo Weinhold
2289ecf9d1cSIngo Weinhold
2299ecf9d1cSIngo Weinhold// #pragma mark -
2309ecf9d1cSIngo Weinhold
23180c2bbd8SIngo Weinhold// archiving constants
23280c2bbd8SIngo Weinholdnamespace {
2334a254e4dSAlex Wilson	const char* const kHAlignedLayoutField = "BTwoDimensionalLayout:"
2344a254e4dSAlex Wilson		"halignedlayout";
2354a254e4dSAlex Wilson	const char* const kVAlignedLayoutField = "BTwoDimensionalLayout:"
2364a254e4dSAlex Wilson		"valignedlayout";
2374a254e4dSAlex Wilson	const char* const kInsetsField = "BTwoDimensionalLayout:insets";
2384a254e4dSAlex Wilson	const char* const kSpacingField = "BTwoDimensionalLayout:spacing";
2394a254e4dSAlex Wilson		// kSpacingField = {fHSpacing, fVSpacing}
24080c2bbd8SIngo Weinhold}
24180c2bbd8SIngo Weinhold
2429ecf9d1cSIngo Weinhold
2439ecf9d1cSIngo WeinholdBTwoDimensionalLayout::BTwoDimensionalLayout()
24407dbd4d5SAxel Dörfler	:
24507dbd4d5SAxel Dörfler	fLeftInset(0),
24607dbd4d5SAxel Dörfler	fRightInset(0),
24707dbd4d5SAxel Dörfler	fTopInset(0),
24807dbd4d5SAxel Dörfler	fBottomInset(0),
24907dbd4d5SAxel Dörfler	fHSpacing(0),
25007dbd4d5SAxel Dörfler	fVSpacing(0),
25107dbd4d5SAxel Dörfler	fLocalLayouter(new LocalLayouter(this))
2529ecf9d1cSIngo Weinhold{
2539ecf9d1cSIngo Weinhold}
2549ecf9d1cSIngo Weinhold
25507dbd4d5SAxel Dörfler
25680c2bbd8SIngo WeinholdBTwoDimensionalLayout::BTwoDimensionalLayout(BMessage* from)
25780c2bbd8SIngo Weinhold	:
2581d6c7b6cSAlex Wilson	BAbstractLayout(from),
25980c2bbd8SIngo Weinhold	fLeftInset(0),
26080c2bbd8SIngo Weinhold	fRightInset(0),
26180c2bbd8SIngo Weinhold	fTopInset(0),
26280c2bbd8SIngo Weinhold	fBottomInset(0),
26380c2bbd8SIngo Weinhold	fHSpacing(0),
26480c2bbd8SIngo Weinhold	fVSpacing(0),
26580c2bbd8SIngo Weinhold	fLocalLayouter(new LocalLayouter(this))
26680c2bbd8SIngo Weinhold{
2674a254e4dSAlex Wilson	BRect insets;
2684a254e4dSAlex Wilson	from->FindRect(kInsetsField, &insets);
2694a254e4dSAlex Wilson	SetInsets(insets.left, insets.top, insets.right, insets.bottom);
2704a254e4dSAlex Wilson
2714a254e4dSAlex Wilson	from->FindFloat(kSpacingField, 0, &fHSpacing);
2724a254e4dSAlex Wilson	from->FindFloat(kSpacingField, 1, &fVSpacing);
27380c2bbd8SIngo Weinhold}
27480c2bbd8SIngo Weinhold
27580c2bbd8SIngo Weinhold
2769ecf9d1cSIngo WeinholdBTwoDimensionalLayout::~BTwoDimensionalLayout()
2779ecf9d1cSIngo Weinhold{
2789ecf9d1cSIngo Weinhold	delete fLocalLayouter;
2799ecf9d1cSIngo Weinhold}
2809ecf9d1cSIngo Weinhold
28107dbd4d5SAxel Dörfler
2829ecf9d1cSIngo Weinholdvoid
2839ecf9d1cSIngo WeinholdBTwoDimensionalLayout::SetInsets(float left, float top, float right,
2849ecf9d1cSIngo Weinhold	float bottom)
2859ecf9d1cSIngo Weinhold{
2866648dd3cSAlex Wilson	fLeftInset = BControlLook::ComposeSpacing(left);
2876648dd3cSAlex Wilson	fTopInset = BControlLook::ComposeSpacing(top);
2886648dd3cSAlex Wilson	fRightInset = BControlLook::ComposeSpacing(right);
2896648dd3cSAlex Wilson	fBottomInset = BControlLook::ComposeSpacing(bottom);
2909ecf9d1cSIngo Weinhold
2919ecf9d1cSIngo Weinhold	InvalidateLayout();
2929ecf9d1cSIngo Weinhold}
2939ecf9d1cSIngo Weinhold
29407dbd4d5SAxel Dörfler
295813147dfSAlex Wilsonvoid
296813147dfSAlex WilsonBTwoDimensionalLayout::SetInsets(float horizontal, float vertical)
297813147dfSAlex Wilson{
298813147dfSAlex Wilson	fLeftInset = BControlLook::ComposeSpacing(horizontal);
299813147dfSAlex Wilson	fRightInset = fLeftInset;
300813147dfSAlex Wilson
301813147dfSAlex Wilson	fTopInset = BControlLook::ComposeSpacing(vertical);
302813147dfSAlex Wilson	fBottomInset = fTopInset;
303813147dfSAlex Wilson
304813147dfSAlex Wilson	InvalidateLayout();
305813147dfSAlex Wilson}
306813147dfSAlex Wilson
307813147dfSAlex Wilson
308813147dfSAlex Wilsonvoid
309813147dfSAlex WilsonBTwoDimensionalLayout::SetInsets(float insets)
310813147dfSAlex Wilson{
311813147dfSAlex Wilson	fLeftInset = BControlLook::ComposeSpacing(insets);
312813147dfSAlex Wilson	fRightInset = fLeftInset;
313813147dfSAlex Wilson	fTopInset = fLeftInset;
314813147dfSAlex Wilson	fBottomInset = fLeftInset;
315813147dfSAlex Wilson
316813147dfSAlex Wilson	InvalidateLayout();
317813147dfSAlex Wilson}
318813147dfSAlex Wilson
319813147dfSAlex Wilson
3209ecf9d1cSIngo Weinholdvoid
3219ecf9d1cSIngo WeinholdBTwoDimensionalLayout::GetInsets(float* left, float* top, float* right,
3224aeb7a3cSStephan Aßmus	float* bottom) const
3239ecf9d1cSIngo Weinhold{
3249ecf9d1cSIngo Weinhold	if (left)
3259ecf9d1cSIngo Weinhold		*left = fLeftInset;
3269ecf9d1cSIngo Weinhold	if (top)
3279ecf9d1cSIngo Weinhold		*top = fTopInset;
3289ecf9d1cSIngo Weinhold	if (right)
3299ecf9d1cSIngo Weinhold		*right = fRightInset;
3309ecf9d1cSIngo Weinhold	if (bottom)
3319ecf9d1cSIngo Weinhold		*bottom = fBottomInset;
3329ecf9d1cSIngo Weinhold}
3339ecf9d1cSIngo Weinhold
33407dbd4d5SAxel Dörfler
3359ecf9d1cSIngo Weinholdvoid
3369ecf9d1cSIngo WeinholdBTwoDimensionalLayout::AlignLayoutWith(BTwoDimensionalLayout* other,
337e724b26fSJohn Scipione	orientation orientation)
3389ecf9d1cSIngo Weinhold{
3399ecf9d1cSIngo Weinhold	if (!other || other == this)
3409ecf9d1cSIngo Weinhold		return;
3419ecf9d1cSIngo Weinhold
3429ecf9d1cSIngo Weinhold	fLocalLayouter->AlignWith(other->fLocalLayouter, orientation);
3439ecf9d1cSIngo Weinhold
3449ecf9d1cSIngo Weinhold	InvalidateLayout();
3459ecf9d1cSIngo Weinhold}
3469ecf9d1cSIngo Weinhold
34707dbd4d5SAxel Dörfler
3489ecf9d1cSIngo WeinholdBSize
3491d6c7b6cSAlex WilsonBTwoDimensionalLayout::BaseMinSize()
3509ecf9d1cSIngo Weinhold{
3519ecf9d1cSIngo Weinhold	_ValidateMinMax();
3529ecf9d1cSIngo Weinhold	return AddInsets(fLocalLayouter->MinSize());
3539ecf9d1cSIngo Weinhold}
3549ecf9d1cSIngo Weinhold
35507dbd4d5SAxel Dörfler
3569ecf9d1cSIngo WeinholdBSize
3571d6c7b6cSAlex WilsonBTwoDimensionalLayout::BaseMaxSize()
3589ecf9d1cSIngo Weinhold{
3599ecf9d1cSIngo Weinhold	_ValidateMinMax();
3609ecf9d1cSIngo Weinhold	return AddInsets(fLocalLayouter->MaxSize());
3619ecf9d1cSIngo Weinhold}
3629ecf9d1cSIngo Weinhold
36307dbd4d5SAxel Dörfler
3649ecf9d1cSIngo WeinholdBSize
3651d6c7b6cSAlex WilsonBTwoDimensionalLayout::BasePreferredSize()
3669ecf9d1cSIngo Weinhold{
3679ecf9d1cSIngo Weinhold	_ValidateMinMax();
3689ecf9d1cSIngo Weinhold	return AddInsets(fLocalLayouter->PreferredSize());
3699ecf9d1cSIngo Weinhold}
3709ecf9d1cSIngo Weinhold
37107dbd4d5SAxel Dörfler
3729ecf9d1cSIngo WeinholdBAlignment
3731d6c7b6cSAlex WilsonBTwoDimensionalLayout::BaseAlignment()
3749ecf9d1cSIngo Weinhold{
3751d6c7b6cSAlex Wilson	return BAbstractLayout::BaseAlignment();
3769ecf9d1cSIngo Weinhold}
3779ecf9d1cSIngo Weinhold
37807dbd4d5SAxel Dörfler
3799ecf9d1cSIngo Weinholdbool
3809ecf9d1cSIngo WeinholdBTwoDimensionalLayout::HasHeightForWidth()
3819ecf9d1cSIngo Weinhold{
3829ecf9d1cSIngo Weinhold	_ValidateMinMax();
3839ecf9d1cSIngo Weinhold	return fLocalLayouter->HasHeightForWidth();
3849ecf9d1cSIngo Weinhold}
3859ecf9d1cSIngo Weinhold
38607dbd4d5SAxel Dörfler
3879ecf9d1cSIngo Weinholdvoid
3889ecf9d1cSIngo WeinholdBTwoDimensionalLayout::GetHeightForWidth(float width, float* min, float* max,
3899ecf9d1cSIngo Weinhold	float* preferred)
3909ecf9d1cSIngo Weinhold{
3919ecf9d1cSIngo Weinhold	if (!HasHeightForWidth())
3929ecf9d1cSIngo Weinhold		return;
3939ecf9d1cSIngo Weinhold
3949ecf9d1cSIngo Weinhold	float outerSpacing = fLeftInset + fRightInset - 1;
3959ecf9d1cSIngo Weinhold	fLocalLayouter->InternalGetHeightForWidth(BLayoutUtils::SubtractDistances(
3969ecf9d1cSIngo Weinhold		width, outerSpacing), min, max, preferred);
3979ecf9d1cSIngo Weinhold	AddInsets(min, max, preferred);
3989ecf9d1cSIngo Weinhold}
3999ecf9d1cSIngo Weinhold
40007dbd4d5SAxel Dörfler
4019ecf9d1cSIngo Weinholdvoid
4021d6c7b6cSAlex WilsonBTwoDimensionalLayout::SetFrame(BRect frame)
4039ecf9d1cSIngo Weinhold{
4041d6c7b6cSAlex Wilson	BAbstractLayout::SetFrame(frame);
4059ecf9d1cSIngo Weinhold}
4069ecf9d1cSIngo Weinhold
40707dbd4d5SAxel Dörfler
40880c2bbd8SIngo Weinholdstatus_t
40980c2bbd8SIngo WeinholdBTwoDimensionalLayout::Archive(BMessage* into, bool deep) const
41080c2bbd8SIngo Weinhold{
41180c2bbd8SIngo Weinhold	BArchiver archiver(into);
4121d6c7b6cSAlex Wilson	status_t err = BAbstractLayout::Archive(into, deep);
41380c2bbd8SIngo Weinhold
4144a254e4dSAlex Wilson	if (err == B_OK) {
4154a254e4dSAlex Wilson		BRect insets(fLeftInset, fTopInset, fRightInset, fBottomInset);
4164a254e4dSAlex Wilson		err = into->AddRect(kInsetsField, insets);
4174a254e4dSAlex Wilson	}
41880c2bbd8SIngo Weinhold
41980c2bbd8SIngo Weinhold	if (err == B_OK)
4204a254e4dSAlex Wilson		err = into->AddFloat(kSpacingField, fHSpacing);
42180c2bbd8SIngo Weinhold
42280c2bbd8SIngo Weinhold	if (err == B_OK)
4234a254e4dSAlex Wilson		err = into->AddFloat(kSpacingField, fVSpacing);
42480c2bbd8SIngo Weinhold
42580c2bbd8SIngo Weinhold	return archiver.Finish(err);
42680c2bbd8SIngo Weinhold}
42780c2bbd8SIngo Weinhold
42880c2bbd8SIngo Weinhold
42980c2bbd8SIngo Weinholdstatus_t
43080c2bbd8SIngo WeinholdBTwoDimensionalLayout::AllArchived(BMessage* into) const
43180c2bbd8SIngo Weinhold{
43280c2bbd8SIngo Weinhold	BArchiver archiver(into);
43380c2bbd8SIngo Weinhold
43480c2bbd8SIngo Weinhold	status_t err = BLayout::AllArchived(into);
43580c2bbd8SIngo Weinhold	if (err == B_OK)
43680c2bbd8SIngo Weinhold		err = fLocalLayouter->AddAlignedLayoutsToArchive(&archiver);
43780c2bbd8SIngo Weinhold	return err;
43880c2bbd8SIngo Weinhold}
43980c2bbd8SIngo Weinhold
44080c2bbd8SIngo Weinhold
44180c2bbd8SIngo Weinholdstatus_t
44280c2bbd8SIngo WeinholdBTwoDimensionalLayout::AllUnarchived(const BMessage* from)
44380c2bbd8SIngo Weinhold{
44480c2bbd8SIngo Weinhold	status_t err = BLayout::AllUnarchived(from);
44580c2bbd8SIngo Weinhold	if (err != B_OK)
44680c2bbd8SIngo Weinhold		return err;
44780c2bbd8SIngo Weinhold
44880c2bbd8SIngo Weinhold	BUnarchiver unarchiver(from);
44980c2bbd8SIngo Weinhold	err = fLocalLayouter->AlignLayoutsFromArchive(&unarchiver, B_HORIZONTAL);
45080c2bbd8SIngo Weinhold	if (err == B_OK)
45180c2bbd8SIngo Weinhold		err = fLocalLayouter->AlignLayoutsFromArchive(&unarchiver, B_VERTICAL);
45280c2bbd8SIngo Weinhold
45380c2bbd8SIngo Weinhold	return err;
45480c2bbd8SIngo Weinhold}
45580c2bbd8SIngo Weinhold
45680c2bbd8SIngo Weinhold
45753617d36SAlex Wilsonstatus_t
45853617d36SAlex WilsonBTwoDimensionalLayout::ItemArchived(BMessage* into, BLayoutItem* item,
45953617d36SAlex Wilson	int32 index) const
46053617d36SAlex Wilson{
46153617d36SAlex Wilson	return BAbstractLayout::ItemArchived(into, item, index);
46253617d36SAlex Wilson}
46353617d36SAlex Wilson
46453617d36SAlex Wilson
46553617d36SAlex Wilsonstatus_t
46653617d36SAlex WilsonBTwoDimensionalLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
46753617d36SAlex Wilson	int32 index)
46853617d36SAlex Wilson{
46953617d36SAlex Wilson	return BAbstractLayout::ItemUnarchived(from, item, index);
47053617d36SAlex Wilson}
47153617d36SAlex Wilson
47253617d36SAlex Wilson
47353617d36SAlex Wilson
47453617d36SAlex Wilson
475b38ea98fSAlex Wilsonvoid
476b38ea98fSAlex WilsonBTwoDimensionalLayout::LayoutInvalidated(bool children)
477b38ea98fSAlex Wilson{
478b38ea98fSAlex Wilson	fLocalLayouter->InvalidateLayout();
479b38ea98fSAlex Wilson}
480b38ea98fSAlex Wilson
481b38ea98fSAlex Wilson
4821d6c7b6cSAlex Wilsonvoid
4834e0131f5SAlex WilsonBTwoDimensionalLayout::DoLayout()
4841d6c7b6cSAlex Wilson{
4851d6c7b6cSAlex Wilson	_ValidateMinMax();
4861d6c7b6cSAlex Wilson
4871d6c7b6cSAlex Wilson	// layout the horizontal/vertical elements
4881d6c7b6cSAlex Wilson	BSize size(SubtractInsets(LayoutArea().Size()));
4891d6c7b6cSAlex Wilson
4901d6c7b6cSAlex Wilson#ifdef DEBUG_LAYOUT
4911d6c7b6cSAlex Wilsonprintf("BTwoDimensionalLayout::DerivedLayoutItems(): view: %p"
4921d6c7b6cSAlex Wilson	" size: (%.1f, %.1f)\n", View(), size.Width(), size.Height());
4931d6c7b6cSAlex Wilson#endif
4941d6c7b6cSAlex Wilson
4951d6c7b6cSAlex Wilson	fLocalLayouter->Layout(size);
4961d6c7b6cSAlex Wilson
4971d6c7b6cSAlex Wilson	// layout the items
4981d6c7b6cSAlex Wilson	BPoint itemOffset(LayoutArea().LeftTop());
4991d6c7b6cSAlex Wilson	int itemCount = CountItems();
5001d6c7b6cSAlex Wilson	for (int i = 0; i < itemCount; i++) {
5011d6c7b6cSAlex Wilson		BLayoutItem* item = ItemAt(i);
5021d6c7b6cSAlex Wilson		if (item->IsVisible()) {
5031d6c7b6cSAlex Wilson			Dimensions itemDimensions;
5041d6c7b6cSAlex Wilson			GetItemDimensions(item, &itemDimensions);
5051d6c7b6cSAlex Wilson			BRect frame = fLocalLayouter->ItemFrame(itemDimensions);
5061d6c7b6cSAlex Wilson			frame.left += fLeftInset;
5071d6c7b6cSAlex Wilson			frame.top += fTopInset;
5081d6c7b6cSAlex Wilson			frame.right += fLeftInset;
5091d6c7b6cSAlex Wilson			frame.bottom += fTopInset;
5101d6c7b6cSAlex Wilson			frame.OffsetBy(itemOffset);
5111d6c7b6cSAlex Wilson{
5121d6c7b6cSAlex Wilson#ifdef DEBUG_LAYOUT
5131d6c7b6cSAlex Wilsonprintf("  frame for item %2d (view: %p): ", i, item->View());
5141d6c7b6cSAlex Wilsonframe.PrintToStream();
5151d6c7b6cSAlex Wilson#endif
5161d6c7b6cSAlex Wilson//BSize min(item->MinSize());
5171d6c7b6cSAlex Wilson//BSize max(item->MaxSize());
5181d6c7b6cSAlex Wilson//printf("    min: (%.1f, %.1f), max: (%.1f, %.1f)\n", min.width, min.height,
5191d6c7b6cSAlex Wilson//	max.width, max.height);
5201d6c7b6cSAlex Wilson//if (item->HasHeightForWidth()) {
5211d6c7b6cSAlex Wilson//float minHeight, maxHeight, preferredHeight;
5221d6c7b6cSAlex Wilson//item->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
5231d6c7b6cSAlex Wilson//	&preferredHeight);
5241d6c7b6cSAlex Wilson//printf("    hfw: min: %.1f, max: %.1f, pref: %.1f\n", minHeight, maxHeight,
5251d6c7b6cSAlex Wilson//	preferredHeight);
5261d6c7b6cSAlex Wilson//}
5271d6c7b6cSAlex Wilson}
5281d6c7b6cSAlex Wilson
5291d6c7b6cSAlex Wilson			item->AlignInFrame(frame);
5301d6c7b6cSAlex Wilson		}
5311d6c7b6cSAlex Wilson//else
5321d6c7b6cSAlex Wilson//printf("  item %2d not visible", i);
5331d6c7b6cSAlex Wilson	}
5341d6c7b6cSAlex Wilson}
5351d6c7b6cSAlex Wilson
5361d6c7b6cSAlex Wilson
5379ecf9d1cSIngo WeinholdBSize
5389ecf9d1cSIngo WeinholdBTwoDimensionalLayout::AddInsets(BSize size)
5399ecf9d1cSIngo Weinhold{
5409ecf9d1cSIngo Weinhold	size.width = BLayoutUtils::AddDistances(size.width,
5419ecf9d1cSIngo Weinhold		fLeftInset + fRightInset - 1);
5429ecf9d1cSIngo Weinhold	size.height = BLayoutUtils::AddDistances(size.height,
5439ecf9d1cSIngo Weinhold		fTopInset + fBottomInset - 1);
5449ecf9d1cSIngo Weinhold	return size;
5459ecf9d1cSIngo Weinhold}
5469ecf9d1cSIngo Weinhold
54707dbd4d5SAxel Dörfler
5489ecf9d1cSIngo Weinholdvoid
5499ecf9d1cSIngo WeinholdBTwoDimensionalLayout::AddInsets(float* minHeight, float* maxHeight,
5509ecf9d1cSIngo Weinhold	float* preferredHeight)
5519ecf9d1cSIngo Weinhold{
5529ecf9d1cSIngo Weinhold	float insets = fTopInset + fBottomInset - 1;
5539ecf9d1cSIngo Weinhold	if (minHeight)
5549ecf9d1cSIngo Weinhold		*minHeight = BLayoutUtils::AddDistances(*minHeight, insets);
5559ecf9d1cSIngo Weinhold	if (maxHeight)
5569ecf9d1cSIngo Weinhold		*maxHeight = BLayoutUtils::AddDistances(*maxHeight, insets);
5579ecf9d1cSIngo Weinhold	if (preferredHeight)
5589ecf9d1cSIngo Weinhold		*preferredHeight = BLayoutUtils::AddDistances(*preferredHeight, insets);
5599ecf9d1cSIngo Weinhold}
5609ecf9d1cSIngo Weinhold
56107dbd4d5SAxel Dörfler
5629ecf9d1cSIngo WeinholdBSize
5639ecf9d1cSIngo WeinholdBTwoDimensionalLayout::SubtractInsets(BSize size)
5649ecf9d1cSIngo Weinhold{
5659ecf9d1cSIngo Weinhold	size.width = BLayoutUtils::SubtractDistances(size.width,
5669ecf9d1cSIngo Weinhold		fLeftInset + fRightInset - 1);
5679ecf9d1cSIngo Weinhold	size.height = BLayoutUtils::SubtractDistances(size.height,
5689ecf9d1cSIngo Weinhold		fTopInset + fBottomInset - 1);
5699ecf9d1cSIngo Weinhold	return size;
5709ecf9d1cSIngo Weinhold}
5719ecf9d1cSIngo Weinhold
57207dbd4d5SAxel Dörfler
5739ecf9d1cSIngo Weinholdvoid
574e724b26fSJohn ScipioneBTwoDimensionalLayout::PrepareItems(orientation orientation)
5759ecf9d1cSIngo Weinhold{
5769ecf9d1cSIngo Weinhold}
5779ecf9d1cSIngo Weinhold
57807dbd4d5SAxel Dörfler
5799ecf9d1cSIngo Weinholdbool
5809ecf9d1cSIngo WeinholdBTwoDimensionalLayout::HasMultiColumnItems()
5819ecf9d1cSIngo Weinhold{
5829ecf9d1cSIngo Weinhold	return false;
5839ecf9d1cSIngo Weinhold}
5849ecf9d1cSIngo Weinhold
58507dbd4d5SAxel Dörfler
5869ecf9d1cSIngo Weinholdbool
5879ecf9d1cSIngo WeinholdBTwoDimensionalLayout::HasMultiRowItems()
5889ecf9d1cSIngo Weinhold{
5899ecf9d1cSIngo Weinhold	return false;
5909ecf9d1cSIngo Weinhold}
5919ecf9d1cSIngo Weinhold
59207dbd4d5SAxel Dörfler
5939ecf9d1cSIngo Weinholdvoid
5949ecf9d1cSIngo WeinholdBTwoDimensionalLayout::_ValidateMinMax()
5959ecf9d1cSIngo Weinhold{
5969ecf9d1cSIngo Weinhold	fLocalLayouter->ValidateMinMax();
5979ecf9d1cSIngo Weinhold}
5989ecf9d1cSIngo Weinhold
5999ecf9d1cSIngo Weinhold
6009ecf9d1cSIngo Weinhold// #pragma mark - CompoundLayouter
6019ecf9d1cSIngo Weinhold
60207dbd4d5SAxel Dörfler
6039ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::CompoundLayouter(
604e724b26fSJohn Scipione	orientation orientation)
60507dbd4d5SAxel Dörfler	:
60607dbd4d5SAxel Dörfler	fLayouter(NULL),
60707dbd4d5SAxel Dörfler	fLayoutInfo(NULL),
60807dbd4d5SAxel Dörfler	fOrientation(orientation),
60907dbd4d5SAxel Dörfler	fLocalLayouters(10),
61007dbd4d5SAxel Dörfler	fLayoutContext(NULL),
61107dbd4d5SAxel Dörfler	fLastLayoutSize(-1)
6129ecf9d1cSIngo Weinhold{
6139ecf9d1cSIngo Weinhold}
6149ecf9d1cSIngo Weinhold
61507dbd4d5SAxel Dörfler
6169ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::~CompoundLayouter()
6179ecf9d1cSIngo Weinhold{
61832e627a7SMichael Lotz	delete fLayouter;
61932e627a7SMichael Lotz	delete fLayoutInfo;
6209ecf9d1cSIngo Weinhold}
6219ecf9d1cSIngo Weinhold
62207dbd4d5SAxel Dörfler
6239ecf9d1cSIngo Weinholdorientation
6249ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::Orientation()
6259ecf9d1cSIngo Weinhold{
6269ecf9d1cSIngo Weinhold	return fOrientation;
6279ecf9d1cSIngo Weinhold}
6289ecf9d1cSIngo Weinhold
62907dbd4d5SAxel Dörfler
6309ecf9d1cSIngo WeinholdLayouter*
6319ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::GetLayouter(bool minMax)
6329ecf9d1cSIngo Weinhold{
6339ecf9d1cSIngo Weinhold	return fLayouter;
6349ecf9d1cSIngo Weinhold}
6359ecf9d1cSIngo Weinhold
63607dbd4d5SAxel Dörfler
6379ecf9d1cSIngo WeinholdLayoutInfo*
6389ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::GetLayoutInfo()
6399ecf9d1cSIngo Weinhold{
6409ecf9d1cSIngo Weinhold	return fLayoutInfo;
6419ecf9d1cSIngo Weinhold}
6429ecf9d1cSIngo Weinhold
64307dbd4d5SAxel Dörfler
6449ecf9d1cSIngo Weinholdvoid
6459ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::AddLocalLayouter(
6469ecf9d1cSIngo Weinhold	LocalLayouter* localLayouter)
6479ecf9d1cSIngo Weinhold{
6489ecf9d1cSIngo Weinhold	if (localLayouter) {
6499ecf9d1cSIngo Weinhold		if (!fLocalLayouters.HasItem(localLayouter)) {
6509ecf9d1cSIngo Weinhold			fLocalLayouters.AddItem(localLayouter);
6519ecf9d1cSIngo Weinhold			InvalidateLayout();
6529ecf9d1cSIngo Weinhold		}
6539ecf9d1cSIngo Weinhold	}
6549ecf9d1cSIngo Weinhold}
6559ecf9d1cSIngo Weinhold
65607dbd4d5SAxel Dörfler
6579ecf9d1cSIngo Weinholdvoid
6589ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::RemoveLocalLayouter(
6599ecf9d1cSIngo Weinhold	LocalLayouter* localLayouter)
6609ecf9d1cSIngo Weinhold{
6619ecf9d1cSIngo Weinhold	if (fLocalLayouters.RemoveItem(localLayouter))
6629ecf9d1cSIngo Weinhold		InvalidateLayout();
6639ecf9d1cSIngo Weinhold}
6649ecf9d1cSIngo Weinhold
66507dbd4d5SAxel Dörfler
66680c2bbd8SIngo Weinholdstatus_t
66780c2bbd8SIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::AddAlignedLayoutsToArchive(
66880c2bbd8SIngo Weinhold	BArchiver* archiver, LocalLayouter* requestedBy)
66980c2bbd8SIngo Weinhold{
67080c2bbd8SIngo Weinhold	// The LocalLayouter* that really owns us is at index 0, layouts
67180c2bbd8SIngo Weinhold	// at other indices are aligned to this one.
67280c2bbd8SIngo Weinhold	if (requestedBy != fLocalLayouters.ItemAt(0))
67380c2bbd8SIngo Weinhold		return B_OK;
67480c2bbd8SIngo Weinhold
67580c2bbd8SIngo Weinhold	status_t err;
67680c2bbd8SIngo Weinhold	for (int32 i = fLocalLayouters.CountItems() - 1; i > 0; i--) {
67780c2bbd8SIngo Weinhold		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
67880c2bbd8SIngo Weinhold
67980c2bbd8SIngo Weinhold		bool wasAvailable;
68080c2bbd8SIngo Weinhold		err = layouter->AddOwnerToArchive(archiver, this, wasAvailable);
68180c2bbd8SIngo Weinhold		if (err != B_OK && wasAvailable)
68280c2bbd8SIngo Weinhold			return err;
68380c2bbd8SIngo Weinhold	}
68480c2bbd8SIngo Weinhold	return B_OK;
68580c2bbd8SIngo Weinhold}
68680c2bbd8SIngo Weinhold
68780c2bbd8SIngo Weinhold
6889ecf9d1cSIngo Weinholdvoid
6899ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::AbsorbCompoundLayouter(
6909ecf9d1cSIngo Weinhold	CompoundLayouter* other)
6919ecf9d1cSIngo Weinhold{
6929ecf9d1cSIngo Weinhold	if (other == this)
6939ecf9d1cSIngo Weinhold		return;
6949ecf9d1cSIngo Weinhold
6959ecf9d1cSIngo Weinhold	int32 count = other->fLocalLayouters.CountItems();
6961bbf3b88SAdrien Destugues	for (int32 i = count - 1; i >= 0; i--) {
6979ecf9d1cSIngo Weinhold		LocalLayouter* layouter
6989ecf9d1cSIngo Weinhold			= (LocalLayouter*)other->fLocalLayouters.ItemAt(i);
6999ecf9d1cSIngo Weinhold		AddLocalLayouter(layouter);
7009ecf9d1cSIngo Weinhold		layouter->SetCompoundLayouter(this, fOrientation);
7019ecf9d1cSIngo Weinhold	}
7024aeb7a3cSStephan Aßmus
7039ecf9d1cSIngo Weinhold	InvalidateLayout();
7049ecf9d1cSIngo Weinhold}
7059ecf9d1cSIngo Weinhold
70607dbd4d5SAxel Dörfler
7079ecf9d1cSIngo Weinholdvoid
7089ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::InvalidateLayout()
7099ecf9d1cSIngo Weinhold{
7109ecf9d1cSIngo Weinhold	if (!fLayouter)
7119ecf9d1cSIngo Weinhold		return;
7129ecf9d1cSIngo Weinhold
7139ecf9d1cSIngo Weinhold	delete fLayouter;
7149ecf9d1cSIngo Weinhold	delete fLayoutInfo;
7159ecf9d1cSIngo Weinhold
7169ecf9d1cSIngo Weinhold	fLayouter = NULL;
7179ecf9d1cSIngo Weinhold	fLayoutInfo = NULL;
7189ecf9d1cSIngo Weinhold	fLayoutContext = NULL;
7199ecf9d1cSIngo Weinhold
7209ecf9d1cSIngo Weinhold	// notify all local layouters to invalidate the respective views
7219ecf9d1cSIngo Weinhold	int32 count = fLocalLayouters.CountItems();
7229ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
7239ecf9d1cSIngo Weinhold		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
7249ecf9d1cSIngo Weinhold		layouter->InternalInvalidateLayout(this);
7259ecf9d1cSIngo Weinhold	}
7269ecf9d1cSIngo Weinhold}
7279ecf9d1cSIngo Weinhold
72807dbd4d5SAxel Dörfler
7299ecf9d1cSIngo Weinholdbool
7309ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::IsMinMaxValid()
7319ecf9d1cSIngo Weinhold{
7329ecf9d1cSIngo Weinhold	return (fLayouter != NULL);
7339ecf9d1cSIngo Weinhold}
7349ecf9d1cSIngo Weinhold
73507dbd4d5SAxel Dörfler
7369ecf9d1cSIngo Weinholdvoid
7379ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::ValidateMinMax()
7389ecf9d1cSIngo Weinhold{
7399ecf9d1cSIngo Weinhold	if (IsMinMaxValid())
7409ecf9d1cSIngo Weinhold		return;
7419ecf9d1cSIngo Weinhold
7429ecf9d1cSIngo Weinhold	fLastLayoutSize = -1;
7439ecf9d1cSIngo Weinhold
7449ecf9d1cSIngo Weinhold	// create the layouter
7459ecf9d1cSIngo Weinhold	_PrepareItems();
7469ecf9d1cSIngo Weinhold
7479ecf9d1cSIngo Weinhold	int elementCount = _CountElements();
7489ecf9d1cSIngo Weinhold
749de667551SAlex Wilson	fLayouter = new CollapsingLayouter(elementCount, _Spacing());
7509ecf9d1cSIngo Weinhold
7519ecf9d1cSIngo Weinhold	// tell the layouter about our constraints
75207dbd4d5SAxel Dörfler	// TODO: We should probably ignore local layouters whose view is hidden.
75307dbd4d5SAxel Dörfler	// It's a bit tricky to find out, whether the view is hidden, though, since
75407dbd4d5SAxel Dörfler	// this doesn't necessarily mean only hidden relative to the parent, but
75507dbd4d5SAxel Dörfler	// hidden relative to a common parent.
7569ecf9d1cSIngo Weinhold	_AddConstraints(fLayouter);
7579ecf9d1cSIngo Weinhold
7589ecf9d1cSIngo Weinhold	fLayoutInfo = fLayouter->CreateLayoutInfo();
7599ecf9d1cSIngo Weinhold}
7609ecf9d1cSIngo Weinhold
76107dbd4d5SAxel Dörfler
7629ecf9d1cSIngo Weinholdvoid
7639ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::Layout(float size,
7649ecf9d1cSIngo Weinhold	LocalLayouter* localLayouter, BLayoutContext* context)
7659ecf9d1cSIngo Weinhold{
7669ecf9d1cSIngo Weinhold	ValidateMinMax();
7674aeb7a3cSStephan Aßmus
7689ecf9d1cSIngo Weinhold	if (context != fLayoutContext || fLastLayoutSize != size) {
7699ecf9d1cSIngo Weinhold		DoLayout(size, localLayouter, context);
7709ecf9d1cSIngo Weinhold		fLayoutContext = context;
7719ecf9d1cSIngo Weinhold		fLastLayoutSize = size;
7729ecf9d1cSIngo Weinhold	}
7739ecf9d1cSIngo Weinhold}
7749ecf9d1cSIngo Weinhold
77507dbd4d5SAxel Dörfler
7769ecf9d1cSIngo Weinholdvoid
7779ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::DoLayout(float size,
7789ecf9d1cSIngo Weinhold	LocalLayouter* localLayouter, BLayoutContext* context)
7799ecf9d1cSIngo Weinhold{
7809ecf9d1cSIngo Weinhold	fLayouter->Layout(fLayoutInfo, size);
7819ecf9d1cSIngo Weinhold}
7829ecf9d1cSIngo Weinhold
78307dbd4d5SAxel Dörfler
7849ecf9d1cSIngo Weinholdvoid
7859ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::_PrepareItems()
7869ecf9d1cSIngo Weinhold{
7879ecf9d1cSIngo Weinhold	int32 count = fLocalLayouters.CountItems();
7889ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
7899ecf9d1cSIngo Weinhold		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
7909ecf9d1cSIngo Weinhold		layouter->PrepareItems(this);
7919ecf9d1cSIngo Weinhold	}
7929ecf9d1cSIngo Weinhold}
7939ecf9d1cSIngo Weinhold
79407dbd4d5SAxel Dörfler
7959ecf9d1cSIngo Weinholdint32
7969ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::_CountElements()
7979ecf9d1cSIngo Weinhold{
7989ecf9d1cSIngo Weinhold	int32 elementCount = 0;
7999ecf9d1cSIngo Weinhold	int32 count = fLocalLayouters.CountItems();
8009ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
8019ecf9d1cSIngo Weinhold		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
8029ecf9d1cSIngo Weinhold		int32 layouterCount = layouter->CountElements(this);
8039ecf9d1cSIngo Weinhold		elementCount = max_c(elementCount, layouterCount);
8049ecf9d1cSIngo Weinhold	}
8059ecf9d1cSIngo Weinhold
8069ecf9d1cSIngo Weinhold	return elementCount;
8079ecf9d1cSIngo Weinhold}
8089ecf9d1cSIngo Weinhold
80907dbd4d5SAxel Dörfler
8109ecf9d1cSIngo Weinholdbool
8119ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::_HasMultiElementItems()
8129ecf9d1cSIngo Weinhold{
8139ecf9d1cSIngo Weinhold	int32 count = fLocalLayouters.CountItems();
8149ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
8159ecf9d1cSIngo Weinhold		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
8169ecf9d1cSIngo Weinhold		if (layouter->HasMultiElementItems(this))
8179ecf9d1cSIngo Weinhold			return true;
8189ecf9d1cSIngo Weinhold	}
8199ecf9d1cSIngo Weinhold
8209ecf9d1cSIngo Weinhold	return false;
8219ecf9d1cSIngo Weinhold}
8229ecf9d1cSIngo Weinhold
82307dbd4d5SAxel Dörfler
8249ecf9d1cSIngo Weinholdvoid
8259ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::_AddConstraints(Layouter* layouter)
8269ecf9d1cSIngo Weinhold{
8279ecf9d1cSIngo Weinhold	int32 count = fLocalLayouters.CountItems();
8289ecf9d1cSIngo Weinhold	for (int32 i = 0; i < count; i++) {
8299ecf9d1cSIngo Weinhold		LocalLayouter* localLayouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
8309ecf9d1cSIngo Weinhold		localLayouter->AddConstraints(this, layouter);
8319ecf9d1cSIngo Weinhold	}
8329ecf9d1cSIngo Weinhold}
8339ecf9d1cSIngo Weinhold
83407dbd4d5SAxel Dörfler
8359ecf9d1cSIngo Weinholdfloat
8369ecf9d1cSIngo WeinholdBTwoDimensionalLayout::CompoundLayouter::_Spacing()
8379ecf9d1cSIngo Weinhold{
8389ecf9d1cSIngo Weinhold	if (!fLocalLayouters.IsEmpty())
8399ecf9d1cSIngo Weinhold		return ((LocalLayouter*)fLocalLayouters.ItemAt(0))->Spacing(this);
8409ecf9d1cSIngo Weinhold	return 0;
8419ecf9d1cSIngo Weinhold}
8429ecf9d1cSIngo Weinhold
8439ecf9d1cSIngo Weinhold
8449ecf9d1cSIngo Weinhold// #pragma mark - VerticalCompoundLayouter
8459ecf9d1cSIngo Weinhold
8469ecf9d1cSIngo Weinhold
8479ecf9d1cSIngo WeinholdBTwoDimensionalLayout::VerticalCompoundLayouter::VerticalCompoundLayouter()
84807dbd4d5SAxel Dörfler	:
84907dbd4d5SAxel Dörfler	CompoundLayouter(B_VERTICAL),
85007dbd4d5SAxel Dörfler	fHeightForWidthLayouter(NULL),
85107dbd4d5SAxel Dörfler	fCachedMinHeightForWidth(0),
85207dbd4d5SAxel Dörfler	fCachedMaxHeightForWidth(0),
85307dbd4d5SAxel Dörfler	fCachedPreferredHeightForWidth(0),
85407dbd4d5SAxel Dörfler	fHeightForWidthLayoutContext(NULL)
8559ecf9d1cSIngo Weinhold{
8569ecf9d1cSIngo Weinhold}
8579ecf9d1cSIngo Weinhold
85807dbd4d5SAxel Dörfler
8599ecf9d1cSIngo WeinholdLayouter*
8609ecf9d1cSIngo WeinholdBTwoDimensionalLayout::VerticalCompoundLayouter::GetLayouter(bool minMax)
8619ecf9d1cSIngo Weinhold{
8629ecf9d1cSIngo Weinhold	return (minMax || !_HasHeightForWidth()
8639ecf9d1cSIngo Weinhold		? fLayouter : fHeightForWidthLayouter);
8649ecf9d1cSIngo Weinhold}
8659ecf9d1cSIngo Weinhold
86607dbd4d5SAxel Dörfler
8679ecf9d1cSIngo Weinholdvoid
8689ecf9d1cSIngo WeinholdBTwoDimensionalLayout::VerticalCompoundLayouter::InvalidateLayout()
8699ecf9d1cSIngo Weinhold{
8709ecf9d1cSIngo Weinhold	CompoundLayouter::InvalidateLayout();
8719ecf9d1cSIngo Weinhold
8729ecf9d1cSIngo Weinhold	InvalidateHeightForWidth();
8739ecf9d1cSIngo Weinhold}
8749ecf9d1cSIngo Weinhold
87507dbd4d5SAxel Dörfler
8769ecf9d1cSIngo Weinholdvoid
8779ecf9d1cSIngo WeinholdBTwoDimensionalLayout::VerticalCompoundLayouter::InvalidateHeightForWidth()
8789ecf9d1cSIngo Weinhold{
8799ecf9d1cSIngo Weinhold	if (fHeightForWidthLayouter != NULL) {
8809ecf9d1cSIngo Weinhold		delete fHeightForWidthLayouter;
8819ecf9d1cSIngo Weinhold		fHeightForWidthLayouter = NULL;
8829ecf9d1cSIngo Weinhold
8839ecf9d1cSIngo Weinhold		// also make sure we're not reusing the old layout info
8849ecf9d1cSIngo Weinhold		fLastLayoutSize = -1;
8859ecf9d1cSIngo Weinhold
8869ecf9d1cSIngo Weinhold		int32 count = fLocalLayouters.CountItems();
8879ecf9d1cSIngo Weinhold		for (int32 i = 0; i < count; i++) {
8889ecf9d1cSIngo Weinhold			LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
8899ecf9d1cSIngo Weinhold			layouter->SetHeightForWidthConstraintsAdded(false);
8909ecf9d1cSIngo Weinhold		}
8919ecf9d1cSIngo Weinhold	}
8929ecf9d1cSIngo Weinhold}
8939ecf9d1cSIngo Weinhold
89407dbd4d5SAxel Dörfler
8959ecf9d1cSIngo Weinholdvoid
8969ecf9d1cSIngo WeinholdBTwoDimensionalLayout::VerticalCompoundLayouter::InternalGetHeightForWidth(
8979ecf9d1cSIngo Weinhold	LocalLayouter* localLayouter, BLayoutContext* context, bool realLayout,
8989ecf9d1cSIngo Weinhold	float* minHeight, float* maxHeight, float* preferredHeight)
8999ecf9d1cSIngo Weinhold{
9009ecf9d1cSIngo Weinhold	bool updateCachedInfo = false;
9019ecf9d1cSIngo Weinhold
9029ecf9d1cSIngo Weinhold	if (_SetHeightForWidthLayoutContext(context)
9039ecf9d1cSIngo Weinhold		|| fHeightForWidthLayouter == NULL) {
9049ecf9d1cSIngo Weinhold		// Either the layout context changed or we haven't initialized the
9059ecf9d1cSIngo Weinhold		// height for width layouter yet. We create it and init it now.
9069ecf9d1cSIngo Weinhold
9079ecf9d1cSIngo Weinhold		// clone the vertical layouter
9089ecf9d1cSIngo Weinhold		delete fHeightForWidthLayouter;
9099ecf9d1cSIngo Weinhold		delete fLayoutInfo;
9109ecf9d1cSIngo Weinhold		fHeightForWidthLayouter = fLayouter->CloneLayouter();
9119ecf9d1cSIngo Weinhold		fLayoutInfo = fHeightForWidthLayouter->CreateLayoutInfo();
9129ecf9d1cSIngo Weinhold
9139ecf9d1cSIngo Weinhold		// add the children's height for width constraints
9149ecf9d1cSIngo Weinhold		int32 count = fLocalLayouters.CountItems();
9159ecf9d1cSIngo Weinhold		for (int32 i = 0; i < count; i++) {
9169ecf9d1cSIngo Weinhold			LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
9179ecf9d1cSIngo Weinhold			if (layouter->HasHeightForWidth()) {
9189ecf9d1cSIngo Weinhold				layouter->AddHeightForWidthConstraints(this,
9199ecf9d1cSIngo Weinhold					fHeightForWidthLayouter, context);
9209ecf9d1cSIngo Weinhold			}
9219ecf9d1cSIngo Weinhold		}
9229ecf9d1cSIngo Weinhold
9239ecf9d1cSIngo Weinhold		updateCachedInfo = true;
9249ecf9d1cSIngo Weinhold	} else if (localLayouter->HasHeightForWidth()) {
9259ecf9d1cSIngo Weinhold		// There is a height for width layouter and it has been initialized
9269ecf9d1cSIngo Weinhold		// in the current layout context. So we just add the height for width
9279ecf9d1cSIngo Weinhold		// constraints of the calling local layouter, if they haven't been
9289ecf9d1cSIngo Weinhold		// added yet.
9299ecf9d1cSIngo Weinhold		updateCachedInfo = localLayouter->AddHeightForWidthConstraints(this,
9309ecf9d1cSIngo Weinhold			fHeightForWidthLayouter, context);
9319ecf9d1cSIngo Weinhold	}
9329ecf9d1cSIngo Weinhold
9339ecf9d1cSIngo Weinhold	// update cached height for width info, if something changed
9349ecf9d1cSIngo Weinhold	if (updateCachedInfo) {
9359ecf9d1cSIngo Weinhold		// get the height for width info
9369ecf9d1cSIngo Weinhold		fCachedMinHeightForWidth = fHeightForWidthLayouter->MinSize();
9379ecf9d1cSIngo Weinhold		fCachedMaxHeightForWidth = fHeightForWidthLayouter->MaxSize();
9389ecf9d1cSIngo Weinhold		fCachedPreferredHeightForWidth
9399ecf9d1cSIngo Weinhold			= fHeightForWidthLayouter->PreferredSize();
9409ecf9d1cSIngo Weinhold	}
9419ecf9d1cSIngo Weinhold
9429ecf9d1cSIngo Weinhold	if (minHeight)
9439ecf9d1cSIngo Weinhold		*minHeight = fCachedMinHeightForWidth;
9449ecf9d1cSIngo Weinhold	if (maxHeight)
9459ecf9d1cSIngo Weinhold		*maxHeight = fCachedMaxHeightForWidth;
9469ecf9d1cSIngo Weinhold	if (preferredHeight)
9479ecf9d1cSIngo Weinhold		*preferredHeight = fCachedPreferredHeightForWidth;
9489ecf9d1cSIngo Weinhold}
9499ecf9d1cSIngo Weinhold
95007dbd4d5SAxel Dörfler
9519ecf9d1cSIngo Weinholdvoid
9529ecf9d1cSIngo WeinholdBTwoDimensionalLayout::VerticalCompoundLayouter::DoLayout(float size,
9539ecf9d1cSIngo Weinhold	LocalLayouter* localLayouter, BLayoutContext* context)
9549ecf9d1cSIngo Weinhold{
9559ecf9d1cSIngo Weinhold	Layouter* layouter;
9569ecf9d1cSIngo Weinhold	if