19ecf9d1cSIngo Weinhold/*
2a0747aadSIngo Weinhold * Copyright 2006-2009, Ingo Weinhold <ingo_weinhold@gmx.de>.
33333f968SRene Gollent * Copyright 2015, Rene Gollent, rene@gollent.com.
49ecf9d1cSIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License.
59ecf9d1cSIngo Weinhold */
69ecf9d1cSIngo Weinhold
74b20c303SIngo Weinhold
860558ed9SIngo Weinhold#include "SplitLayout.h"
99ecf9d1cSIngo Weinhold
104b20c303SIngo Weinhold#include <new>
119ecf9d1cSIngo Weinhold#include <stdio.h>
129ecf9d1cSIngo Weinhold
1382ab3167SAlex Wilson#include <ControlLook.h>
149ecf9d1cSIngo Weinhold#include <LayoutItem.h>
159ecf9d1cSIngo Weinhold#include <LayoutUtils.h>
164b20c303SIngo Weinhold#include <Message.h>
179ecf9d1cSIngo Weinhold#include <View.h>
189ecf9d1cSIngo Weinhold
199ecf9d1cSIngo Weinhold#include "OneElementLayouter.h"
209ecf9d1cSIngo Weinhold#include "SimpleLayouter.h"
219ecf9d1cSIngo Weinhold
224b20c303SIngo Weinhold
236829d417SAlex Wilsonusing std::nothrow;
246829d417SAlex Wilson
256829d417SAlex Wilson
264b20c303SIngo Weinhold// archivng constants
274b20c303SIngo Weinholdnamespace {
284a254e4dSAlex Wilson	const char* const kItemCollapsibleField = "BSplitLayout:item:collapsible";
294a254e4dSAlex Wilson	const char* const kItemWeightField = "BSplitLayout:item:weight";
304a254e4dSAlex Wilson	const char* const kSpacingField = "BSplitLayout:spacing";
314a254e4dSAlex Wilson	const char* const kSplitterSizeField = "BSplitLayout:splitterSize";
324a254e4dSAlex Wilson	const char* const kIsVerticalField = "BSplitLayout:vertical";
334a254e4dSAlex Wilson	const char* const kInsetsField = "BSplitLayout:insets";
344b20c303SIngo Weinhold}
354b20c303SIngo Weinhold
364b20c303SIngo Weinhold
379ecf9d1cSIngo Weinholdclass BSplitLayout::ItemLayoutInfo {
389ecf9d1cSIngo Weinholdpublic:
399ecf9d1cSIngo Weinhold	float		weight;
409ecf9d1cSIngo Weinhold	BRect		layoutFrame;
419ecf9d1cSIngo Weinhold	BSize		min;
429ecf9d1cSIngo Weinhold	BSize		max;
439ecf9d1cSIngo Weinhold	bool		isVisible;
449ecf9d1cSIngo Weinhold	bool		isCollapsible;
459ecf9d1cSIngo Weinhold
469ecf9d1cSIngo Weinhold	ItemLayoutInfo()
474b20c303SIngo Weinhold		:
484b20c303SIngo Weinhold		weight(1.0f),
494b20c303SIngo Weinhold		layoutFrame(0, 0, -1, -1),
504b20c303SIngo Weinhold		min(),
514b20c303SIngo Weinhold		max(),
524b20c303SIngo Weinhold		isVisible(true),
534b20c303SIngo Weinhold		isCollapsible(true)
549ecf9d1cSIngo Weinhold	{
559ecf9d1cSIngo Weinhold	}
569ecf9d1cSIngo Weinhold};
579ecf9d1cSIngo Weinhold
584b20c303SIngo Weinhold
599ecf9d1cSIngo Weinholdclass BSplitLayout::ValueRange {
609ecf9d1cSIngo Weinholdpublic:
619ecf9d1cSIngo Weinhold	int32 sumValue;	// including spacing
629ecf9d1cSIngo Weinhold	int32 previousMin;
639ecf9d1cSIngo Weinhold	int32 previousMax;
649ecf9d1cSIngo Weinhold	int32 previousSize;
659ecf9d1cSIngo Weinhold	int32 nextMin;
669ecf9d1cSIngo Weinhold	int32 nextMax;
679ecf9d1cSIngo Weinhold	int32 nextSize;
689ecf9d1cSIngo Weinhold};
699ecf9d1cSIngo Weinhold
704b20c303SIngo Weinhold
719ecf9d1cSIngo Weinholdclass BSplitLayout::SplitterItem : public BLayoutItem {
729ecf9d1cSIngo Weinholdpublic:
739ecf9d1cSIngo Weinhold	SplitterItem(BSplitLayout* layout)
744b20c303SIngo Weinhold		:
754b20c303SIngo Weinhold		fLayout(layout),
764b20c303SIngo Weinhold		fFrame()
779ecf9d1cSIngo Weinhold	{
789ecf9d1cSIngo Weinhold	}
799ecf9d1cSIngo Weinhold
804b20c303SIngo Weinhold
819ecf9d1cSIngo Weinhold	virtual BSize MinSize()
829ecf9d1cSIngo Weinhold	{
839ecf9d1cSIngo Weinhold		if (fLayout->Orientation() == B_HORIZONTAL)
849ecf9d1cSIngo Weinhold			return BSize(fLayout->SplitterSize() - 1, -1);
859ecf9d1cSIngo Weinhold		else
869ecf9d1cSIngo Weinhold			return BSize(-1, fLayout->SplitterSize() - 1);
879ecf9d1cSIngo Weinhold	}
889ecf9d1cSIngo Weinhold
899ecf9d1cSIngo Weinhold	virtual BSize MaxSize()
909ecf9d1cSIngo Weinhold	{
919ecf9d1cSIngo Weinhold		if (fLayout->Orientation() == B_HORIZONTAL)
929ecf9d1cSIngo Weinhold			return BSize(fLayout->SplitterSize() - 1, B_SIZE_UNLIMITED);
939ecf9d1cSIngo Weinhold		else
949ecf9d1cSIngo Weinhold			return BSize(B_SIZE_UNLIMITED, fLayout->SplitterSize() - 1);
959ecf9d1cSIngo Weinhold	}
969ecf9d1cSIngo Weinhold
979ecf9d1cSIngo Weinhold	virtual BSize PreferredSize()
989ecf9d1cSIngo Weinhold	{
999ecf9d1cSIngo Weinhold		return MinSize();
1009ecf9d1cSIngo Weinhold	}
1019ecf9d1cSIngo Weinhold
1029ecf9d1cSIngo Weinhold	virtual BAlignment Alignment()
1039ecf9d1cSIngo Weinhold	{
1049ecf9d1cSIngo Weinhold		return BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER);
1059ecf9d1cSIngo Weinhold	}
1069ecf9d1cSIngo Weinhold
1079ecf9d1cSIngo Weinhold	virtual void SetExplicitMinSize(BSize size)
1089ecf9d1cSIngo Weinhold	{
1099ecf9d1cSIngo Weinhold		// not allowed
1109ecf9d1cSIngo Weinhold	}
1119ecf9d1cSIngo Weinhold
1129ecf9d1cSIngo Weinhold	virtual void SetExplicitMaxSize(BSize size)
1139ecf9d1cSIngo Weinhold	{
1149ecf9d1cSIngo Weinhold		// not allowed
1159ecf9d1cSIngo Weinhold	}
1169ecf9d1cSIngo Weinhold
1179ecf9d1cSIngo Weinhold	virtual void SetExplicitPreferredSize(BSize size)
1189ecf9d1cSIngo Weinhold	{
1199ecf9d1cSIngo Weinhold		// not allowed
1209ecf9d1cSIngo Weinhold	}
1219ecf9d1cSIngo Weinhold
1229ecf9d1cSIngo Weinhold	virtual void SetExplicitAlignment(BAlignment alignment)
1239ecf9d1cSIngo Weinhold	{
1249ecf9d1cSIngo Weinhold		// not allowed
1259ecf9d1cSIngo Weinhold	}
1269ecf9d1cSIngo Weinhold
1279ecf9d1cSIngo Weinhold	virtual bool IsVisible()
1289ecf9d1cSIngo Weinhold	{
1299ecf9d1cSIngo Weinhold		return true;
1309ecf9d1cSIngo Weinhold	}
1319ecf9d1cSIngo Weinhold
1329ecf9d1cSIngo Weinhold	virtual void SetVisible(bool visible)
1339ecf9d1cSIngo Weinhold	{
1349ecf9d1cSIngo Weinhold		// not allowed
1359ecf9d1cSIngo Weinhold	}
1369ecf9d1cSIngo Weinhold
1379ecf9d1cSIngo Weinhold
1389ecf9d1cSIngo Weinhold	virtual BRect Frame()
1399ecf9d1cSIngo Weinhold	{
1409ecf9d1cSIngo Weinhold		return fFrame;
1419ecf9d1cSIngo Weinhold	}
1429ecf9d1cSIngo Weinhold
1439ecf9d1cSIngo Weinhold	virtual void SetFrame(BRect frame)
1449ecf9d1cSIngo Weinhold	{
1459ecf9d1cSIngo Weinhold		fFrame = frame;
1469ecf9d1cSIngo Weinhold	}
1479ecf9d1cSIngo Weinhold
1489ecf9d1cSIngo Weinholdprivate:
1499ecf9d1cSIngo Weinhold	BSplitLayout*	fLayout;
1509ecf9d1cSIngo Weinhold	BRect			fFrame;
1519ecf9d1cSIngo Weinhold};
1529ecf9d1cSIngo Weinhold
1539ecf9d1cSIngo Weinhold
1549ecf9d1cSIngo Weinhold// #pragma mark -
1559ecf9d1cSIngo Weinhold
1569ecf9d1cSIngo Weinhold
157e724b26fSJohn ScipioneBSplitLayout::BSplitLayout(orientation orientation, float spacing)
1584b20c303SIngo Weinhold	:
1594b20c303SIngo Weinhold	fOrientation(orientation),
1604b20c303SIngo Weinhold	fLeftInset(0),
1614b20c303SIngo Weinhold	fRightInset(0),
1624b20c303SIngo Weinhold	fTopInset(0),
1634b20c303SIngo Weinhold	fBottomInset(0),
1644b20c303SIngo Weinhold	fSplitterSize(6),
1656648dd3cSAlex Wilson	fSpacing(BControlLook::ComposeSpacing(spacing)),
1664b20c303SIngo Weinhold
1674b20c303SIngo Weinhold	fSplitterItems(),
1684b20c303SIngo Weinhold	fVisibleItems(),
1694b20c303SIngo Weinhold	fMin(),
1704b20c303SIngo Weinhold	fMax(),
1714b20c303SIngo Weinhold	fPreferred(),
1724b20c303SIngo Weinhold
1734b20c303SIngo Weinhold	fHorizontalLayouter(NULL),
1744b20c303SIngo Weinhold	fVerticalLayouter(NULL),
1754b20c303SIngo Weinhold	fHorizontalLayoutInfo(NULL),
1764b20c303SIngo Weinhold	fVerticalLayoutInfo(NULL),
1774b20c303SIngo Weinhold
1784b20c303SIngo Weinhold	fHeightForWidthItems(),
1794b20c303SIngo Weinhold	fHeightForWidthVerticalLayouter(NULL),
1804b20c303SIngo Weinhold	fHeightForWidthHorizontalLayoutInfo(NULL),
1814b20c303SIngo Weinhold
1824b20c303SIngo Weinhold	fLayoutValid(false),
1834b20c303SIngo Weinhold
1844b20c303SIngo Weinhold	fCachedHeightForWidthWidth(-2),
1854b20c303SIngo Weinhold	fHeightForWidthVerticalLayouterWidth(-2),
1864b20c303SIngo Weinhold	fCachedMinHeightForWidth(-1),
1874b20c303SIngo Weinhold	fCachedMaxHeightForWidth(-1),
1884b20c303SIngo Weinhold	fCachedPreferredHeightForWidth(-1),
1894b20c303SIngo Weinhold
1904b20c303SIngo Weinhold	fDraggingStartPoint(),
1914b20c303SIngo Weinhold	fDraggingStartValue(0),
1924b20c303SIngo Weinhold	fDraggingCurrentValue(0),
1934b20c303SIngo Weinhold	fDraggingSplitterIndex(-1)
1944b20c303SIngo Weinhold{
1954b20c303SIngo Weinhold}
1964b20c303SIngo Weinhold
1974b20c303SIngo Weinhold
1984b20c303SIngo WeinholdBSplitLayout::BSplitLayout(BMessage* from)
1994b20c303SIngo Weinhold	:
2001d6c7b6cSAlex Wilson	BAbstractLayout(BUnarchiver::PrepareArchive(from)),
20171947e47SAlex Wilson	fOrientation(B_HORIZONTAL),
20271947e47SAlex Wilson	fLeftInset(0),
20371947e47SAlex Wilson	fRightInset(0),
20471947e47SAlex Wilson	fTopInset(0),
20571947e47SAlex Wilson	fBottomInset(0),
20671947e47SAlex Wilson	fSplitterSize(6),
20771947e47SAlex Wilson	fSpacing(be_control_look->DefaultItemSpacing()),
20871947e47SAlex Wilson
2094b20c303SIngo Weinhold	fSplitterItems(),
2104b20c303SIngo Weinhold	fVisibleItems(),
2114b20c303SIngo Weinhold	fMin(),
2124b20c303SIngo Weinhold	fMax(),
2134b20c303SIngo Weinhold	fPreferred(),
2144b20c303SIngo Weinhold
2154b20c303SIngo Weinhold	fHorizontalLayouter(NULL),
2164b20c303SIngo Weinhold	fVerticalLayouter(NULL),
2174b20c303SIngo Weinhold	fHorizontalLayoutInfo(NULL),
2184b20c303SIngo Weinhold	fVerticalLayoutInfo(NULL),
2194b20c303SIngo Weinhold
2204b20c303SIngo Weinhold	fHeightForWidthItems(),
2214b20c303SIngo Weinhold	fHeightForWidthVerticalLayouter(NULL),
2224b20c303SIngo Weinhold	fHeightForWidthHorizontalLayoutInfo(NULL),
2234b20c303SIngo Weinhold
2244b20c303SIngo Weinhold	fLayoutValid(false),
2254b20c303SIngo Weinhold
2264b20c303SIngo Weinhold	fCachedHeightForWidthWidth(-2),
2274b20c303SIngo Weinhold	fHeightForWidthVerticalLayouterWidth(-2),
2284b20c303SIngo Weinhold	fCachedMinHeightForWidth(-1),
2294b20c303SIngo Weinhold	fCachedMaxHeightForWidth(-1),
2304b20c303SIngo Weinhold	fCachedPreferredHeightForWidth(-1),
2314b20c303SIngo Weinhold
2324b20c303SIngo Weinhold	fDraggingStartPoint(),
2334b20c303SIngo Weinhold	fDraggingStartValue(0),
2344b20c303SIngo Weinhold	fDraggingCurrentValue(0),
2354b20c303SIngo Weinhold	fDraggingSplitterIndex(-1)
2369ecf9d1cSIngo Weinhold{
2374a254e4dSAlex Wilson	BUnarchiver unarchiver(from);
2384a254e4dSAlex Wilson
2394b20c303SIngo Weinhold	bool isVertical;
2404a254e4dSAlex Wilson	status_t err = from->FindBool(kIsVerticalField, &isVertical);
2414a254e4dSAlex Wilson	if (err != B_OK) {
2424a254e4dSAlex Wilson		unarchiver.Finish(err);
2434a254e4dSAlex Wilson		return;
2444a254e4dSAlex Wilson	}
2454b20c303SIngo Weinhold	fOrientation = (isVertical) ? B_VERTICAL : B_HORIZONTAL ;
2464b20c303SIngo Weinhold
2474a254e4dSAlex Wilson	BRect insets;
2484a254e4dSAlex Wilson	err = from->FindRect(kInsetsField, &insets);
2494a254e4dSAlex Wilson	if (err != B_OK) {
2504a254e4dSAlex Wilson		unarchiver.Finish(err);
2514a254e4dSAlex Wilson		return;
2524a254e4dSAlex Wilson	}
2534a254e4dSAlex Wilson	SetInsets(insets.left, insets.top, insets.right, insets.bottom);
2544a254e4dSAlex Wilson
2554a254e4dSAlex Wilson	err = from->FindFloat(kSplitterSizeField, &fSplitterSize);
2564a254e4dSAlex Wilson	if (err == B_OK)
2574a254e4dSAlex Wilson		err = from->FindFloat(kSpacingField, &fSpacing);
2584a254e4dSAlex Wilson
2594a254e4dSAlex Wilson	unarchiver.Finish(err);
2609ecf9d1cSIngo Weinhold}
2619ecf9d1cSIngo Weinhold
2624b20c303SIngo Weinhold
2639ecf9d1cSIngo WeinholdBSplitLayout::~BSplitLayout()
2649ecf9d1cSIngo Weinhold{
2659ecf9d1cSIngo Weinhold}
2669ecf9d1cSIngo Weinhold
2674b20c303SIngo Weinhold
2689ecf9d1cSIngo Weinholdvoid
2699ecf9d1cSIngo WeinholdBSplitLayout::SetInsets(float left, float top, float right, float bottom)
2709ecf9d1cSIngo Weinhold{
271813147dfSAlex Wilson	fLeftInset = left;
272813147dfSAlex Wilson	fTopInset = top;
273813147dfSAlex Wilson	fRightInset = right;
274813147dfSAlex Wilson	fBottomInset = bottom;
2759ecf9d1cSIngo Weinhold
2769ecf9d1cSIngo Weinhold	InvalidateLayout();
2779ecf9d1cSIngo Weinhold}
2789ecf9d1cSIngo Weinhold
2794b20c303SIngo Weinhold
2809ecf9d1cSIngo Weinholdvoid
2814aeb7a3cSStephan AßmusBSplitLayout::GetInsets(float* left, float* top, float* right,
2824aeb7a3cSStephan Aßmus	float* bottom) const
2839ecf9d1cSIngo Weinhold{
2849ecf9d1cSIngo Weinhold	if (left)
2859ecf9d1cSIngo Weinhold		*left = fLeftInset;
2869ecf9d1cSIngo Weinhold	if (top)
2879ecf9d1cSIngo Weinhold		*top = fTopInset;
2889ecf9d1cSIngo Weinhold	if (right)
2899ecf9d1cSIngo Weinhold		*right = fRightInset;
2909ecf9d1cSIngo Weinhold	if (bottom)
2919ecf9d1cSIngo Weinhold		*bottom = fBottomInset;
2929ecf9d1cSIngo Weinhold}
2939ecf9d1cSIngo Weinhold
2944b20c303SIngo Weinhold
2959ecf9d1cSIngo Weinholdfloat
2969ecf9d1cSIngo WeinholdBSplitLayout::Spacing() const
2979ecf9d1cSIngo Weinhold{
2989ecf9d1cSIngo Weinhold	return fSpacing;
2999ecf9d1cSIngo Weinhold}
3009ecf9d1cSIngo Weinhold
3014b20c303SIngo Weinhold
3029ecf9d1cSIngo Weinholdvoid
3039ecf9d1cSIngo WeinholdBSplitLayout::SetSpacing(float spacing)
3049ecf9d1cSIngo Weinhold{
3056648dd3cSAlex Wilson	spacing = BControlLook::ComposeSpacing(spacing);
3069ecf9d1cSIngo Weinhold	if (spacing != fSpacing) {
3079ecf9d1cSIngo Weinhold		fSpacing = spacing;
3089ecf9d1cSIngo Weinhold
3099ecf9d1cSIngo Weinhold		InvalidateLayout();
3109ecf9d1cSIngo Weinhold	}
3119ecf9d1cSIngo Weinhold}
3129ecf9d1cSIngo Weinhold
3134b20c303SIngo Weinhold
3149ecf9d1cSIngo Weinholdorientation
3159ecf9d1cSIngo WeinholdBSplitLayout::Orientation() const
3169ecf9d1cSIngo Weinhold{
3179ecf9d1cSIngo Weinhold	return fOrientation;
3189ecf9d1cSIngo Weinhold}
3199ecf9d1cSIngo Weinhold
3204b20c303SIngo Weinhold
3219ecf9d1cSIngo Weinholdvoid
322e724b26fSJohn ScipioneBSplitLayout::SetOrientation(orientation orientation)
3239ecf9d1cSIngo Weinhold{
3249ecf9d1cSIngo Weinhold	if (orientation != fOrientation) {
3259ecf9d1cSIngo Weinhold		fOrientation = orientation;
3269ecf9d1cSIngo Weinhold
3279ecf9d1cSIngo Weinhold		InvalidateLayout();
3289ecf9d1cSIngo Weinhold	}
3299ecf9d1cSIngo Weinhold}
3309ecf9d1cSIngo Weinhold
3314b20c303SIngo Weinhold
3329ecf9d1cSIngo Weinholdfloat
3339ecf9d1cSIngo WeinholdBSplitLayout::SplitterSize() const
3349ecf9d1cSIngo Weinhold{
3359ecf9d1cSIngo Weinhold	return fSplitterSize;
3369ecf9d1cSIngo Weinhold}
3379ecf9d1cSIngo Weinhold
3384b20c303SIngo Weinhold
3399ecf9d1cSIngo Weinholdvoid
3409ecf9d1cSIngo WeinholdBSplitLayout::SetSplitterSize(float size)
3419ecf9d1cSIngo Weinhold{
3429ecf9d1cSIngo Weinhold	if (size != fSplitterSize) {
3439ecf9d1cSIngo Weinhold		fSplitterSize = size;
3449ecf9d1cSIngo Weinhold
3459ecf9d1cSIngo Weinhold		InvalidateLayout();
3469ecf9d1cSIngo Weinhold	}
3479ecf9d1cSIngo Weinhold}
3489ecf9d1cSIngo Weinhold
3494b20c303SIngo Weinhold
3509ecf9d1cSIngo WeinholdBLayoutItem*
3519ecf9d1cSIngo WeinholdBSplitLayout::AddView(BView* child)
3529ecf9d1cSIngo Weinhold{
3531d6c7b6cSAlex Wilson	return BAbstractLayout::AddView(child);
3549ecf9d1cSIngo Weinhold}
3559ecf9d1cSIngo Weinhold
3564b20c303SIngo Weinhold
3579ecf9d1cSIngo WeinholdBLayoutItem*
3589ecf9d1cSIngo WeinholdBSplitLayout::AddView(int32 index, BView* child)
3599ecf9d1cSIngo Weinhold{
3601d6c7b6cSAlex Wilson	return BAbstractLayout::AddView(index, child);
3619ecf9d1cSIngo Weinhold}
3629ecf9d1cSIngo Weinhold
3634b20c303SIngo Weinhold
3649ecf9d1cSIngo WeinholdBLayoutItem*
3659ecf9d1cSIngo WeinholdBSplitLayout::AddView(BView* child, float weight)
3669ecf9d1cSIngo Weinhold{
3679ecf9d1cSIngo Weinhold	return AddView(-1, child, weight);
3689ecf9d1cSIngo Weinhold}
3699ecf9d1cSIngo Weinhold
3704b20c303SIngo Weinhold
3719ecf9d1cSIngo WeinholdBLayoutItem*
3729ecf9d1cSIngo WeinholdBSplitLayout::AddView(int32 index, BView* child, float weight)
3739ecf9d1cSIngo Weinhold{
3749ecf9d1cSIngo Weinhold	BLayoutItem* item = AddView(index, child);
3759ecf9d1cSIngo Weinhold	if (item)
3769ecf9d1cSIngo Weinhold		SetItemWeight(item, weight);
3779ecf9d1cSIngo Weinhold
3789ecf9d1cSIngo Weinhold	return item;
3799ecf9d1cSIngo Weinhold}
3809ecf9d1cSIngo Weinhold
3814b20c303SIngo Weinhold
3829ecf9d1cSIngo Weinholdbool
3839ecf9d1cSIngo WeinholdBSplitLayout::AddItem(BLayoutItem* item)
3849ecf9d1cSIngo Weinhold{
3851d6c7b6cSAlex Wilson	return BAbstractLayout::AddItem(item);
3869ecf9d1cSIngo Weinhold}
3879ecf9d1cSIngo Weinhold
3884b20c303SIngo Weinhold
3899ecf9d1cSIngo Weinholdbool
3909ecf9d1cSIngo WeinholdBSplitLayout::AddItem(int32 index, BLayoutItem* item)
3919ecf9d1cSIngo Weinhold{
3921d6c7b6cSAlex Wilson	return BAbstractLayout::AddItem(index, item);
3939ecf9d1cSIngo Weinhold}
3949ecf9d1cSIngo Weinhold
3954b20c303SIngo Weinhold
3969ecf9d1cSIngo Weinholdbool
3979ecf9d1cSIngo WeinholdBSplitLayout::AddItem(BLayoutItem* item, float weight)
3989ecf9d1cSIngo Weinhold{
3999ecf9d1cSIngo Weinhold	return AddItem(-1, item, weight);
4009ecf9d1cSIngo Weinhold}
4019ecf9d1cSIngo Weinhold
4024b20c303SIngo Weinhold
4039ecf9d1cSIngo Weinholdbool
4049ecf9d1cSIngo WeinholdBSplitLayout::AddItem(int32 index, BLayoutItem* item, float weight)
4059ecf9d1cSIngo Weinhold{
4069ecf9d1cSIngo Weinhold	bool success = AddItem(index, item);
4079ecf9d1cSIngo Weinhold	if (success)
4089ecf9d1cSIngo Weinhold		SetItemWeight(item, weight);
4099ecf9d1cSIngo Weinhold
4109ecf9d1cSIngo Weinhold	return success;
4119ecf9d1cSIngo Weinhold}
4129ecf9d1cSIngo Weinhold
4134b20c303SIngo Weinhold
4149ecf9d1cSIngo Weinholdfloat
4159ecf9d1cSIngo WeinholdBSplitLayout::ItemWeight(int32 index) const
4169ecf9d1cSIngo Weinhold{
4179ecf9d1cSIngo Weinhold	if (index < 0 || index >= CountItems())
4189ecf9d1cSIngo Weinhold		return 0;
4199ecf9d1cSIngo Weinhold
4209ecf9d1cSIngo Weinhold	return ItemWeight(ItemAt(index));
4219ecf9d1cSIngo Weinhold}
4229ecf9d1cSIngo Weinhold
4234b20c303SIngo Weinhold
4249ecf9d1cSIngo Weinholdfloat
4259ecf9d1cSIngo WeinholdBSplitLayout::ItemWeight(BLayoutItem* item) const
4269ecf9d1cSIngo Weinhold{
4279ecf9d1cSIngo Weinhold	if (ItemLayoutInfo* info = _ItemLayoutInfo(item))
4289ecf9d1cSIngo Weinhold		return info->weight;
4299ecf9d1cSIngo Weinhold	return 0;
4309ecf9d1cSIngo Weinhold}
4319ecf9d1cSIngo Weinhold
4324b20c303SIngo Weinhold
4339ecf9d1cSIngo Weinholdvoid
4349ecf9d1cSIngo WeinholdBSplitLayout::SetItemWeight(int32 index, float weight, bool invalidateLayout)
4359ecf9d1cSIngo Weinhold{
4369ecf9d1cSIngo Weinhold	if (index < 0 || index >= CountItems())
4379ecf9d1cSIngo Weinhold		return;
4389ecf9d1cSIngo Weinhold
4399ecf9d1cSIngo Weinhold	BLayoutItem* item = ItemAt(index);
4409ecf9d1cSIngo Weinhold	SetItemWeight(item, weight);
4419ecf9d1cSIngo Weinhold
4429ecf9d1cSIngo Weinhold	if (fHorizontalLayouter) {
4439ecf9d1cSIngo Weinhold		int32 visibleIndex = fVisibleItems.IndexOf(item);
4449ecf9d1cSIngo Weinhold		if (visibleIndex >= 0) {
4459ecf9d1cSIngo Weinhold			if (fOrientation == B_HORIZONTAL)
4469ecf9d1cSIngo Weinhold				fHorizontalLayouter->SetWeight(visibleIndex, weight);
4479ecf9d1cSIngo Weinhold			else
4489ecf9d1cSIngo Weinhold				fVerticalLayouter->SetWeight(visibleIndex, weight);
4499ecf9d1cSIngo Weinhold		}
4509ecf9d1cSIngo Weinhold	}
4519ecf9d1cSIngo Weinhold
4529ecf9d1cSIngo Weinhold	if (invalidateLayout)
4539ecf9d1cSIngo Weinhold		InvalidateLayout();
4549ecf9d1cSIngo Weinhold}
4559ecf9d1cSIngo Weinhold
4564b20c303SIngo Weinhold
4579ecf9d1cSIngo Weinholdvoid
4589ecf9d1cSIngo WeinholdBSplitLayout::SetItemWeight(BLayoutItem* item, float weight)
4599ecf9d1cSIngo Weinhold{
4609ecf9d1cSIngo Weinhold	if (ItemLayoutInfo* info = _ItemLayoutInfo(item))
4619ecf9d1cSIngo Weinhold		info->weight = weight;
4629ecf9d1cSIngo Weinhold}
4639ecf9d1cSIngo Weinhold
4644b20c303SIngo Weinhold
4656d16dcfaSRene Gollentbool
4667b27c8fcSRene GollentBSplitLayout::IsCollapsible(int32 index) const
4676d16dcfaSRene Gollent{
4686d16dcfaSRene Gollent	return _ItemLayoutInfo(ItemAt(index))->isCollapsible;
4696d16dcfaSRene Gollent}
4706d16dcfaSRene Gollent
4716d16dcfaSRene Gollent
4729ecf9d1cSIngo Weinholdvoid
4739ecf9d1cSIngo WeinholdBSplitLayout::SetCollapsible(bool collapsible)
4749ecf9d1cSIngo Weinhold{
4759ecf9d1cSIngo Weinhold	SetCollapsible(0, CountItems() - 1, collapsible);
4769ecf9d1cSIngo Weinhold}
4779ecf9d1cSIngo Weinhold
4784b20c303SIngo Weinhold
4799ecf9d1cSIngo Weinholdvoid
4809ecf9d1cSIngo WeinholdBSplitLayout::SetCollapsible(int32 index, bool collapsible)
4819ecf9d1cSIngo Weinhold{
4829ecf9d1cSIngo Weinhold	SetCollapsible(index, index, collapsible);
4839ecf9d1cSIngo Weinhold}
4849ecf9d1cSIngo Weinhold
4854b20c303SIngo Weinhold
4869ecf9d1cSIngo Weinholdvoid
4879ecf9d1cSIngo WeinholdBSplitLayout::SetCollapsible(int32 first, int32 last, bool collapsible)
4889ecf9d1cSIngo Weinhold{
4899ecf9d1cSIngo Weinhold	for (int32 i = first; i <= last; i++)
4909ecf9d1cSIngo Weinhold		_ItemLayoutInfo(ItemAt(i))->isCollapsible = collapsible;
4919ecf9d1cSIngo Weinhold}
4929ecf9d1cSIngo Weinhold
4934b20c303SIngo Weinhold
4946beb27d4SRene Gollentbool
4957b27c8fcSRene GollentBSplitLayout::IsItemCollapsed(int32 index) const
4966beb27d4SRene Gollent{
4973333f968SRene Gollent	return !_ItemLayoutInfo(ItemAt(index))->isVisible;
4986beb27d4SRene Gollent}
4996beb27d4SRene Gollent
5006beb27d4SRene Gollent
5016beb27d4SRene Gollentvoid
5027b27c8fcSRene GollentBSplitLayout::SetItemCollapsed(int32 index, bool collapsed)
5036beb27d4SRene Gollent{
5043333f968SRene Gollent	ItemAt(index)->SetVisible(!collapsed);
5056beb27d4SRene Gollent
5066beb27d4SRene Gollent	InvalidateLayout(true);
5076beb27d4SRene Gollent}
5089ecf9d1cSIngo Weinhold
5094b20c303SIngo Weinhold
5109ecf9d1cSIngo WeinholdBSize
5111d6c7b6cSAlex WilsonBSplitLayout::BaseMinSize()
5129ecf9d1cSIngo Weinhold{
5139ecf9d1cSIngo Weinhold	_ValidateMinMax();
5149ecf9d1cSIngo Weinhold
5159ecf9d1cSIngo Weinhold	return _AddInsets(fMin);
5169ecf9d1cSIngo Weinhold}
5179ecf9d1cSIngo Weinhold
5184b20c303SIngo Weinhold
5199ecf9d1cSIngo WeinholdBSize
5201d6c7b6cSAlex WilsonBSplitLayout::BaseMaxSize()
5219ecf9d1cSIngo Weinhold{
5229ecf9d1cSIngo Weinhold	_ValidateMinMax();
5239ecf9d1cSIngo Weinhold
5249ecf9d1cSIngo Weinhold	return _AddInsets(fMax);
5259ecf9d1cSIngo Weinhold}
5269ecf9d1cSIngo Weinhold
5274b20c303SIngo Weinhold
5289ecf9d1cSIngo WeinholdBSize
5291d6c7b6cSAlex WilsonBSplitLayout::BasePreferredSize()
5309ecf9d1cSIngo Weinhold{
5319ecf9d1cSIngo Weinhold	_ValidateMinMax();
5329ecf9d1cSIngo Weinhold
5339ecf9d1cSIngo Weinhold	return _AddInsets(fPreferred);
5349ecf9d1cSIngo Weinhold}
5359ecf9d1cSIngo Weinhold
5364b20c303SIngo Weinhold
5379ecf9d1cSIngo WeinholdBAlignment
5381d6c7b6cSAlex WilsonBSplitLayout::BaseAlignment()
5399ecf9d1cSIngo Weinhold{
5401d6c7b6cSAlex Wilson	return BAbstractLayout::BaseAlignment();
5419ecf9d1cSIngo Weinhold}
5429ecf9d1cSIngo Weinhold
5434b20c303SIngo Weinhold
5449ecf9d1cSIngo Weinholdbool
5459ecf9d1cSIngo WeinholdBSplitLayout::HasHeightForWidth()
5469ecf9d1cSIngo Weinhold{
5479ecf9d1cSIngo Weinhold	_ValidateMinMax();
5489ecf9d1cSIngo Weinhold
5499ecf9d1cSIngo Weinhold	return !fHeightForWidthItems.IsEmpty();
5509ecf9d1cSIngo Weinhold}
5519ecf9d1cSIngo Weinhold
5524b20c303SIngo Weinhold
5539ecf9d1cSIngo Weinholdvoid
5549ecf9d1cSIngo WeinholdBSplitLayout::GetHeightForWidth(float width, float* min, float* max,
5559ecf9d1cSIngo Weinhold	float* preferred)
5569ecf9d1cSIngo Weinhold{
5579ecf9d1cSIngo Weinhold	if (!HasHeightForWidth())
5589ecf9d1cSIngo Weinhold		return;
5599ecf9d1cSIngo Weinhold
5609ecf9d1cSIngo Weinhold	float innerWidth = _SubtractInsets(BSize(width, 0)).width;
5619ecf9d1cSIngo Weinhold	_InternalGetHeightForWidth(innerWidth, false, min, max, preferred);
5629ecf9d1cSIngo Weinhold	_AddInsets(min, max, preferred);
5639ecf9d1cSIngo Weinhold}
5649ecf9d1cSIngo Weinhold
5654b20c303SIngo Weinhold
5669ecf9d1cSIngo Weinholdvoid
567b38ea98fSAlex WilsonBSplitLayout::LayoutInvalidated(bool children)
5689ecf9d1cSIngo Weinhold{
569b38ea98fSAlex Wilson	delete fHorizontalLayouter;
570b38ea98fSAlex Wilson	delete fVerticalLayouter;
571b38ea98fSAlex Wilson	delete fHorizontalLayoutInfo;
572b38ea98fSAlex Wilson	delete fVerticalLayoutInfo;
573b38ea98fSAlex Wilson
574b38ea98fSAlex Wilson	fHorizontalLayouter = NULL;
575b38ea98fSAlex Wilson	fVerticalLayouter = NULL;
576b38ea98fSAlex Wilson	fHorizontalLayoutInfo = NULL;
577b38ea98fSAlex Wilson	fVerticalLayoutInfo = NULL;
578b38ea98fSAlex Wilson
579b38ea98fSAlex Wilson	_InvalidateCachedHeightForWidth();
580b38ea98fSAlex Wilson
581b38ea98fSAlex Wilson	fLayoutValid = false;
5829ecf9d1cSIngo Weinhold}
5839ecf9d1cSIngo Weinhold
5844b20c303SIngo Weinhold
5859ecf9d1cSIngo Weinholdvoid
5864e0131f5SAlex WilsonBSplitLayout::DoLayout()
5879ecf9d1cSIngo Weinhold{
5889ecf9d1cSIngo Weinhold	_ValidateMinMax();
5899ecf9d1cSIngo Weinhold
5909ecf9d1cSIngo Weinhold	// layout the elements
5911d6c7b6cSAlex Wilson	BSize size = _SubtractInsets(LayoutArea().Size());
5929ecf9d1cSIngo Weinhold	fHorizontalLayouter->Layout(fHorizontalLayoutInfo, size.width);
5939ecf9d1cSIngo Weinhold
5949ecf9d1cSIngo Weinhold	Layouter* verticalLayouter;
5959ecf9d1cSIngo Weinhold	if (HasHeightForWidth()) {
5969ecf9d1cSIngo Weinhold		float minHeight, maxHeight, preferredHeight;
5979ecf9d1cSIngo Weinhold		_InternalGetHeightForWidth(size.width, true, &minHeight, &maxHeight,
5989ecf9d1cSIngo Weinhold			&preferredHeight);
5999ecf9d1cSIngo Weinhold		size.height = max_c(size.height, minHeight);
6009ecf9d1cSIngo Weinhold		verticalLayouter = fHeightForWidthVerticalLayouter;
6019ecf9d1cSIngo Weinhold	} else
6029ecf9d1cSIngo Weinhold		verticalLayouter = fVerticalLayouter;
6031f9fd6d8SStephan Aßmus
6049ecf9d1cSIngo Weinhold	verticalLayouter->Layout(fVerticalLayoutInfo, size.height);
6059ecf9d1cSIngo Weinhold
6069ecf9d1cSIngo Weinhold	float xOffset = fLeftInset;
6079ecf9d1cSIngo Weinhold	float yOffset = fTopInset;
6089ecf9d1cSIngo Weinhold	float splitterWidth = 0;	// pixel counts, no distances
6099ecf9d1cSIngo Weinhold	float splitterHeight = 0;	//
6109ecf9d1cSIngo Weinhold	float xSpacing = 0;
6119ecf9d1cSIngo Weinhold	float ySpacing = 0;
6129ecf9d1cSIngo Weinhold	if (fOrientation == B_HORIZONTAL) {
6139ecf9d1cSIngo Weinhold		splitterWidth = fSplitterSize;
6149ecf9d1cSIngo Weinhold		splitterHeight = size.height + 1;
6159ecf9d1cSIngo Weinhold		xSpacing = fSpacing;
6169ecf9d1cSIngo Weinhold	} else {
6179ecf9d1cSIngo Weinhold		splitterWidth = size.width + 1;
6189ecf9d1cSIngo Weinhold		splitterHeight = fSplitterSize;
6199ecf9d1cSIngo Weinhold		ySpacing = fSpacing;
6209ecf9d1cSIngo Weinhold	}
6219ecf9d1cSIngo Weinhold
6229ecf9d1cSIngo Weinhold	int itemCount = CountItems();
6239ecf9d1cSIngo Weinhold	for (int i = 0; i < itemCount; i++) {
6249ecf9d1cSIngo Weinhold		// layout the splitter
6259ecf9d1cSIngo Weinhold		if (i > 0) {
6269ecf9d1cSIngo Weinhold			SplitterItem* splitterItem = _SplitterItemAt(i - 1);
6279ecf9d1cSIngo Weinhold
6289ecf9d1cSIngo Weinhold			_LayoutItem(splitterItem, BRect(xOffset, yOffset,
6299ecf9d1cSIngo Weinhold				xOffset + splitterWidth - 1, yOffset + splitterHeight - 1),
6309ecf9d1cSIngo Weinhold				true);
6319ecf9d1cSIngo Weinhold
6329ecf9d1cSIngo Weinhold			if (fOrientation == B_HORIZONTAL)
6339ecf9d1cSIngo Weinhold				xOffset += splitterWidth + xSpacing;
6349ecf9d1cSIngo Weinhold			else
6359ecf9d1cSIngo Weinhold				yOffset += splitterHeight + ySpacing;
6369ecf9d1cSIngo Weinhold		}
6379ecf9d1cSIngo Weinhold
6389ecf9d1cSIngo Weinhold		// layout the item
6399ecf9d1cSIngo Weinhold		BLayoutItem* item = ItemAt(i);
6409ecf9d1cSIngo Weinhold		int32 visibleIndex = fVisibleItems.IndexOf(item);
6419ecf9d1cSIngo Weinhold		if (visibleIndex < 0) {
6429ecf9d1cSIngo Weinhold			_LayoutItem(item, BRect(), false);
6439ecf9d1cSIngo Weinhold			continue;
6449ecf9d1cSIngo Weinhold		}
6459ecf9d1cSIngo Weinhold
6469ecf9d1cSIngo Weinhold		// get the dimensions of the item
6479ecf9d1cSIngo Weinhold		float width = fHorizontalLayoutInfo->ElementSize(visibleIndex);
6489ecf9d1cSIngo Weinhold		float height = fVerticalLayoutInfo->ElementSize(visibleIndex);
6499ecf9d1cSIngo Weinhold
6509ecf9d1cSIngo Weinhold		// place the component
6519ecf9d1cSIngo Weinhold		_LayoutItem(item, BRect(xOffset, yOffset, xOffset + width,
6529ecf9d1cSIngo Weinhold			yOffset + height), true);
6539ecf9d1cSIngo Weinhold
6549ecf9d1cSIngo Weinhold		if (fOrientation == B_HORIZONTAL)
6559ecf9d1cSIngo Weinhold			xOffset += width + xSpacing + 1;
6569ecf9d1cSIngo Weinhold		else
6579ecf9d1cSIngo Weinhold			yOffset += height + ySpacing + 1;
6589ecf9d1cSIngo Weinhold	}
6599ecf9d1cSIngo Weinhold
6609ecf9d1cSIngo Weinhold	fLayoutValid = true;
6619ecf9d1cSIngo Weinhold}
6629ecf9d1cSIngo Weinhold
6634b20c303SIngo Weinhold
6649ecf9d1cSIngo WeinholdBRect
6659ecf9d1cSIngo WeinholdBSplitLayout::SplitterItemFrame(int32 index) const
6669ecf9d1cSIngo Weinhold{
6679ecf9d1cSIngo Weinhold	if (SplitterItem* item = _SplitterItemAt(index))
6689ecf9d1cSIngo Weinhold		return item->Frame();
6699ecf9d1cSIngo Weinhold	return BRect();
6709ecf9d1cSIngo Weinhold}
6719ecf9d1cSIngo Weinhold
6724b20c303SIngo Weinhold
6731f9fd6d8SStephan Aßmusbool
6741f9fd6d8SStephan AßmusBSplitLayout::IsAboveSplitter(const BPoint& point) const
6751f9fd6d8SStephan Aßmus{
6761f9fd6d8SStephan Aßmus	return _SplitterItemAt(point) != NULL;
6771f9fd6d8SStephan Aßmus}
6781f9fd6d8SStephan Aßmus
6794b20c303SIngo Weinhold
6809ecf9d1cSIngo Weinholdbool
6819ecf9d1cSIngo WeinholdBSplitLayout::StartDraggingSplitter(BPoint point)
6829ecf9d1cSIngo Weinhold{
6839ecf9d1cSIngo Weinhold	StopDraggingSplitter();
6849ecf9d1cSIngo Weinhold
6859ecf9d1cSIngo Weinhold	// Layout must be valid. Bail out, if it isn't.
6869ecf9d1cSIngo Weinhold	if (!fLayoutValid)
6879ecf9d1cSIngo Weinhold		return false;
6889ecf9d1cSIngo Weinhold
6899ecf9d1cSIngo Weinhold	// Things shouldn't be draggable, if we have a >= max layout.
6901d6c7b6cSAlex Wilson	BSize size = _SubtractInsets(LayoutArea().Size());
6916eb09230SMichael Lotz	if ((fOrientation == B_HORIZONTAL && size.width >= fMax.width)
6926eb09230SMichael Lotz		|| (fOrientation == B_VERTICAL && size.height >= fMax.height)) {
6939ecf9d1cSIngo Weinhold		return false;
6949ecf9d1cSIngo Weinhold	}
6959ecf9d1cSIngo Weinhold
6963756e259SRene Gollent	int32 index = -1;
6973756e259SRene Gollent	if (_SplitterItemAt(point, &index) != NULL) {
6981d6c7b6cSAlex Wilson		fDraggingStartPoint = Owner()->ConvertToScreen(point);
6991f9fd6d8SStephan Aßmus		fDraggingStartValue = _SplitterValue(index);
7001f9fd6d8SStephan Aßmus		fDraggingCurrentValue = fDraggingStartValue;
7011f9fd6d8SStephan Aßmus		fDraggingSplitterIndex = index;
7029ecf9d1cSIngo Weinhold
7031f9fd6d8SStephan Aßmus		return true;
7049ecf9d1cSIngo Weinhold	}
7059ecf9d1cSIngo Weinhold
7069ecf9d1cSIngo Weinhold	return false;
7079ecf9d1cSIngo Weinhold}
7089ecf9d1cSIngo Weinhold
7094b20c303SIngo Weinhold
7109ecf9d1cSIngo Weinholdbool
7119ecf9d1cSIngo WeinholdBSplitLayout::DragSplitter(BPoint point)
7129ecf9d1cSIngo Weinhold{
7139ecf9d1cSIngo Weinhold	if (fDraggingSplitterIndex < 0)
7149ecf9d1cSIngo Weinhold		return false;
7159ecf9d1cSIngo Weinhold
7161d6c7b6cSAlex Wilson	point = Owner()->ConvertToScreen(point);
7179ecf9d1cSIngo Weinhold
7189ecf9d1cSIngo Weinhold	int32 valueDiff;
7199ecf9d1cSIngo Weinhold	if (fOrientation == B_HORIZONTAL)
7209ecf9d1cSIngo Weinhold		valueDiff = int32(point.x - fDraggingStartPoint.x);
7219ecf9d1cSIngo Weinhold	else
7229ecf9d1cSIngo Weinhold		valueDiff = int32(point.y - fDraggingStartPoint.y);
7239ecf9d1cSIngo Weinhold
7249ecf9d1cSIngo Weinhold	return _SetSplitterValue(fDraggingSplitterIndex,
7259ecf9d1cSIngo Weinhold		fDraggingStartValue + valueDiff);
7269ecf9d1cSIngo Weinhold}
7279ecf9d1cSIngo Weinhold
7284b20c303SIngo Weinhold
7299ecf9d1cSIngo Weinholdbool
7309ecf9d1cSIngo WeinholdBSplitLayout::StopDraggingSplitter()
7319ecf9d1cSIngo Weinhold{
7329ecf9d1cSIngo Weinhold	if (fDraggingSplitterIndex < 0)
7339ecf9d1cSIngo Weinhold		return false;
7349ecf9d1cSIngo Weinhold
7359ecf9d1cSIngo Weinhold	// update the item weights
7369ecf9d1cSIngo Weinhold	_UpdateSplitterWeights();
7379ecf9d1cSIngo Weinhold
7389ecf9d1cSIngo Weinhold	fDraggingSplitterIndex = -1;
7399ecf9d1cSIngo Weinhold
7409ecf9d1cSIngo Weinhold	return true;
7419ecf9d1cSIngo Weinhold}
7429ecf9d1cSIngo Weinhold
7434b20c303SIngo Weinhold
7449ecf9d1cSIngo Weinholdint32
7459ecf9d1cSIngo WeinholdBSplitLayout::DraggedSplitter() const
7469ecf9d1cSIngo Weinhold{
7479ecf9d1cSIngo Weinhold	return fDraggingSplitterIndex;
7489ecf9d1cSIngo Weinhold}
7499ecf9d1cSIngo Weinhold
7504b20c303SIngo Weinhold
7514b20c303SIngo Weinholdstatus_t
7524b20c303SIngo WeinholdBSplitLayout::Archive(BMessage* into, bool deep) const
7534b20c303SIngo Weinhold{
7544b20c303SIngo Weinhold	BArchiver archiver(into);
7551d6c7b6cSAlex Wilson	status_t err = BAbstractLayout::Archive(into, deep);
7564b20c303SIngo Weinhold
7574b20c303SIngo Weinhold	if (err == B_OK)
7584a254e4dSAlex Wilson		err = into->AddBool(kIsVerticalField, fOrientation == B_VERTICAL);
7594b20c303SIngo Weinhold
7604a254e4dSAlex Wilson	if (err == B_OK) {
7614a254e4dSAlex Wilson		BRect insets(fLeftInset, fTopInset, fRightInset, fBottomInset);
7624a254e4dSAlex Wilson		err = into->AddRect(kInsetsField, insets);
7634a254e4dSAlex Wilson	}
7644b20c303SIngo Weinhold
7654b20c303SIngo Weinhold	if (err == B_OK)
7664b20c303SIngo Weinhold		err = into->AddFloat(kSplitterSizeField, fSplitterSize);
7674b20c303SIngo Weinhold
7684b20c303SIngo Weinhold	if (err == B_OK)
7694b20c303SIngo Weinhold		err = into->AddFloat(kSpacingField, fSpacing);
7704b20c303SIngo Weinhold
7714b20c303SIngo Weinhold	return archiver.Finish(err);
7724b20c303SIngo Weinhold}
7734b20c303SIngo Weinhold
7744b20c303SIngo Weinhold
7754b20c303SIngo WeinholdBArchivable*
7764b20c303SIngo WeinholdBSplitLayout::Instantiate(BMessage* from)
7774b20c303SIngo Weinhold{
7784b20c303SIngo Weinhold	if (validate_instantiation(from, "BSplitLayout"))
7794b20c303SIngo Weinhold		return new(std::nothrow) BSplitLayout(from);
7804b20c303SIngo Weinhold	return NULL;
7814b20c303SIngo Weinhold}
7824b20c303SIngo Weinhold
7834b20c303SIngo Weinhold
7844b20c303SIngo Weinholdstatus_t
7854b20c303SIngo WeinholdBSplitLayout::ItemArchived(BMessage* into, BLayoutItem* item, int32 index) const
7864b20c303SIngo Weinhold{
7876829d417SAlex Wilson	ItemLayoutInfo* info = _ItemLayoutInfo(item);
7884b20c303SIngo Weinhold
7894a254e4dSAlex Wilson	status_t err = into->AddFloat(kItemWeightField, info->weight);
7904b20c303SIngo Weinhold	if (err == B_OK)
7914a254e4dSAlex Wilson		err = into->AddBool(kItemCollapsibleField, info->isCollapsible);
7924b20c303SIngo Weinhold
7934b20c303SIngo Weinhold	return err;
7944b20c303SIngo Weinhold}
7954b20c303SIngo Weinhold
7964b20c303SIngo Weinhold
7974b20c303SIngo Weinholdstatus_t
7984b20c303SIngo WeinholdBSplitLayout::ItemUnarchived(const BMessage* from,
7994b20c303SIngo Weinhold	BLayoutItem* item, int32 index)
8004b20c303SIngo Weinhold{
8014b20c303SIngo Weinhold	ItemLayoutInfo* info = _ItemLayoutInfo(item);
8024a254e4dSAlex Wilson	status_t err = from->FindFloat(kItemWeightField, index, &info->weight);
8034b20c303SIngo Weinhold
8044b20c303SIngo Weinhold	if (err == B_OK) {
8054b20c303SIngo Weinhold		bool* collapsible = &info->isCollapsible;
8064a254e4dSAlex Wilson		err = from->FindBool(kItemCollapsibleField, index, collapsible);
8074b20c303SIngo Weinhold	}
8084b20c303SIngo Weinhold	return err;
8094b20c303SIngo Weinhold}
8104b20c303SIngo Weinhold
8114b20c303SIngo Weinhold
8126829d417SAlex Wilsonbool
8136829d417SAlex WilsonBSplitLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
8149ecf9d1cSIngo Weinhold{
8156829d417SAlex Wilson	ItemLayoutInfo* itemInfo = new(nothrow) ItemLayoutInfo();
8166829d417SAlex Wilson	if (!itemInfo)
8176829d417SAlex Wilson		return false;
8186829d417SAlex Wilson
8199ecf9d1cSIngo Weinhold	if (CountItems() > 1) {
8206829d417SAlex Wilson		SplitterItem* splitter = new(nothrow) SplitterItem(this);
8216829d417SAlex Wilson		ItemLayoutInfo* splitterInfo = new(nothrow) ItemLayoutInfo();
8226829d417SAlex Wilson		if (!splitter || !splitterInfo || !fSplitterItems.AddItem(splitter)) {
8236829d417SAlex Wilson			delete itemInfo;
8246829d417SAlex Wilson			delete splitter;
8256829d417SAlex Wilson			delete splitterInfo;
8266829d417SAlex Wilson			return false;
8276829d417SAlex Wilson		}
8286829d417SAlex Wilson		splitter->SetLayoutData(splitterInfo);
8296829d417SAlex Wilson		SetItemWeight(splitter, 0);
8309ecf9d1cSIngo Weinhold	}
8319ecf9d1cSIngo Weinhold
8326829d417SAlex Wilson	item->SetLayoutData(itemInfo);
8339ecf9d1cSIngo Weinhold	SetItemWeight(item, 1);
8346829d417SAlex Wilson	return true;
8359ecf9d1cSIngo Weinhold}
8369ecf9d1cSIngo Weinhold
8374b20c303SIngo Weinhold
8389ecf9d1cSIngo Weinholdvoid
8396829d417SAlex WilsonBSplitLayout::ItemRemoved(BLayoutItem* item, int32 atIndex)
8409ecf9d1cSIngo Weinhold{
8419ecf9d1cSIngo Weinhold	if (fSplitterItems.CountItems() > 0) {
8429ecf9d1cSIngo Weinhold		SplitterItem* splitterItem = (SplitterItem*)fSplitterItems.RemoveItem(
8439ecf9d1cSIngo Weinhold			fSplitterItems.CountItems() - 1);
8446829d417SAlex Wilson		delete _ItemLayoutInfo(splitterItem);
8459ecf9d1cSIngo Weinhold		delete splitterItem;
8469ecf9d1cSIngo Weinhold	}
8479ecf9d1cSIngo Weinhold
8486829d417SAlex Wilson	delete _ItemLayoutInfo(item);
8499ecf9d1cSIngo Weinhold	item->SetLayoutData(NULL);
8509ecf9d1cSIngo Weinhold}
8519ecf9d1cSIngo Weinhold
8524b20c303SIngo Weinhold
8539ecf9d1cSIngo Weinholdvoid
8549ecf9d1cSIngo WeinholdBSplitLayout::_InvalidateCachedHeightForWidth()
8559ecf9d1cSIngo Weinhold{
8569ecf9d1cSIngo Weinhold	delete fHeightForWidthVerticalLayouter;
8579ecf9d1cSIngo Weinhold	delete fHeightForWidthHorizontalLayoutInfo;
8589ecf9d1cSIngo Weinhold
8599ecf9d1cSIngo Weinhold	fHeightForWidthVerticalLayouter = NULL;
8609ecf9d1cSIngo Weinhold	fHeightForWidthHorizontalLayoutInfo = NULL;
8619ecf9d1cSIngo Weinhold
8629ecf9d1cSIngo Weinhold	fCachedHeightForWidthWidth = -2;
8639ecf9d1cSIngo Weinhold	fHeightForWidthVerticalLayouterWidth = -2;
8649ecf9d1cSIngo Weinhold}
8659ecf9d1cSIngo Weinhold
8664b20c303SIngo Weinhold
8671f9fd6d8SStephan AßmusBSplitLayout::SplitterItem*
8681f9fd6d8SStephan AßmusBSplitLayout::_SplitterItemAt(const BPoint& point, int32* index) const
8691f9fd6d8SStephan Aßmus{
8701f9fd6d8SStephan Aßmus	int32 splitterCount = fSplitterItems.CountItems();
8711f9fd6d8SStephan Aßmus	for (int32 i = 0; i < splitterCount; i++) {
8721f9fd6d8SStephan Aßmus		SplitterItem* splitItem = _SplitterItemAt(i);
8731f9fd6d8SStephan Aßmus		BRect frame = splitItem->Frame();
8741f9fd6d8SStephan Aßmus		if (frame.Contains(point)) {
8751f9fd6d8SStephan Aßmus			if (index != NULL)
8761f9fd6d8SStephan Aßmus				*index = i;
8771f9fd6d8SStephan Aßmus			return splitItem;
8781f9fd6d8SStephan Aßmus		}
8791f9fd6d8SStephan Aßmus	}
8801f9fd6d8SStephan Aßmus	return NULL;
8811f9fd6d8SStephan Aßmus}
8821f9fd6d8SStephan Aßmus
8834b20c303SIngo Weinhold
8849ecf9d1cSIngo WeinholdBSplitLayout::SplitterItem*
8859ecf9d1cSIngo WeinholdBSplitLayout::_SplitterItemAt(int32 index) const
8869ecf9d1cSIngo Weinhold{
8879ecf9d1cSIngo Weinhold	return (SplitterItem*)fSplitterItems.ItemAt(index);
8889ecf9d1cSIngo Weinhold}
8899ecf9d1cSIngo Weinhold
8904b20c303SIngo Weinhold
8919ecf9d1cSIngo Weinholdvoid
8929ecf9d1cSIngo WeinholdBSplitLayout::_GetSplitterValueRange(int32 index, ValueRange& range)
8939ecf9d1cSIngo Weinhold{
8949ecf9d1cSIngo Weinhold	ItemLayoutInfo* previousInfo = _ItemLayoutInfo(ItemAt(index));
8959ecf9d1cSIngo Weinhold	ItemLayoutInfo* nextInfo = _ItemLayoutInfo(ItemAt(index + 1));
8969ecf9d1cSIngo Weinhold	if (fOrientation == B_HORIZONTAL) {
8979ecf9d1cSIngo Weinhold		range.previousMin = (int32)previousInfo->min.width + 1;
8989ecf9d1cSIngo Weinhold		range.previousMax = (int32)previousInfo->max.width + 1;
8999ecf9d1cSIngo Weinhold		range.previousSize = previousInfo->layoutFrame.IntegerWidth() + 1;
9009ecf9d1cSIngo Weinhold		range.nextMin = (int32)nextInfo->min.width + 1;
9019ecf9d1cSIngo Weinhold		range.nextMax = (int32)nextInfo->max.width + 1;
9029ecf9d1cSIngo Weinhold		range.nextSize = nextInfo->layoutFrame.IntegerWidth() + 1;
9039ecf9d1cSIngo Weinhold	} else {
9049ecf9d1cSIngo Weinhold		range.previousMin = (int32)previousInfo->min.height + 1;
9059ecf9d1cSIngo Weinhold		range.previousMax = (int32)previousInfo->max.height + 1;
9069ecf9d1cSIngo Weinhold		range.previousSize = previousInfo->layoutFrame.IntegerHeight() + 1;
9079ecf9d1cSIngo Weinhold		range.nextMin = (int32)nextInfo->min.height + 1;
9089ecf9d1cSIngo Weinhold		range.nextMax = (int32)nextInfo->max.height + 1;
9099ecf9d1cSIngo Weinhold		range.nextSize = (int32)nextInfo->layoutFrame.IntegerHeight() + 1;
9109ecf9d1cSIngo Weinhold	}
9119ecf9d1cSIngo Weinhold
9129ecf9d1cSIngo Weinhold	range.sumValue = range.previousSize + range.nextSize;
9139ecf9d1cSIngo Weinhold	if (previousInfo->isVisible)
9149ecf9d1cSIngo Weinhold		range.sumValue += (int32)fSpacing;
9159ecf9d1cSIngo Weinhold	if (nextInfo->isVisible)
9169ecf9d1cSIngo Weinhold		range.sumValue += (int32)fSpacing;
9179ecf9d1cSIngo Weinhold}
9189ecf9d1cSIngo Weinhold
9194b20c303SIngo Weinhold
9209ecf9d1cSIngo Weinholdint32
9219ecf9d1cSIngo WeinholdBSplitLayout::_SplitterValue(int32 index) const
9229ecf9d1cSIngo Weinhold{
9239ecf9d1cSIngo Weinhold	ItemLayoutInfo* info = _ItemLayoutInfo(ItemAt(index));
9249ecf9d1cSIngo Weinhold	if (info && info->isVisible) {
9259ecf9d1cSIngo Weinhold		if (fOrientation == B_HORIZONTAL)
9269ecf9d1cSIngo Weinhold			return info->layoutFrame.IntegerWidth() + 1 + (int32)fSpacing;
9279ecf9d1cSIngo Weinhold		else
9289ecf9d1cSIngo Weinhold			return info->layoutFrame.IntegerHeight() + 1 + (int32)fSpacing;
9299ecf9d1cSIngo Weinhold	} else
9309ecf9d1cSIngo Weinhold		return 0;
9319ecf9d1cSIngo Weinhold}
9329ecf9d1cSIngo Weinhold
9334b20c303SIngo Weinhold
9349ecf9d1cSIngo Weinholdvoid
9359ecf9d1cSIngo WeinholdBSplitLayout::_LayoutItem(BLayoutItem* item, BRect frame, bool visible)
9369ecf9d1cSIngo Weinhold{
9379ecf9d1cSIngo Weinhold	// update the layout frame
9389ecf9d1cSIngo Weinhold	ItemLayoutInfo* info = _ItemLayoutInfo(item);
9399ecf9d1cSIngo Weinhold	info->isVisible = visible;
9409ecf9d1cSIngo Weinhold	if (visible)
9419ecf9d1cSIngo Weinhold		info->layoutFrame = frame;
9429ecf9d1cSIngo Weinhold	else
9439ecf9d1cSIngo Weinhold		info->layoutFrame = BRect(0, 0, -1, -1);
9449ecf9d1cSIngo Weinhold
9459ecf9d1cSIngo Weinhold	// update min/max
9469ecf9d1cSIngo Weinhold	info->min = item->MinSize();
9479ecf9d1cSIngo Weinhold	info->max = item->MaxSize();
9489ecf9d1cSIngo Weinhold
9499ecf9d1cSIngo Weinhold	if (item->HasHeightForWidth()) {
9501d6c7b6cSAlex Wilson		BSize size = _SubtractInsets(LayoutArea().Size());
9519ecf9d1cSIngo Weinhold		float minHeight, maxHeight;
9529ecf9d1cSIngo Weinhold		item->GetHeightForWidth(size.width, &minHeight, &maxHeight, NULL);
9539ecf9d1cSIngo Weinhold		info->min.height = max_c(info->