103069455SIngo Weinhold/*
203069455SIngo Weinhold * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz
303069455SIngo Weinhold * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz
48d9b6ef4SClemens Zeidler * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
503069455SIngo Weinhold * Distributed under the terms of the MIT License.
603069455SIngo Weinhold */
7f0307e76SAlex Wilson
8f0307e76SAlex Wilson
98d9b6ef4SClemens Zeidler#include "ALMLayout.h"
10248bbad2SClemens Zeidler
11a25ffa4fSAlex Wilson
12d10cb215SAlex Wilson#include <stdio.h>
13b7630c4cSczeidler#include <vector>
14248bbad2SClemens Zeidler
15c761a8a6SAlex Wilson#include <AutoDeleter.h>
1675e2dcf8SAlex Wilson#include <ControlLook.h>
1775e2dcf8SAlex Wilson
18ef93b55dSClemens Zeidler#include "RowColumnManager.h"
19419fe0b8SAlex Wilson#include "SharedSolver.h"
2021f083afSClemens Zeidler#include "ViewLayoutItem.h"
2121f083afSClemens Zeidler
22a101e99aSIngo Weinhold
23c761a8a6SAlex Wilsonusing BPrivate::AutoDeleter;
245440f6feSClemens Zeidlerusing namespace LinearProgramming;
255440f6feSClemens Zeidler
265440f6feSClemens Zeidler
273a3c1d82SClemens Zeidlerconst BSize kUnsetSize(B_SIZE_UNSET, B_SIZE_UNSET);
283a3c1d82SClemens Zeidler
293a3c1d82SClemens Zeidler
3035bf0b5cSAlex Wilsonnamespace {
3135bf0b5cSAlex Wilson
320a5e1307SAlex Wilsonconst char* kSolverField = "BALMLayout:solver";
33015e5f06SAlex Wilsonconst char* kBadLayoutPolicyField = "BALMLayout:policy";
3435bf0b5cSAlex Wilsonconst char* kXTabsField = "BALMLayout:xtabs";
3535bf0b5cSAlex Wilsonconst char* kYTabsField = "BALMLayout:ytabs";
3635bf0b5cSAlex Wilsonconst char* kMyTabsField = "BALMLayout:tabs";
3735bf0b5cSAlex Wilsonconst char* kInsetsField = "BALMLayout:insets";
3835bf0b5cSAlex Wilsonconst char* kSpacingField = "BALMLayout:spacing";
3935bf0b5cSAlex Wilson
40df2ad520SAlex Wilsonconst char* kTabsField = "BALMLayout:item:tabs";
41df2ad520SAlex Wilsonconst char* kItemAspectRatio = "BALMLayout:item:aspect";
42df2ad520SAlex Wilsonconst char* kItemPenalties = "BALMLayout:item:penalties";
43df2ad520SAlex Wilsonconst char* kItemInsets = "BALMLayout:item:insets";
44df2ad520SAlex Wilson
45681f48fcSAlex Wilsonint CompareXTabFunc(const XTab* tab1, const XTab* tab2);
46681f48fcSAlex Wilsonint CompareYTabFunc(const YTab* tab1, const YTab* tab2);
47681f48fcSAlex Wilson
4835bf0b5cSAlex Wilson};
4935bf0b5cSAlex Wilson
50681f48fcSAlex Wilson
51a9761aedSAlex Wilsonnamespace BALM {
52a9761aedSAlex Wilson
5393977272SAlex Wilson
54a9761aedSAlex Wilsontemplate <class T>
55a9761aedSAlex Wilsonstruct BALMLayout::TabAddTransaction {
56a9761aedSAlex Wilson	~TabAddTransaction()
57c761a8a6SAlex Wilson	{
58a9761aedSAlex Wilson		if (fTab)
59a9761aedSAlex Wilson			fLayout->_RemoveSelfFromTab(fTab);
60a9761aedSAlex Wilson		if (fIndex > 0)
61a9761aedSAlex Wilson			_TabList()->RemoveItemAt(fIndex);
62c761a8a6SAlex Wilson	}
63c761a8a6SAlex Wilson
64a9761aedSAlex Wilson	TabAddTransaction(BALMLayout* layout)
65c761a8a6SAlex Wilson		:
66a9761aedSAlex Wilson		fTab(NULL),
67a9761aedSAlex Wilson		fLayout(layout),
68a9761aedSAlex Wilson		fIndex(-1)
69c761a8a6SAlex Wilson	{
70c761a8a6SAlex Wilson	}
7193977272SAlex Wilson
72a9761aedSAlex Wilson	bool AttempAdd(T* tab)
7393977272SAlex Wilson	{
74a9761aedSAlex Wilson		if (fLayout->_HasTabInLayout(tab))
75a9761aedSAlex Wilson			return true;
76a9761aedSAlex Wilson		if (!fLayout->_AddedTab(tab))
77a9761aedSAlex Wilson			return false;
78a9761aedSAlex Wilson		fTab = tab;
79c761a8a6SAlex Wilson
80a9761aedSAlex Wilson		BObjectList<T>* tabList = _TabList();
81a9761aedSAlex Wilson		int32 index = tabList->CountItems();
82a9761aedSAlex Wilson		if (!tabList->AddItem(tab, index))
83a9761aedSAlex Wilson			return false;
84a9761aedSAlex Wilson		fIndex = index;
85a9761aedSAlex Wilson		return true;
8693977272SAlex Wilson	}
8793977272SAlex Wilson
88a9761aedSAlex Wilson	void Commit()
89c761a8a6SAlex Wilson	{
90a9761aedSAlex Wilson		fTab = NULL;
91a9761aedSAlex Wilson		fIndex = -1;
92c761a8a6SAlex Wilson	}
93c761a8a6SAlex Wilson
94a9761aedSAlex Wilsonprivate:
95a9761aedSAlex Wilson	BObjectList<T>* _TabList();
96a9761aedSAlex Wilson
97a9761aedSAlex Wilson	T*				fTab;
98a9761aedSAlex Wilson	BALMLayout*		fLayout;
99a9761aedSAlex Wilson	int32			fIndex;
100c761a8a6SAlex Wilson};
101c761a8a6SAlex Wilson
102c761a8a6SAlex Wilson
103a9761aedSAlex Wilsontemplate <>
104a9761aedSAlex WilsonBObjectList<XTab>*
105a9761aedSAlex WilsonBALMLayout::TabAddTransaction<XTab>::_TabList()
106a9761aedSAlex Wilson{
107a9761aedSAlex Wilson	return &fLayout->fXTabList;
108a9761aedSAlex Wilson}
109c761a8a6SAlex Wilson
11093977272SAlex Wilson
111a9761aedSAlex Wilsontemplate <>
112a9761aedSAlex WilsonBObjectList<YTab>*
113a9761aedSAlex WilsonBALMLayout::TabAddTransaction<YTab>::_TabList()
114a9761aedSAlex Wilson{
115a9761aedSAlex Wilson	return &fLayout->fYTabList;
116a9761aedSAlex Wilson}
117a9761aedSAlex Wilson
118a9761aedSAlex Wilson
119a9761aedSAlex Wilson}; // end namespace BALM
120c761a8a6SAlex Wilson
121c761a8a6SAlex Wilson
122015e5f06SAlex WilsonBALM::BALMLayout::BadLayoutPolicy::BadLayoutPolicy()
123015e5f06SAlex Wilson{
124015e5f06SAlex Wilson}
125015e5f06SAlex Wilson
126015e5f06SAlex Wilson
127015e5f06SAlex WilsonBALM::BALMLayout::BadLayoutPolicy::BadLayoutPolicy(BMessage* archive)
128015e5f06SAlex Wilson	:
129015e5f06SAlex Wilson	BArchivable(archive)
130015e5f06SAlex Wilson{
131015e5f06SAlex Wilson}
132015e5f06SAlex Wilson
133015e5f06SAlex Wilson
1342bbf8b1fSAlex WilsonBALM::BALMLayout::BadLayoutPolicy::~BadLayoutPolicy()
1352bbf8b1fSAlex Wilson{
1362bbf8b1fSAlex Wilson}
1372bbf8b1fSAlex Wilson
1382bbf8b1fSAlex Wilson
139015e5f06SAlex WilsonBALM::BALMLayout::DefaultPolicy::DefaultPolicy()
140015e5f06SAlex Wilson{
141015e5f06SAlex Wilson}
142015e5f06SAlex Wilson
143015e5f06SAlex Wilson
144015e5f06SAlex WilsonBALM::BALMLayout::DefaultPolicy::DefaultPolicy(BMessage* archive)
145015e5f06SAlex Wilson	:
146015e5f06SAlex Wilson	BadLayoutPolicy(archive)
147015e5f06SAlex Wilson{
148015e5f06SAlex Wilson}
149015e5f06SAlex Wilson
150015e5f06SAlex Wilson
1512bbf8b1fSAlex WilsonBALM::BALMLayout::DefaultPolicy::~DefaultPolicy()
1522bbf8b1fSAlex Wilson{
1532bbf8b1fSAlex Wilson}
1542bbf8b1fSAlex Wilson
1552bbf8b1fSAlex Wilson
1562bbf8b1fSAlex Wilsonbool
15709e87fa3SAlex WilsonBALM::BALMLayout::DefaultPolicy::OnBadLayout(BALMLayout* layout,
15809e87fa3SAlex Wilson	ResultType result, BLayoutContext* context)
1592bbf8b1fSAlex Wilson{
16009e87fa3SAlex Wilson	if (!context)
16109e87fa3SAlex Wilson		return true;
16209e87fa3SAlex Wilson
16309e87fa3SAlex Wilson	if (result == kInfeasible) {
164d10cb215SAlex Wilson		printf("BALMLayout failed to solve your layout!\n");
1652bbf8b1fSAlex Wilson		return false;
1662bbf8b1fSAlex Wilson	} else
1672bbf8b1fSAlex Wilson		return true;
1682bbf8b1fSAlex Wilson}
1692bbf8b1fSAlex Wilson
1702bbf8b1fSAlex Wilson
171015e5f06SAlex Wilsonstatus_t
172015e5f06SAlex WilsonBALM::BALMLayout::DefaultPolicy::Archive(BMessage* archive, bool deep) const
173015e5f06SAlex Wilson{
174015e5f06SAlex Wilson	return BadLayoutPolicy::Archive(archive, deep);
175015e5f06SAlex Wilson}
176015e5f06SAlex Wilson
177015e5f06SAlex Wilson
178015e5f06SAlex WilsonBArchivable*
179015e5f06SAlex WilsonBALM::BALMLayout::DefaultPolicy::Instantiate(BMessage* archive)
180015e5f06SAlex Wilson{
181015e5f06SAlex Wilson	if (validate_instantiation(archive, "BALM::BALMLayout::DefaultPolicy"))
182015e5f06SAlex Wilson		return new DefaultPolicy(archive);
183015e5f06SAlex Wilson	return NULL;
184015e5f06SAlex Wilson}
185015e5f06SAlex Wilson
186015e5f06SAlex Wilson
1876c4a44e3Sczeidlerclass BALMLayout::BALMLayoutSpecListener
1886c4a44e3Sczeidler	: public LinearProgramming::SpecificationListener {
1896c4a44e3Sczeidlerpublic:
1906c4a44e3Sczeidler	BALMLayoutSpecListener(BALMLayout* layout)
1916c4a44e3Sczeidler		:
1926c4a44e3Sczeidler		fLayout(layout)
1936c4a44e3Sczeidler	{
1946c4a44e3Sczeidler	}
1956c4a44e3Sczeidler
1966c4a44e3Sczeidler	void ConstraintRemoved(Constraint* constraint)
1976c4a44e3Sczeidler	{
1986c4a44e3Sczeidler		fLayout->fConstraints.RemoveItem(constraint);
1996c4a44e3Sczeidler	}
2006c4a44e3Sczeidler
2016c4a44e3Sczeidlerprivate:
2026c4a44e3Sczeidler			BALMLayout*			fLayout;
2036c4a44e3Sczeidler};
2046c4a44e3Sczeidler
2056c4a44e3Sczeidler
206b23e9af5SClemens Zeidler/*!
207a101e99aSIngo Weinhold * Constructor.
208a101e99aSIngo Weinhold * Creates new layout engine.
209b23e9af5SClemens Zeidler *
210b23e9af5SClemens Zeidler * If friendLayout is not NULL the solver of the friend layout is used.
211a101e99aSIngo Weinhold */
21275e2dcf8SAlex WilsonBALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout)
2131d6c7b6cSAlex Wilson	:
21475e2dcf8SAlex Wilson	fLeftInset(0),
21575e2dcf8SAlex Wilson	fRightInset(0),
21675e2dcf8SAlex Wilson	fTopInset(0),
21775e2dcf8SAlex Wilson	fBottomInset(0),
2183479e516SAlex Wilson	fHSpacing(BControlLook::ComposeSpacing(hSpacing)),
2192bbf8b1fSAlex Wilson	fVSpacing(BControlLook::ComposeSpacing(vSpacing)),
220681f48fcSAlex Wilson	fXTabsSorted(false),
221681f48fcSAlex Wilson	fYTabsSorted(false),
2222bbf8b1fSAlex Wilson	fBadLayoutPolicy(new DefaultPolicy())
223a101e99aSIngo Weinhold{
22435bf0b5cSAlex Wilson	_SetSolver(friendLayout ? friendLayout->fSolver : new SharedSolver());
225b23e9af5SClemens Zeidler
2266c4a44e3Sczeidler	fSpecListener = new BALMLayoutSpecListener(this);
2276c4a44e3Sczeidler	Solver()->AddListener(fSpecListener);
2286c4a44e3Sczeidler
229fc691d7dSClemens Zeidler	fLeft = AddXTab();
230fc691d7dSClemens Zeidler	fRight = AddXTab();
231fc691d7dSClemens Zeidler	fTop = AddYTab();
232fc691d7dSClemens Zeidler	fBottom = AddYTab();
233b8ec67f4SStephan Aßmus
2347583db5aSClemens Zeidler	// the Left tab is always at x-position 0, and the Top tab is always at
2357583db5aSClemens Zeidler	// y-position 0
236a101e99aSIngo Weinhold	fLeft->SetRange(0, 0);
237a101e99aSIngo Weinhold	fTop->SetRange(0, 0);
238b8ec67f4SStephan Aßmus
239a101e99aSIngo Weinhold	// cached layout values
240a101e99aSIngo Weinhold	// need to be invalidated whenever the layout specification is changed
2413a3c1d82SClemens Zeidler	fMinSize = kUnsetSize;
2423a3c1d82SClemens Zeidler	fMaxSize = kUnsetSize;
2433a3c1d82SClemens Zeidler	fPreferredSize = kUnsetSize;
244a101e99aSIngo Weinhold}
245a101e99aSIngo Weinhold
246a101e99aSIngo Weinhold
24735bf0b5cSAlex WilsonBALMLayout::BALMLayout(BMessage* archive)
24835bf0b5cSAlex Wilson	:
24935bf0b5cSAlex Wilson	BAbstractLayout(BUnarchiver::PrepareArchive(archive)),
25035bf0b5cSAlex Wilson	fSolver(NULL),
25135bf0b5cSAlex Wilson	fLeft(NULL),
25235bf0b5cSAlex Wilson	fRight(NULL),
25335bf0b5cSAlex Wilson	fTop(NULL),
25435bf0b5cSAlex Wilson	fBottom(NULL),
25535bf0b5cSAlex Wilson	fMinSize(kUnsetSize),
25635bf0b5cSAlex Wilson	fMaxSize(kUnsetSize),
25735bf0b5cSAlex Wilson	fPreferredSize(kUnsetSize),
25835bf0b5cSAlex Wilson	fXTabsSorted(false),
25935bf0b5cSAlex Wilson	fYTabsSorted(false),
26035bf0b5cSAlex Wilson	fBadLayoutPolicy(new DefaultPolicy())
26135bf0b5cSAlex Wilson{
26235bf0b5cSAlex Wilson	BUnarchiver unarchiver(archive);
26335bf0b5cSAlex Wilson
26435bf0b5cSAlex Wilson	BRect insets;
26535bf0b5cSAlex Wilson	status_t err = archive->FindRect(kInsetsField, &insets);
26635bf0b5cSAlex Wilson	if (err != B_OK) {
26735bf0b5cSAlex Wilson		unarchiver.Finish(err);
26835bf0b5cSAlex Wilson		return;
26935bf0b5cSAlex Wilson	}
27035bf0b5cSAlex Wilson
27135bf0b5cSAlex Wilson	fLeftInset = insets.left;
27235bf0b5cSAlex Wilson	fRightInset = insets.right;
27335bf0b5cSAlex Wilson	fTopInset = insets.top;
27435bf0b5cSAlex Wilson	fBottomInset = insets.bottom;
27535bf0b5cSAlex Wilson
27635bf0b5cSAlex Wilson
27735bf0b5cSAlex Wilson	BSize spacing;
27835bf0b5cSAlex Wilson	err = archive->FindSize(kSpacingField, &spacing);
27935bf0b5cSAlex Wilson	if (err != B_OK) {
28035bf0b5cSAlex Wilson		unarchiver.Finish(err);
28135bf0b5cSAlex Wilson		return;
28235bf0b5cSAlex Wilson	}
28335bf0b5cSAlex Wilson
28435bf0b5cSAlex Wilson	fHSpacing = spacing.width;
28535bf0b5cSAlex Wilson	fVSpacing = spacing.height;
28635bf0b5cSAlex Wilson
28735bf0b5cSAlex Wilson	int32 tabCount = 0;
28835bf0b5cSAlex Wilson	archive->GetInfo(kXTabsField, NULL, &tabCount);
28935bf0b5cSAlex Wilson	for (int32 i = 0; i < tabCount && err == B_OK; i++)
29035bf0b5cSAlex Wilson		err = unarchiver.EnsureUnarchived(kXTabsField, i);
29135bf0b5cSAlex Wilson
29235bf0b5cSAlex Wilson	archive->GetInfo(kYTabsField, NULL, &tabCount);
29335bf0b5cSAlex Wilson	for (int32 i = 0; i < tabCount && err == B_OK; i++)
29435bf0b5cSAlex Wilson		err = unarchiver.EnsureUnarchived(kYTabsField, i);
29535bf0b5cSAlex Wilson
296015e5f06SAlex Wilson	if (err == B_OK && archive->GetInfo(kBadLayoutPolicyField, NULL) == B_OK)
297015e5f06SAlex Wilson		err = unarchiver.EnsureUnarchived(kBadLayoutPolicyField);
298015e5f06SAlex Wilson
2990a5e1307SAlex Wilson	if (err == B_OK)
3000a5e1307SAlex Wilson		err = unarchiver.EnsureUnarchived(kSolverField);
3010a5e1307SAlex Wilson
30235bf0b5cSAlex Wilson	unarchiver.Finish(err);
3036c4a44e3Sczeidler
3046c4a44e3Sczeidler	fSpecListener = new BALMLayoutSpecListener(this);
3056c4a44e3Sczeidler	Solver()->AddListener(fSpecListener);
30635bf0b5cSAlex Wilson}
30735bf0b5cSAlex Wilson
30835bf0b5cSAlex Wilson
309248bbad2SClemens ZeidlerBALMLayout::~BALMLayout()
310248bbad2SClemens Zeidler{
3116c4a44e3Sczeidler	Solver()->RemoveListener(fSpecListener);
3126c4a44e3Sczeidler	delete fSpecListener;
3136c4a44e3Sczeidler
314ef93b55dSClemens Zeidler	delete fRowColumnManager;
3152bbf8b1fSAlex Wilson	delete fBadLayoutPolicy;
316419fe0b8SAlex Wilson
3176c4a44e3Sczeidler	for (int32 i = 0; i < fConstraints.CountItems(); i++)
3186c4a44e3Sczeidler		Solver()->RemoveConstraint(fConstraints.ItemAt(i), true);
3196c4a44e3Sczeidler
32035bf0b5cSAlex Wilson	if (fSolver) {
32135bf0b5cSAlex Wilson		fSolver->LayoutLeaving(this);
32235bf0b5cSAlex Wilson		fSolver->ReleaseReference();
32335bf0b5cSAlex Wilson	}
324248bbad2SClemens Zeidler}
325248bbad2SClemens Zeidler
326248bbad2SClemens Zeidler
327a101e99aSIngo Weinhold/**
328a101e99aSIngo Weinhold * Adds a new x-tab to the specification.
329b8ec67f4SStephan Aßmus *
330a101e99aSIngo Weinhold * @return the new x-tab
331a101e99aSIngo Weinhold */
33257014d1fSczeidlerBReference<XTab>
333a101e99aSIngo WeinholdBALMLayout::AddXTab()
334a101e99aSIngo Weinhold{
33557014d1fSczeidler	BReference<XTab> tab(new(std::nothrow) XTab(this), true);
336fc691d7dSClemens Zeidler	if (!tab)
337fc691d7dSClemens Zeidler		return NULL;
338419fe0b8SAlex Wilson	if (!Solver()->AddVariable(tab))
339fc691d7dSClemens Zeidler		return NULL;
340fc691d7dSClemens Zeidler
341ef93b55dSClemens Zeidler	fXTabList.AddItem(tab);
342c761a8a6SAlex Wilson	if (!tab->AddedToLayout(this)) {
343c761a8a6SAlex Wilson		fXTabList.RemoveItem(tab);
344c761a8a6SAlex Wilson		return NULL;
345c761a8a6SAlex Wilson	}
346681f48fcSAlex Wilson	fXTabsSorted = false;
347fc691d7dSClemens Zeidler	return tab;
348a101e99aSIngo Weinhold}
349b8ec67f4SStephan Aßmus
350a101e99aSIngo Weinhold
351b50d4ed8SAlex Wilsonvoid
352b50d4ed8SAlex WilsonBALMLayout::AddXTabs(BReference<XTab>* tabs, uint32 count)
353b50d4ed8SAlex Wilson{
354b50d4ed8SAlex Wilson	for (uint32 i = 0; i < count; i++)
355b50d4ed8SAlex Wilson		tabs[i] = AddXTab();
356b50d4ed8SAlex Wilson}
357b50d4ed8SAlex Wilson
358b50d4ed8SAlex Wilson
359b50d4ed8SAlex Wilsonvoid
360b50d4ed8SAlex WilsonBALMLayout::AddYTabs(BReference<YTab>* tabs, uint32 count)
361b50d4ed8SAlex Wilson{
362b50d4ed8SAlex Wilson	for (uint32 i = 0; i < count; i++)
363b50d4ed8SAlex Wilson		tabs[i] = AddYTab();
364b50d4ed8SAlex Wilson}
365b50d4ed8SAlex Wilson
366b50d4ed8SAlex Wilson
367a101e99aSIngo Weinhold/**
368a101e99aSIngo Weinhold * Adds a new y-tab to the specification.
369b8ec67f4SStephan Aßmus *
370a101e99aSIngo Weinhold * @return the new y-tab
371a101e99aSIngo Weinhold */
37257014d1fSczeidlerBReference<YTab>
373a101e99aSIngo WeinholdBALMLayout::AddYTab()
374a101e99aSIngo Weinhold{
37557014d1fSczeidler	BReference<YTab> tab(new(std::nothrow) YTab(this), true);
37657014d1fSczeidler	if (tab.Get() == NULL)
377fc691d7dSClemens Zeidler		return NULL;
378419fe0b8SAlex Wilson	if (!Solver()->AddVariable(tab))
379fc691d7dSClemens Zeidler		return NULL;
380fc691d7dSClemens Zeidler
381ef93b55dSClemens Zeidler	fYTabList.AddItem(tab);
382c761a8a6SAlex Wilson	if (!tab->AddedToLayout(this)) {
383c761a8a6SAlex Wilson		fYTabList.RemoveItem(tab);
384c761a8a6SAlex Wilson		return NULL;
385c761a8a6SAlex Wilson	}
386681f48fcSAlex Wilson	fYTabsSorted = false;
387fc691d7dSClemens Zeidler	return tab;
388a101e99aSIngo Weinhold}
389a101e99aSIngo Weinhold
390a101e99aSIngo Weinhold
391ef93b55dSClemens Zeidlerint32
392ef93b55dSClemens ZeidlerBALMLayout::CountXTabs() const
393a101e99aSIngo Weinhold{
394ef93b55dSClemens Zeidler	return fXTabList.CountItems();
395ef93b55dSClemens Zeidler}
396ef93b55dSClemens Zeidler
397ef93b55dSClemens Zeidler
398ef93b55dSClemens Zeidlerint32
399ef93b55dSClemens ZeidlerBALMLayout::CountYTabs() const
400ef93b55dSClemens Zeidler{
401ef93b55dSClemens Zeidler	return fYTabList.CountItems();
402ef93b55dSClemens Zeidler}
403ef93b55dSClemens Zeidler
404ef93b55dSClemens Zeidler
405ef93b55dSClemens ZeidlerXTab*
406681f48fcSAlex WilsonBALMLayout::XTabAt(int32 index, bool ordered)
407ef93b55dSClemens Zeidler{
408681f48fcSAlex Wilson	if (ordered && !fXTabsSorted) {
409681f48fcSAlex Wilson		Layout();
410681f48fcSAlex Wilson		fXTabList.SortItems(CompareXTabFunc);
411681f48fcSAlex Wilson		fXTabsSorted = true;
412681f48fcSAlex Wilson	}
413ef93b55dSClemens Zeidler	return fXTabList.ItemAt(index);
414ef93b55dSClemens Zeidler}
415ef93b55dSClemens Zeidler
416ef93b55dSClemens Zeidler
417bc7956c7SAlex WilsonXTab*
418bc7956c7SAlex WilsonBALMLayout::XTabAt(int32 index) const
419bc7956c7SAlex Wilson{
420bc7956c7SAlex Wilson	return fXTabList.ItemAt(index);
421bc7956c7SAlex Wilson}
422bc7956c7SAlex Wilson
423bc7956c7SAlex Wilson
424ef93b55dSClemens ZeidlerYTab*
425681f48fcSAlex WilsonBALMLayout::YTabAt(int32 index, bool ordered)
426ef93b55dSClemens Zeidler{
427681f48fcSAlex Wilson	if (ordered && !fYTabsSorted) {
428681f48fcSAlex Wilson		Layout();
429681f48fcSAlex Wilson		fYTabList.SortItems(CompareYTabFunc);
430681f48fcSAlex Wilson		fYTabsSorted = true;
431681f48fcSAlex Wilson	}
432ef93b55dSClemens Zeidler	return fYTabList.ItemAt(index);
433a101e99aSIngo Weinhold}
434a101e99aSIngo Weinhold
435a101e99aSIngo Weinhold
436bc7956c7SAlex WilsonYTab*
437bc7956c7SAlex WilsonBALMLayout::YTabAt(int32 index) const
438bc7956c7SAlex Wilson{
439bc7956c7SAlex Wilson	return fYTabList.ItemAt(index);
440bc7956c7SAlex Wilson}
441bc7956c7SAlex Wilson
442bc7956c7SAlex Wilson
4436c4a44e3Sczeidlerconst XTabList
4446c4a44e3SczeidlerBALMLayout::GetXTabs() const
4456c4a44e3Sczeidler{
4466c4a44e3Sczeidler	return fXTabList;
4476c4a44e3Sczeidler}
4486c4a44e3Sczeidler
4496c4a44e3Sczeidler
4506c4a44e3Sczeidlerconst YTabList
4516c4a44e3SczeidlerBALMLayout::GetYTabs() const
4526c4a44e3Sczeidler{
4536c4a44e3Sczeidler	return fYTabList;
4546c4a44e3Sczeidler}
4556c4a44e3Sczeidler
4566c4a44e3Sczeidler
457d7568eabSczeidlerint32
458d7568eabSczeidlerBALMLayout::IndexOf(XTab* tab, bool ordered)
459d7568eabSczeidler{
460d7568eabSczeidler	if (ordered && !fXTabsSorted) {
461d7568eabSczeidler		Layout();
462d7568eabSczeidler		fXTabList.SortItems(CompareXTabFunc);
463d7568eabSczeidler		fXTabsSorted = true;
464d7568eabSczeidler	}
465d7568eabSczeidler	return fXTabList.IndexOf(tab);
466d7568eabSczeidler}
467d7568eabSczeidler
468d7568eabSczeidler
469d7568eabSczeidlerint32
470d7568eabSczeidlerBALMLayout::IndexOf(YTab* tab, bool ordered)
471d7568eabSczeidler{
472d7568eabSczeidler	if (ordered && !fYTabsSorted) {
473d7568eabSczeidler		Layout();
474d7568eabSczeidler		fYTabList.SortItems(CompareYTabFunc);
475d7568eabSczeidler		fYTabsSorted = true;
476d7568eabSczeidler	}
477d7568eabSczeidler	return fYTabList.IndexOf(tab);
478d7568eabSczeidler}
479d7568eabSczeidler
480d7568eabSczeidler
4816c4a44e3Sczeidlerint32
4826c4a44e3SczeidlerBALMLayout::CountConstraints() const
4836c4a44e3Sczeidler{
4846c4a44e3Sczeidler	return fConstraints.CountItems();
4856c4a44e3Sczeidler}
4866c4a44e3Sczeidler
4876c4a44e3Sczeidler
4886c4a44e3SczeidlerConstraint*
4896c4a44e3SczeidlerBALMLayout::ConstraintAt(int32 index) const
4906c4a44e3Sczeidler{
4916c4a44e3Sczeidler	return fConstraints.ItemAt(index);
4926c4a44e3Sczeidler}
4936c4a44e3Sczeidler
4946c4a44e3Sczeidler
4956c4a44e3Sczeidlerbool
4966c4a44e3SczeidlerBALMLayout::AddConstraint(Constraint* constraint)
4976c4a44e3Sczeidler{
4986c4a44e3Sczeidler	fConstraints.AddItem(constraint);
4996c4a44e3Sczeidler	return Solver()->AddConstraint(constraint);
5006c4a44e3Sczeidler}
5016c4a44e3Sczeidler
5026c4a44e3Sczeidler
5036c4a44e3Sczeidlerbool
5046c4a44e3SczeidlerBALMLayout::RemoveConstraint(Constraint* constraint,
5056c4a44e3Sczeidler	bool deleteConstraint)
5066c4a44e3Sczeidler{
5076c4a44e3Sczeidler	if (!fConstraints.RemoveItem(constraint))
5086c4a44e3Sczeidler		return false;
5096c4a44e3Sczeidler	return Solver()->RemoveConstraint(constraint, deleteConstraint);
5106c4a44e3Sczeidler}
5116c4a44e3Sczeidler
5126c4a44e3Sczeidler
5136c4a44e3SczeidlerConstraint*
5146c4a44e3SczeidlerBALMLayout::AddConstraint(double coeff1, Variable* var1, OperatorType op,
5156c4a44e3Sczeidler	double rightSide, double penaltyNeg, double penaltyPos)
5166c4a44e3Sczeidler{
5176c4a44e3Sczeidler	Constraint* constraint = Solver()->AddConstraint(coeff1, var1, op,
5186c4a44e3Sczeidler		rightSide, penaltyNeg, penaltyPos);
5196c4a44e3Sczeidler	fConstraints.AddItem(constraint);
5206c4a44e3Sczeidler	return constraint;
5216c4a44e3Sczeidler}
5226c4a44e3Sczeidler
5236c4a44e3Sczeidler
5246c4a44e3SczeidlerConstraint*
5256c4a44e3SczeidlerBALMLayout::AddConstraint(double coeff1, Variable* var1, double coeff2,
5266c4a44e3Sczeidler	Variable* var2,	OperatorType op, double rightSide, double penaltyNeg,
5276c4a44e3Sczeidler	double penaltyPos)
5286c4a44e3Sczeidler{
5296c4a44e3Sczeidler	Constraint* constraint = Solver()->AddConstraint(coeff1, var1, coeff2, var2,
5306c4a44e3Sczeidler		op, rightSide, penaltyNeg, penaltyPos);
5316c4a44e3Sczeidler	fConstraints.AddItem(constraint);
5326c4a44e3Sczeidler	return constraint;
5336c4a44e3Sczeidler}
5346c4a44e3Sczeidler
5356c4a44e3SczeidlerConstraint*
5366c4a44e3SczeidlerBALMLayout::AddConstraint(double coeff1, Variable* var1, double coeff2,
5376c4a44e3Sczeidler	Variable* var2, double coeff3, Variable* var3, OperatorType op,
5386c4a44e3Sczeidler	double rightSide, double penaltyNeg, double penaltyPos)
5396c4a44e3Sczeidler{
5406c4a44e3Sczeidler	Constraint* constraint = Solver()->AddConstraint(coeff1, var1, coeff2, var2,
5416c4a44e3Sczeidler		coeff3, var3, op, rightSide, penaltyNeg, penaltyPos);
5426c4a44e3Sczeidler	fConstraints.AddItem(constraint);
5436c4a44e3Sczeidler	return constraint;
5446c4a44e3Sczeidler}
5456c4a44e3Sczeidler
5466c4a44e3Sczeidler
5476c4a44e3SczeidlerConstraint*
5486c4a44e3SczeidlerBALMLayout::AddConstraint(double coeff1, Variable* var1, double coeff2,
5496c4a44e3Sczeidler	Variable* var2, double coeff3, Variable* var3, double coeff4,
5506c4a44e3Sczeidler	Variable* var4, OperatorType op, double rightSide, double penaltyNeg,
5516c4a44e3Sczeidler	double penaltyPos)
5526c4a44e3Sczeidler{
5536c4a44e3Sczeidler	Constraint* constraint = Solver()->AddConstraint(coeff1, var1, coeff2, var2,
5546c4a44e3Sczeidler		coeff3, var3, coeff4, var4, op, rightSide, penaltyNeg, penaltyPos);
5556c4a44e3Sczeidler	fConstraints.AddItem(constraint);
5566c4a44e3Sczeidler	return constraint;
5576c4a44e3Sczeidler}
5586c4a44e3Sczeidler
5596c4a44e3Sczeidler
56035bf0b5cSAlex Wilsonnamespace {
56135bf0b5cSAlex Wilson
56235bf0b5cSAlex Wilson
563681f48fcSAlex Wilsonint
564681f48fcSAlex WilsonCompareXTabFunc(const XTab* tab1, const XTab* tab2)
56557014d1fSczeidler{
56657014d1fSczeidler	if (tab1->Value() < tab2->Value())
56757014d1fSczeidler		return -1;
56857014d1fSczeidler	else if (tab1->Value() == tab2->Value())
56957014d1fSczeidler		return 0;
57057014d1fSczeidler	return 1;
57157014d1fSczeidler}
57257014d1fSczeidler
57357014d1fSczeidler
574681f48fcSAlex Wilsonint
575681f48fcSAlex WilsonCompareYTabFunc(const YTab* tab1, const YTab* tab2)
57657014d1fSczeidler{
57757014d1fSczeidler	if (tab1->Value() < tab2->Value())
57857014d1fSczeidler		return -1;
57957014d1fSczeidler	else if (tab1->Value() == tab2->Value())
58057014d1fSczeidler		return 0;
58157014d1fSczeidler	return 1;
58257014d1fSczeidler}
58357014d1fSczeidler
58457014d1fSczeidler
58535bf0b5cSAlex Wilson}; // end anonymous namespace
586bc7956c7SAlex Wilson
587bc7956c7SAlex Wilson
588a101e99aSIngo Weinhold/**
589a101e99aSIngo Weinhold * Adds a new row to the specification that is glued to the given y-tabs.
590b8ec67f4SStephan Aßmus *
591a101e99aSIngo Weinhold * @param top
592a101e99aSIngo Weinhold * @param bottom
593a101e99aSIngo Weinhold * @return the new row
594a101e99aSIngo Weinhold */
595a101e99aSIngo WeinholdRow*
59657014d1fSczeidlerBALMLayout::AddRow(YTab* _top, YTab* _bottom)
597a101e99aSIngo Weinhold{
59857014d1fSczeidler	BReference<YTab> top = _top;
59957014d1fSczeidler	BReference<YTab> bottom = _bottom;
60057014d1fSczeidler	if (_top == NULL)
601ef93b55dSClemens Zeidler		top = AddYTab();
60257014d1fSczeidler	if (_bottom == NULL)
603ef93b55dSClemens Zeidler		bottom = AddYTab();
604419fe0b8SAlex Wilson	return new(std::nothrow) Row(Solver(), top, bottom);
605a101e99aSIngo Weinhold}
606a101e99aSIngo Weinhold
607a101e99aSIngo Weinhold
608a101e99aSIngo Weinhold/**
609a101e99aSIngo Weinhold * Adds a new column to the specification that is glued to the given x-tabs.
610b8ec67f4SStephan Aßmus *
611a101e99aSIngo Weinhold * @param left
612a101e99aSIngo Weinhold * @param right
613a101e99aSIngo Weinhold * @return the new column
614a101e99aSIngo Weinhold */
615a101e99aSIngo WeinholdColumn*
61657014d1fSczeidlerBALMLayout::AddColumn(XTab* _left, XTab* _right)
617a101e99aSIngo Weinhold{
61857014d1fSczeidler	BReference<XTab> left = _left;
61957014d1fSczeidler	BReference<XTab> right = _right;
62057014d1fSczeidler	if (_left == NULL)
621ef93b55dSClemens Zeidler		left = AddXTab();
62257014d1fSczeidler	if (_right == NULL)
623ef93b55dSClemens Zeidler		right = AddXTab();
624419fe0b8SAlex Wilson	return new(std::nothrow) Column(Solver(), left, right);
625a101e99aSIngo Weinhold}
626a101e99aSIngo Weinhold
627a101e99aSIngo Weinhold
628c3e57dc3SczeidlerArea*
629c3e57dc3SczeidlerBALMLayout::AreaFor(int32 id) const
630c3e57dc3Sczeidler{
631c3e57dc3Sczeidler	int32 areaCount = CountAreas();
632c3e57dc3Sczeidler	for (int32 i = 0; i < areaCount; i++) {
633c3e57dc3Sczeidler		Area* area = AreaAt(i);
634c3e57dc3Sczeidler		if (area->ID() == id)
635c3e57dc3Sczeidler			return area;
636c3e57dc3Sczeidler	}
637c3e57dc3Sczeidler	return NULL;
638c3e57dc3Sczeidler}
639c3e57dc3Sczeidler
640c3e57dc3Sczeidler
6415b6fca06SClemens Zeidler/**
6425b6fca06SClemens Zeidler * Finds the area that contains the given control.
6435b6fca06SClemens Zeidler *
6445b6fca06SClemens Zeidler * @param control	the control to look for
6455b6fca06SClemens Zeidler * @return the area that contains the control
6465b6fca06SClemens Zeidler */
6475b6fca06SClemens ZeidlerArea*
6485b6fca06SClemens ZeidlerBALMLayout::AreaFor(const BView* control) const
6495b6fca06SClemens Zeidler{
6505b6fca06SClemens Zeidler	return AreaFor(ItemAt(IndexOfView(const_cast<BView*>(control))));
6515b6fca06SClemens Zeidler}
6525b6fca06SClemens Zeidler
6535b6fca06SClemens Zeidler
6545b6fca06SClemens ZeidlerArea*
6555b6fca06SClemens ZeidlerBALMLayout::AreaFor(const BLayoutItem* item) const
6565b6fca06SClemens Zeidler{
6575b6fca06SClemens Zeidler	if (!item)
6585b6fca06SClemens Zeidler		return NULL;
6595b6fca06SClemens Zeidler	return static_cast<Area*>(item->LayoutData());
6605b6fca06SClemens Zeidler}
6615b6fca06SClemens Zeidler
6625b6fca06SClemens Zeidler
663b7630c4cSczeidlerint32
664b7630c4cSczeidlerBALMLayout::CountAreas() const
665b7630c4cSczeidler{
666b7630c4cSczeidler	return CountItems();
667b7630c4cSczeidler}
668b7630c4cSczeidler
669b7630c4cSczeidler
670ef93b55dSClemens ZeidlerArea*
671ef93b55dSClemens ZeidlerBALMLayout::AreaAt(int32 index) const
672ef93b55dSClemens Zeidler{
673ef93b55dSClemens Zeidler	return AreaFor(ItemAt(index));
674ef93b55dSClemens Zeidler}
675ef93b55dSClemens Zeidler
676ef93b55dSClemens Zeidler
67770e20761SClemens ZeidlerXTab*
67870e20761SClemens ZeidlerBALMLayout::LeftOf(const BView* view) const
67970e20761SClemens Zeidler{
680ef93b55dSClemens Zeidler	Area* area = AreaFor(view);
681ef93b55dSClemens Zeidler	if (!area)
682ef93b55dSClemens Zeidler		return NULL;
683ef93b55dSClemens Zeidler	return area->Left();
68470e20761SClemens Zeidler}
68570e20761SClemens Zeidler
68670e20761SClemens Zeidler
68770e20761SClemens ZeidlerXTab*
68870e20761SClemens ZeidlerBALMLayout::LeftOf(const BLayoutItem* item) const
68970e20761SClemens Zeidler{
690ef93b55dSClemens Zeidler	Area* area = AreaFor(item);
691ef93b55dSClemens Zeidler	if (!area)
692ef93b55dSClemens Zeidler		return NULL;
693ef93b55dSClemens Zeidler	return area->Left();
69470e20761SClemens Zeidler}
69570e20761SClemens Zeidler
69670e20761SClemens Zeidler
69770e20761SClemens ZeidlerXTab*
69870e20761SClemens ZeidlerBALMLayout::RightOf(const BView* view) const
69970e20761SClemens Zeidler{
700ef93b55dSClemens Zeidler	Area* area = AreaFor(view);
701ef93b55dSClemens Zeidler	if (!area)
702ef93b55dSClemens Zeidler		return NULL;
703ef93b55dSClemens Zeidler	return area->Right();
70470e20761SClemens Zeidler}
70570e20761SClemens Zeidler
70670e20761SClemens Zeidler
70770e20761SClemens ZeidlerXTab*
70870e20761SClemens ZeidlerBALMLayout::RightOf(const BLayoutItem* item) const
70970e20761SClemens Zeidler{
710ef93b55dSClemens Zeidler	Area* area = AreaFor(item);
711ef93b55dSClemens Zeidler	if (!area)
712ef93b55dSClemens Zeidler		return NULL;
713ef93b55dSClemens Zeidler	return area->Right();
71470e20761SClemens Zeidler}
71570e20761SClemens Zeidler
71670e20761SClemens Zeidler
71770e20761SClemens ZeidlerYTab*
71870e20761SClemens ZeidlerBALMLayout::TopOf(const BView* view) const
71970e20761SClemens Zeidler{
720ef93b55dSClemens Zeidler	Area* area = AreaFor(view);
721ef93b55dSClemens Zeidler	if (!area)
722ef93b55dSClemens Zeidler		return NULL;
723ef93b55dSClemens Zeidler	return area->Top();
72470e20761SClemens Zeidler}
72570e20761SClemens Zeidler
72670e20761SClemens Zeidler
72770e20761SClemens ZeidlerYTab*
72870e20761SClemens ZeidlerBALMLayout::TopOf(const BLayoutItem* item) const
72970e20761SClemens Zeidler{
730ef93b55dSClemens Zeidler	Area* area = AreaFor(item);
731ef93b55dSClemens Zeidler	if (!area)
732ef93b55dSClemens Zeidler		return NULL;
733ef93b55dSClemens Zeidler	return area->Top();
73470e20761SClemens Zeidler}
73570e20761SClemens Zeidler
73670e20761SClemens Zeidler
73770e20761SClemens ZeidlerYTab*
73870e20761SClemens ZeidlerBALMLayout::BottomOf(const BView* view) const
73970e20761SClemens Zeidler{
740ef93b55dSClemens Zeidler	Area* area = AreaFor(view);
741ef93b55dSClemens Zeidler	if (!area)
742ef93b55dSClemens Zeidler		return NULL;
743ef93b55dSClemens Zeidler	return area->Bottom();
74470e20761SClemens Zeidler}
74570e20761SClemens Zeidler
74670e20761SClemens Zeidler
74770e20761SClemens ZeidlerYTab*
74870e20761SClemens ZeidlerBALMLayout::BottomOf(const BLayoutItem* item) const
74970e20761SClemens Zeidler{
750ef93b55dSClemens Zeidler	Area* area = AreaFor(item);
751ef93b55dSClemens Zeidler	if (!area)
752ef93b55dSClemens Zeidler		return NULL;
753ef93b55dSClemens Zeidler	return area->Bottom();
75470e20761SClemens Zeidler}
75570e20761SClemens Zeidler
75670e20761SClemens Zeidler
75721f083afSClemens ZeidlerBLayoutItem*
75821f083afSClemens ZeidlerBALMLayout::AddView(BView* child)
75921f083afSClemens Zeidler{
76021f083afSClemens Zeidler	return AddView(-1, child);
76121f083afSClemens Zeidler}
76221f083afSClemens Zeidler
76321f083afSClemens Zeidler
76421f083afSClemens ZeidlerBLayoutItem*
76521f083afSClemens ZeidlerBALMLayout::AddView(int32 index, BView* child)
76621f083afSClemens Zeidler{
76721f083afSClemens Zeidler	return BAbstractLayout::AddView(index, child);
76821f083afSClemens Zeidler}
76921f083afSClemens Zeidler
77021f083afSClemens Zeidler
771a101e99aSIngo Weinhold/**
772a101e99aSIngo Weinhold * Adds a new area to the specification, automatically setting preferred size constraints.
773b8ec67f4SStephan Aßmus *
774a101e99aSIngo Weinhold * @param left			left border
775a101e99aSIngo Weinhold * @param top			top border
776a101e99aSIngo Weinhold * @param right		right border
777a101e99aSIngo Weinhold * @param bottom		bottom border
778a101e99aSIngo Weinhold * @param content		the control which is the area content
779a101e99aSIngo Weinhold * @return the new area
780a101e99aSIngo Weinhold */
781a101e99aSIngo WeinholdArea*
78221f083afSClemens ZeidlerBALMLayout::AddView(BView* view, XTab* left, YTab* top, XTab* right,
78321f083afSClemens Zeidler	YTab* bottom)
784b8ec67f4SStephan Aßmus{
785574533efSAlex Wilson	BLayoutItem* item = _LayoutItemToAdd(view);
78621f083afSClemens Zeidler	Area* area = AddItem(item, left, top, right, bottom);
78721f083afSClemens Zeidler	if (!area) {
788574533efSAlex Wilson		if (item != view->GetLayout())
789574533efSAlex Wilson			delete item;
790248bbad2SClemens Zeidler		return NULL;
79121f083afSClemens Zeidler	}
792a101e99aSIngo Weinhold	return area;
793a101e99aSIngo Weinhold}
794a101e99aSIngo Weinhold
795a101e99aSIngo Weinhold
796a101e99aSIngo Weinhold/**
797a101e99aSIngo Weinhold * Adds a new area to the specification, automatically setting preferred size constraints.
798b8ec67f4SStephan Aßmus *
799a101e99aSIngo Weinhold * @param row			the row that defines the top and bottom border
800a101e99aSIngo Weinhold * @param column		the column that defines the left and right border
801a101e99aSIngo Weinhold * @param content		the control which is the area content
802b8ec67f4SStephan Aßmus * @return the new area
803a101e99aSIngo Weinhold */
804a101e99aSIngo WeinholdArea*
80521f083afSClemens ZeidlerBALMLayout::AddView(BView* view, Row* row, Column* column)
80621f083afSClemens Zeidler{
807574533efSAlex Wilson	BLayoutItem* item = _LayoutItemToAdd(view);
80821f083afSClemens Zeidler	Area* area = AddItem(item, row, column);
80921f083afSClemens Zeidler	if (!area) {
810574533efSAlex Wilson		if (item != view->GetLayout())
811574533efSAlex Wilson			delete item;
81221f083afSClemens Zeidler		return NULL;
81321f083afSClemens Zeidler	}
81421f083afSClemens Zeidler	return area;
81521f083afSClemens Zeidler}
81621f083afSClemens Zeidler
81721f083afSClemens Zeidler
81821f083afSClemens Zeidlerbool
81921f083afSClemens ZeidlerBALMLayout::AddItem(BLayoutItem* item)
82021f083afSClemens Zeidler{
82121f083afSClemens Zeidler	return AddItem(-1, item);
82221f083afSClemens Zeidler}
82321f083afSClemens Zeidler
82421f083afSClemens Zeidler
82521f083afSClemens Zeidlerbool
82621f083afSClemens ZeidlerBALMLayout::AddItem(int32 index, BLayoutItem* item)
82721f083afSClemens Zeidler{
82821f083afSClemens Zeidler	if (!item)
8296751b488SClemens Zeidler		return false;
83021f083afSClemens Zeidler
83121f083afSClemens Zeidler	// simply add the item at the upper right corner of the previous item
83221f083afSClemens Zeidler	// TODO maybe find a more elegant solution
83321f083afSClemens Zeidler	XTab* left = Left();
83421f083afSClemens Zeidler	YTab* top = Top();
83521f083afSClemens Zeidler
83621f083afSClemens Zeidler	// check range
83721f083afSClemens Zeidler	if (index < 0 || index > CountItems())
83821f083afSClemens Zeidler		index = CountItems();
83921f083afSClemens Zeidler
84021f083afSClemens Zeidler	// for index = 0 we already have set the right tabs
84121f083afSClemens Zeidler	if (index != 0) {
84221f083afSClemens Zeidler		BLayoutItem* prevItem = ItemAt(index - 1);
8435b6fca06SClemens Zeidler		Area* area = AreaFor(prevItem);
84421f083afSClemens Zeidler		if (area) {
84521f083afSClemens Zeidler			left = area->Right();
84621f083afSClemens Zeidler			top = area->Top();
84721f083afSClemens Zeidler		}
84821f083afSClemens Zeidler	}
84970e20761SClemens Zeidler	Area* area = AddItem(item, left, top);
85021f083afSClemens Zeidler	return area ? true : false;
85121f083afSClemens Zeidler}
85221f083afSClemens Zeidler
85321f083afSClemens Zeidler
85421f083afSClemens ZeidlerArea*
85535babcf0SczeidlerBALMLayout::AddItem(BLayoutItem* item, XTab* _left, YTab* _top, XTab* _right,
85657014d1fSczeidler	YTab* _bottom)
857a101e99aSIngo Weinhold{
85835babcf0Sczeidler	if ((_left && !_left->IsSuitableFor(this))
85935babcf0Sczeidler			|| (_top && !_top->IsSuitableFor(this))
860c761a8a6SAlex Wilson			|| (_right && !_right->IsSuitableFor(this))
861c761a8a6SAlex Wilson			|| (_bottom && !_bottom->IsSuitableFor(this)))
862c761a8a6SAlex Wilson		debugger("Tab added to unfriendly layout!");
863c761a8a6SAlex Wilson
86457014d1fSczeidler	BReference<XTab> right = _right;
86557014d1fSczeidler	if (right.Get() == NULL)
86670e20761SClemens Zeidler		right = AddXTab();
86757014d1fSczeidler	BReference<YTab> bottom = _bottom;
86857014d1fSczeidler	if (bottom.Get() == NULL)
86970e20761SClemens Zeidler		bottom = AddYTab();
87035babcf0Sczeidler	BReference<XTab> left = _left;
87135babcf0Sczeidler	if (left.Get() == NULL)
87235babcf0Sczeidler		left = AddXTab();
87335babcf0Sczeidler	BReference<YTab> top = _top;
87435babcf0Sczeidler	if (top.Get() == NULL)
87535babcf0Sczeidler		top = AddYTab();
87670e20761SClemens Zeidler
877a9761aedSAlex Wilson	TabAddTransaction<XTab> leftTabAdd(this);
878a9761aedSAlex Wilson	if (!leftTabAdd.AttempAdd(left))
879a9761aedSAlex Wilson		return NULL;
880c761a8a6SAlex Wilson
881a9761aedSAlex Wilson	TabAddTransaction<YTab> topTabAdd(this);
882a9761aedSAlex Wilson	if (!topTabAdd.AttempAdd(top))
883a9761aedSAlex Wilson		return NULL;
88493977272SAlex Wilson
885a9761aedSAlex Wilson	TabAddTransaction<XTab> rightTabAdd(this);
886a9761aedSAlex Wilson	if (!rightTabAdd.AttempAdd(right))
887a9761aedSAlex Wilson		return NULL;
888c761a8a6SAlex Wilson
889a9761aedSAlex Wilson	TabAddTransaction<YTab> bottomTabAdd(this);
890a9761aedSAlex Wilson	if (!bottomTabAdd.AttempAdd(bottom))
891a9761aedSAlex Wilson		return NULL;
89293977272SAlex Wilson
893c761a8a6SAlex Wilson	// Area is added in ItemAdded
89421f083afSClemens Zeidler	if (!BAbstractLayout::AddItem(-1, item))
89521f083afSClemens Zeidler		return NULL;
8965b6fca06SClemens Zeidler	Area* area = AreaFor(item);
897c761a8a6SAlex Wilson	if (!area) {
898c761a8a6SAlex Wilson		RemoveItem(item);
899248bbad2SClemens Zeidler		return NULL;
900c761a8a6SAlex Wilson	}
901248bbad2SClemens Zeidler
9026c4a44e3Sczeidler	fSolver->Invalidate(true);
903419fe0b8SAlex Wilson	area->_Init(Solver(), left, top, right, bottom, fRowColumnManager);
904ef93b55dSClemens Zeidler	fRowColumnManager->AddArea(area);
905c761a8a6SAlex Wilson
906a9761aedSAlex Wilson	leftTabAdd.Commit();
907a9761aedSAlex Wilson	topTabAdd.Commit();
908a9761aedSAlex Wilson	rightTabAdd.Commit();
909a9761aedSAlex Wilson	bottomTabAdd.Commit();
910a101e99aSIngo Weinhold	return area;
911a101e99aSIngo Weinhold}
912a101e99aSIngo Weinhold
913a101e99aSIngo Weinhold
91421f083afSClemens ZeidlerArea*
91521f083afSClemens ZeidlerBALMLayout::AddItem(BLayoutItem* item, Row* row, Column* column)
91621f083afSClemens Zeidler{
91721f083afSClemens Zeidler	if (!BAbstractLayout::AddItem(-1, item))
91821f083afSClemens Zeidler		return NULL;
9195b6fca06SClemens Zeidler	Area* area = AreaFor(item);
92021f083afSClemens Zeidler	if (!area)
92121f083afSClemens Zeidler		return NULL;
92221f083afSClemens Zeidler
9236c4a44e3Sczeidler	fSolver->Invalidate(true);
924419fe0b8SAlex Wilson	area->_Init(Solver(), row, column, fRowColumnManager);
925ef93b55dSClemens Zeidler
926ef93b55dSClemens Zeidler	fRowColumnManager->AddArea(area);
92721f083afSClemens Zeidler	return area;
92821f083afSClemens Zeidler}
92921f083afSClemens Zeidler
93021f083afSClemens Zeidler
931a101e99aSIngo Weinhold/**
932a101e99aSIngo Weinhold * Gets the left variable.
933a101e99aSIngo Weinhold */
934a101e99aSIngo WeinholdXTab*
935a101e99aSIngo WeinholdBALMLayout::Left() const
936a101e99aSIngo Weinhold{
937a101e99aSIngo Weinhold	return fLeft;
938a101e99aSIngo Weinhold}
939a101e99aSIngo Weinhold
940a101e99aSIngo Weinhold
941a101e99aSIngo Weinhold/**
942a101e99aSIngo Weinhold * Gets the right variable.
943a101e99aSIngo Weinhold */
944a101e99aSIngo WeinholdXTab*
945a101e99aSIngo WeinholdBALMLayout::Right() const
946a101e99aSIngo Weinhold{
947a101e99aSIngo Weinhold	return fRight;
948a101e99aSIngo Weinhold}
949a101e99aSIngo Weinhold
950a101e99aSIngo Weinhold
951a101e99aSIngo Weinhold/**
952a101e99aSIngo Weinhold * Gets the top variable.
953a101e99aSIngo Weinhold */
954a101e99aSIngo WeinholdYTab*
955a101e99aSIngo WeinholdBALMLayout::Top() const
956a101e99aSIngo Weinhold{
957a101e99aSIngo Weinhold	return fTop;
958a101e99aSIngo Weinhold}
959a101e99aSIngo Weinhold
960a101e99aSIngo Weinhold
961a101e99aSIngo Weinhold/**
962a101e99aSIngo Weinhold * Gets the bottom variable.
963a101e99aSIngo Weinhold */
964a101e99aSIngo WeinholdYTab*
965a101e99aSIngo WeinholdBALMLayout::Bottom() const
966a101e99aSIngo Weinhold{
967a101e99aSIngo Weinhold	return fBottom;
968a101e99aSIngo Weinhold}
969a101e99aSIngo Weinhold
970a101e99aSIngo Weinhold
9712bbf8b1fSAlex Wilsonvoid
9722bbf8b1fSAlex WilsonBALMLayout::SetBadLayoutPolicy(BadLayoutPolicy* policy)
9732bbf8b1fSAlex Wilson{
9742bbf8b1fSAlex Wilson	if (fBadLayoutPolicy != policy)
9752bbf8b1fSAlex Wilson		delete fBadLayoutPolicy;
9762bbf8b1fSAlex Wilson	if (policy == NULL)
9772bbf8b1fSAlex Wilson		policy = new DefaultPolicy();
9782bbf8b1fSAlex Wilson	fBadLayoutPolicy = policy;
9792bbf8b1fSAlex Wilson}
9802bbf8b1fSAlex Wilson
9812bbf8b1fSAlex Wilson
9822bbf8b1fSAlex Wilsonstruct BALMLayout::BadLayoutPolicy*
9832bbf8b1fSAlex WilsonBALMLayout::GetBadLayoutPolicy() const