2 * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz
3 * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz
4 * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
5 * Distributed under the terms of the MIT License.
15 #include <AutoDeleter.h>
16 #include <ControlLook.h>
18 #include "RowColumnManager.h"
19 #include "SharedSolver.h"
20 #include "ViewLayoutItem.h"
23 using BPrivate::AutoDeleter
;
24 using namespace LinearProgramming
;
27 const BSize
kUnsetSize(B_SIZE_UNSET
, B_SIZE_UNSET
);
32 const char* kSolverField
= "BALMLayout:solver";
33 const char* kBadLayoutPolicyField
= "BALMLayout:policy";
34 const char* kXTabsField
= "BALMLayout:xtabs";
35 const char* kYTabsField
= "BALMLayout:ytabs";
36 const char* kMyTabsField
= "BALMLayout:tabs";
37 const char* kInsetsField
= "BALMLayout:insets";
38 const char* kSpacingField
= "BALMLayout:spacing";
40 const char* kTabsField
= "BALMLayout:item:tabs";
41 const char* kItemAspectRatio
= "BALMLayout:item:aspect";
42 const char* kItemPenalties
= "BALMLayout:item:penalties";
43 const char* kItemInsets
= "BALMLayout:item:insets";
45 int CompareXTabFunc(const XTab
* tab1
, const XTab
* tab2
);
46 int CompareYTabFunc(const YTab
* tab1
, const YTab
* tab2
);
55 struct BALMLayout::TabAddTransaction
{
59 fLayout
->_RemoveSelfFromTab(fTab
);
61 _TabList()->RemoveItemAt(fIndex
);
64 TabAddTransaction(BALMLayout
* layout
)
72 bool AttempAdd(T
* tab
)
74 if (fLayout
->_HasTabInLayout(tab
))
76 if (!fLayout
->_AddedTab(tab
))
80 BObjectList
<T
>* tabList
= _TabList();
81 int32 index
= tabList
->CountItems();
82 if (!tabList
->AddItem(tab
, index
))
95 BObjectList
<T
>* _TabList();
105 BALMLayout::TabAddTransaction
<XTab
>::_TabList()
107 return &fLayout
->fXTabList
;
113 BALMLayout::TabAddTransaction
<YTab
>::_TabList()
115 return &fLayout
->fYTabList
;
119 }; // end namespace BALM
122 BALM::BALMLayout::BadLayoutPolicy::BadLayoutPolicy()
127 BALM::BALMLayout::BadLayoutPolicy::BadLayoutPolicy(BMessage
* archive
)
134 BALM::BALMLayout::BadLayoutPolicy::~BadLayoutPolicy()
139 BALM::BALMLayout::DefaultPolicy::DefaultPolicy()
144 BALM::BALMLayout::DefaultPolicy::DefaultPolicy(BMessage
* archive
)
146 BadLayoutPolicy(archive
)
151 BALM::BALMLayout::DefaultPolicy::~DefaultPolicy()
157 BALM::BALMLayout::DefaultPolicy::OnBadLayout(BALMLayout
* layout
,
158 ResultType result
, BLayoutContext
* context
)
163 if (result
== kInfeasible
) {
164 printf("BALMLayout failed to solve your layout!\n");
172 BALM::BALMLayout::DefaultPolicy::Archive(BMessage
* archive
, bool deep
) const
174 return BadLayoutPolicy::Archive(archive
, deep
);
179 BALM::BALMLayout::DefaultPolicy::Instantiate(BMessage
* archive
)
181 if (validate_instantiation(archive
, "BALM::BALMLayout::DefaultPolicy"))
182 return new DefaultPolicy(archive
);
187 class BALMLayout::BALMLayoutSpecListener
188 : public LinearProgramming::SpecificationListener
{
190 BALMLayoutSpecListener(BALMLayout
* layout
)
196 void ConstraintRemoved(Constraint
* constraint
)
198 fLayout
->fConstraints
.RemoveItem(constraint
);
208 * Creates new layout engine.
210 * If friendLayout is not NULL the solver of the friend layout is used.
212 BALMLayout::BALMLayout(float hSpacing
, float vSpacing
, BALMLayout
* friendLayout
)
218 fHSpacing(BControlLook::ComposeSpacing(hSpacing
)),
219 fVSpacing(BControlLook::ComposeSpacing(vSpacing
)),
222 fBadLayoutPolicy(new DefaultPolicy())
224 _SetSolver(friendLayout
? friendLayout
->fSolver
: new SharedSolver());
226 fSpecListener
= new BALMLayoutSpecListener(this);
227 Solver()->AddListener(fSpecListener
);
234 // the Left tab is always at x-position 0, and the Top tab is always at
236 fLeft
->SetRange(0, 0);
237 fTop
->SetRange(0, 0);
239 // cached layout values
240 // need to be invalidated whenever the layout specification is changed
241 fMinSize
= kUnsetSize
;
242 fMaxSize
= kUnsetSize
;
243 fPreferredSize
= kUnsetSize
;
247 BALMLayout::BALMLayout(BMessage
* archive
)
249 BAbstractLayout(BUnarchiver::PrepareArchive(archive
)),
255 fMinSize(kUnsetSize
),
256 fMaxSize(kUnsetSize
),
257 fPreferredSize(kUnsetSize
),
260 fBadLayoutPolicy(new DefaultPolicy())
262 BUnarchiver
unarchiver(archive
);
265 status_t err
= archive
->FindRect(kInsetsField
, &insets
);
267 unarchiver
.Finish(err
);
271 fLeftInset
= insets
.left
;
272 fRightInset
= insets
.right
;
273 fTopInset
= insets
.top
;
274 fBottomInset
= insets
.bottom
;
278 err
= archive
->FindSize(kSpacingField
, &spacing
);
280 unarchiver
.Finish(err
);
284 fHSpacing
= spacing
.width
;
285 fVSpacing
= spacing
.height
;
288 archive
->GetInfo(kXTabsField
, NULL
, &tabCount
);
289 for (int32 i
= 0; i
< tabCount
&& err
== B_OK
; i
++)
290 err
= unarchiver
.EnsureUnarchived(kXTabsField
, i
);
292 archive
->GetInfo(kYTabsField
, NULL
, &tabCount
);
293 for (int32 i
= 0; i
< tabCount
&& err
== B_OK
; i
++)
294 err
= unarchiver
.EnsureUnarchived(kYTabsField
, i
);
296 if (err
== B_OK
&& archive
->GetInfo(kBadLayoutPolicyField
, NULL
) == B_OK
)
297 err
= unarchiver
.EnsureUnarchived(kBadLayoutPolicyField
);
300 err
= unarchiver
.EnsureUnarchived(kSolverField
);
302 unarchiver
.Finish(err
);
304 fSpecListener
= new BALMLayoutSpecListener(this);
305 Solver()->AddListener(fSpecListener
);
309 BALMLayout::~BALMLayout()
311 Solver()->RemoveListener(fSpecListener
);
312 delete fSpecListener
;
314 delete fRowColumnManager
;
315 delete fBadLayoutPolicy
;
317 for (int32 i
= 0; i
< fConstraints
.CountItems(); i
++)
318 Solver()->RemoveConstraint(fConstraints
.ItemAt(i
), true);
321 fSolver
->LayoutLeaving(this);
322 fSolver
->ReleaseReference();
328 * Adds a new x-tab to the specification.
330 * @return the new x-tab
333 BALMLayout::AddXTab()
335 BReference
<XTab
> tab(new(std::nothrow
) XTab(this), true);
338 if (!Solver()->AddVariable(tab
))
341 fXTabList
.AddItem(tab
);
342 if (!tab
->AddedToLayout(this)) {
343 fXTabList
.RemoveItem(tab
);
346 fXTabsSorted
= false;
352 BALMLayout::AddXTabs(BReference
<XTab
>* tabs
, uint32 count
)
354 for (uint32 i
= 0; i
< count
; i
++)
360 BALMLayout::AddYTabs(BReference
<YTab
>* tabs
, uint32 count
)
362 for (uint32 i
= 0; i
< count
; i
++)
368 * Adds a new y-tab to the specification.
370 * @return the new y-tab
373 BALMLayout::AddYTab()
375 BReference
<YTab
> tab(new(std::nothrow
) YTab(this), true);
376 if (tab
.Get() == NULL
)
378 if (!Solver()->AddVariable(tab
))
381 fYTabList
.AddItem(tab
);
382 if (!tab
->AddedToLayout(this)) {
383 fYTabList
.RemoveItem(tab
);
386 fYTabsSorted
= false;
392 BALMLayout::CountXTabs() const
394 return fXTabList
.CountItems();
399 BALMLayout::CountYTabs() const
401 return fYTabList
.CountItems();
406 BALMLayout::XTabAt(int32 index
, bool ordered
)
408 if (ordered
&& !fXTabsSorted
) {
410 fXTabList
.SortItems(CompareXTabFunc
);
413 return fXTabList
.ItemAt(index
);
418 BALMLayout::XTabAt(int32 index
) const
420 return fXTabList
.ItemAt(index
);
425 BALMLayout::YTabAt(int32 index
, bool ordered
)
427 if (ordered
&& !fYTabsSorted
) {
429 fYTabList
.SortItems(CompareYTabFunc
);
432 return fYTabList
.ItemAt(index
);
437 BALMLayout::YTabAt(int32 index
) const
439 return fYTabList
.ItemAt(index
);
444 BALMLayout::GetXTabs() const
451 BALMLayout::GetYTabs() const
458 BALMLayout::IndexOf(XTab
* tab
, bool ordered
)
460 if (ordered
&& !fXTabsSorted
) {
462 fXTabList
.SortItems(CompareXTabFunc
);
465 return fXTabList
.IndexOf(tab
);
470 BALMLayout::IndexOf(YTab
* tab
, bool ordered
)
472 if (ordered
&& !fYTabsSorted
) {
474 fYTabList
.SortItems(CompareYTabFunc
);
477 return fYTabList
.IndexOf(tab
);
482 BALMLayout::CountConstraints() const
484 return fConstraints
.CountItems();
489 BALMLayout::ConstraintAt(int32 index
) const
491 return fConstraints
.ItemAt(index
);
496 BALMLayout::AddConstraint(Constraint
* constraint
)
498 fConstraints
.AddItem(constraint
);
499 return Solver()->AddConstraint(constraint
);
504 BALMLayout::RemoveConstraint(Constraint
* constraint
,
505 bool deleteConstraint
)
507 if (!fConstraints
.RemoveItem(constraint
))
509 return Solver()->RemoveConstraint(constraint
, deleteConstraint
);
514 BALMLayout::AddConstraint(double coeff1
, Variable
* var1
, OperatorType op
,
515 double rightSide
, double penaltyNeg
, double penaltyPos
)
517 Constraint
* constraint
= Solver()->AddConstraint(coeff1
, var1
, op
,
518 rightSide
, penaltyNeg
, penaltyPos
);
519 fConstraints
.AddItem(constraint
);
525 BALMLayout::AddConstraint(double coeff1
, Variable
* var1
, double coeff2
,
526 Variable
* var2
, OperatorType op
, double rightSide
, double penaltyNeg
,
529 Constraint
* constraint
= Solver()->AddConstraint(coeff1
, var1
, coeff2
, var2
,
530 op
, rightSide
, penaltyNeg
, penaltyPos
);
531 fConstraints
.AddItem(constraint
);
536 BALMLayout::AddConstraint(double coeff1
, Variable
* var1
, double coeff2
,
537 Variable
* var2
, double coeff3
, Variable
* var3
, OperatorType op
,
538 double rightSide
, double penaltyNeg
, double penaltyPos
)
540 Constraint
* constraint
= Solver()->AddConstraint(coeff1
, var1
, coeff2
, var2
,
541 coeff3
, var3
, op
, rightSide
, penaltyNeg
, penaltyPos
);
542 fConstraints
.AddItem(constraint
);
548 BALMLayout::AddConstraint(double coeff1
, Variable
* var1
, double coeff2
,
549 Variable
* var2
, double coeff3
, Variable
* var3
, double coeff4
,
550 Variable
* var4
, OperatorType op
, double rightSide
, double penaltyNeg
,
553 Constraint
* constraint
= Solver()->AddConstraint(coeff1
, var1
, coeff2
, var2
,
554 coeff3
, var3
, coeff4
, var4
, op
, rightSide
, penaltyNeg
, penaltyPos
);
555 fConstraints
.AddItem(constraint
);
564 CompareXTabFunc(const XTab
* tab1
, const XTab
* tab2
)
566 if (tab1
->Value() < tab2
->Value())
568 else if (tab1
->Value() == tab2
->Value())
575 CompareYTabFunc(const YTab
* tab1
, const YTab
* tab2
)
577 if (tab1
->Value() < tab2
->Value())
579 else if (tab1
->Value() == tab2
->Value())
585 }; // end anonymous namespace
589 * Adds a new row to the specification that is glued to the given y-tabs.
593 * @return the new row
596 BALMLayout::AddRow(YTab
* _top
, YTab
* _bottom
)
598 BReference
<YTab
> top
= _top
;
599 BReference
<YTab
> bottom
= _bottom
;
604 return new(std::nothrow
) Row(Solver(), top
, bottom
);
609 * Adds a new column to the specification that is glued to the given x-tabs.
613 * @return the new column
616 BALMLayout::AddColumn(XTab
* _left
, XTab
* _right
)
618 BReference
<XTab
> left
= _left
;
619 BReference
<XTab
> right
= _right
;
624 return new(std::nothrow
) Column(Solver(), left
, right
);
629 BALMLayout::AreaFor(int32 id
) const
631 int32 areaCount
= CountAreas();
632 for (int32 i
= 0; i
< areaCount
; i
++) {
633 Area
* area
= AreaAt(i
);
634 if (area
->ID() == id
)
642 * Finds the area that contains the given control.
644 * @param control the control to look for
645 * @return the area that contains the control
648 BALMLayout::AreaFor(const BView
* control
) const
650 return AreaFor(ItemAt(IndexOfView(const_cast<BView
*>(control
))));
655 BALMLayout::AreaFor(const BLayoutItem
* item
) const
659 return static_cast<Area
*>(item
->LayoutData());
664 BALMLayout::CountAreas() const
671 BALMLayout::AreaAt(int32 index
) const
673 return AreaFor(ItemAt(index
));
678 BALMLayout::LeftOf(const BView
* view
) const
680 Area
* area
= AreaFor(view
);
688 BALMLayout::LeftOf(const BLayoutItem
* item
) const
690 Area
* area
= AreaFor(item
);
698 BALMLayout::RightOf(const BView
* view
) const
700 Area
* area
= AreaFor(view
);
703 return area
->Right();
708 BALMLayout::RightOf(const BLayoutItem
* item
) const
710 Area
* area
= AreaFor(item
);
713 return area
->Right();
718 BALMLayout::TopOf(const BView
* view
) const
720 Area
* area
= AreaFor(view
);
728 BALMLayout::TopOf(const BLayoutItem
* item
) const
730 Area
* area
= AreaFor(item
);
738 BALMLayout::BottomOf(const BView
* view
) const
740 Area
* area
= AreaFor(view
);
743 return area
->Bottom();
748 BALMLayout::BottomOf(const BLayoutItem
* item
) const
750 Area
* area
= AreaFor(item
);
753 return area
->Bottom();
758 BALMLayout::AddView(BView
* child
)
760 return AddView(-1, child
);
765 BALMLayout::AddView(int32 index
, BView
* child
)
767 return BAbstractLayout::AddView(index
, child
);
772 * Adds a new area to the specification, automatically setting preferred size constraints.
774 * @param left left border
775 * @param top top border
776 * @param right right border
777 * @param bottom bottom border
778 * @param content the control which is the area content
779 * @return the new area
782 BALMLayout::AddView(BView
* view
, XTab
* left
, YTab
* top
, XTab
* right
,
785 BLayoutItem
* item
= _LayoutItemToAdd(view
);
786 Area
* area
= AddItem(item
, left
, top
, right
, bottom
);
788 if (item
!= view
->GetLayout())
797 * Adds a new area to the specification, automatically setting preferred size constraints.
799 * @param row the row that defines the top and bottom border
800 * @param column the column that defines the left and right border
801 * @param content the control which is the area content
802 * @return the new area
805 BALMLayout::AddView(BView
* view
, Row
* row
, Column
* column
)
807 BLayoutItem
* item
= _LayoutItemToAdd(view
);
808 Area
* area
= AddItem(item
, row
, column
);
810 if (item
!= view
->GetLayout())
819 BALMLayout::AddItem(BLayoutItem
* item
)
821 return AddItem(-1, item
);
826 BALMLayout::AddItem(int32 index
, BLayoutItem
* item
)
831 // simply add the item at the upper right corner of the previous item
832 // TODO maybe find a more elegant solution
837 if (index
< 0 || index
> CountItems())
838 index
= CountItems();
840 // for index = 0 we already have set the right tabs
842 BLayoutItem
* prevItem
= ItemAt(index
- 1);
843 Area
* area
= AreaFor(prevItem
);
845 left
= area
->Right();
849 Area
* area
= AddItem(item
, left
, top
);
850 return area
? true : false;
855 BALMLayout::AddItem(BLayoutItem
* item
, XTab
* _left
, YTab
* _top
, XTab
* _right
,
858 if ((_left
&& !_left
->IsSuitableFor(this))
859 || (_top
&& !_top
->IsSuitableFor(this))
860 || (_right
&& !_right
->IsSuitableFor(this))
861 || (_bottom
&& !_bottom
->IsSuitableFor(this)))
862 debugger("Tab added to unfriendly layout!");
864 BReference
<XTab
> right
= _right
;
865 if (right
.Get() == NULL
)
867 BReference
<YTab
> bottom
= _bottom
;
868 if (bottom
.Get() == NULL
)
870 BReference
<XTab
> left
= _left
;
871 if (left
.Get() == NULL
)
873 BReference
<YTab
> top
= _top
;
874 if (top
.Get() == NULL
)
877 TabAddTransaction
<XTab
> leftTabAdd(this);
878 if (!leftTabAdd
.AttempAdd(left
))
881 TabAddTransaction
<YTab
> topTabAdd(this);
882 if (!topTabAdd
.AttempAdd(top
))
885 TabAddTransaction
<XTab
> rightTabAdd(this);
886 if (!rightTabAdd
.AttempAdd(right
))
889 TabAddTransaction
<YTab
> bottomTabAdd(this);
890 if (!bottomTabAdd
.AttempAdd(bottom
))
893 // Area is added in ItemAdded
894 if (!BAbstractLayout::AddItem(-1, item
))
896 Area
* area
= AreaFor(item
);
902 fSolver
->Invalidate(true);
903 area
->_Init(Solver(), left
, top
, right
, bottom
, fRowColumnManager
);
904 fRowColumnManager
->AddArea(area
);
908 rightTabAdd
.Commit();
909 bottomTabAdd
.Commit();
915 BALMLayout::AddItem(BLayoutItem
* item
, Row
* row
, Column
* column
)
917 if (!BAbstractLayout::AddItem(-1, item
))
919 Area
* area
= AreaFor(item
);
923 fSolver
->Invalidate(true);
924 area
->_Init(Solver(), row
, column
, fRowColumnManager
);
926 fRowColumnManager
->AddArea(area
);
932 * Gets the left variable.
935 BALMLayout::Left() const
942 * Gets the right variable.
945 BALMLayout::Right() const
952 * Gets the top variable.
955 BALMLayout::Top() const
962 * Gets the bottom variable.
965 BALMLayout::Bottom() const
972 BALMLayout::SetBadLayoutPolicy(BadLayoutPolicy
* policy
)
974 if (fBadLayoutPolicy
!= policy
)
975 delete fBadLayoutPolicy
;
977 policy
= new DefaultPolicy();
978 fBadLayoutPolicy
= policy
;
982 struct BALMLayout::BadLayoutPolicy
*
983 BALMLayout::GetBadLayoutPolicy() const
985 return fBadLayoutPolicy
;
993 BALMLayout::BaseMinSize()
995 ResultType result
= fSolver
->ValidateMinSize();
996 if (result
!= kOptimal
&& result
!= kUnbounded
)
997 fBadLayoutPolicy
->OnBadLayout(this, result
, NULL
);
1003 * Gets maximum size.
1006 BALMLayout::BaseMaxSize()
1008 ResultType result
= fSolver
->ValidateMaxSize();
1009 if (result
!= kOptimal
&& result
!= kUnbounded
)
1010 fBadLayoutPolicy
->OnBadLayout(this, result
, NULL
);
1016 * Gets preferred size.
1019 BALMLayout::BasePreferredSize()
1021 ResultType result
= fSolver
->ValidatePreferredSize();
1022 if (result
!= kOptimal
)
1023 fBadLayoutPolicy
->OnBadLayout(this, result
, NULL
);
1025 return fPreferredSize
;
1030 * Gets the alignment.
1033 BALMLayout::BaseAlignment()
1035 BAlignment alignment
;
1036 alignment
.SetHorizontal(B_ALIGN_HORIZONTAL_CENTER
);
1037 alignment
.SetVertical(B_ALIGN_VERTICAL_CENTER
);
1043 BALMLayout::Archive(BMessage
* into
, bool deep
) const
1045 BArchiver
archiver(into
);
1046 status_t err
= BAbstractLayout::Archive(into
, deep
);
1048 return archiver
.Finish(err
);
1050 BRect
insets(fLeftInset
, fTopInset
, fRightInset
, fBottomInset
);
1051 err
= into
->AddRect(kInsetsField
, insets
);
1053 return archiver
.Finish(err
);
1055 BSize
spacing(fHSpacing
, fVSpacing
);
1056 err
= into
->AddSize(kSpacingField
, spacing
);
1058 return archiver
.Finish(err
);
1061 for (int32 i
= CountXTabs() - 1; i
>= 0 && err
== B_OK
; i
--)
1062 err
= archiver
.AddArchivable(kXTabsField
, XTabAt(i
));
1064 for (int32 i
= CountYTabs() - 1; i
>= 0 && err
== B_OK
; i
--)
1065 err
= archiver
.AddArchivable(kYTabsField
, YTabAt(i
));
1067 err
= archiver
.AddArchivable(kBadLayoutPolicyField
, fBadLayoutPolicy
);
1071 err
= archiver
.AddArchivable(kSolverField
, fSolver
);
1074 err
= archiver
.AddArchivable(kMyTabsField
, fLeft
);
1076 err
= archiver
.AddArchivable(kMyTabsField
, fTop
);
1078 err
= archiver
.AddArchivable(kMyTabsField
, fRight
);
1080 err
= archiver
.AddArchivable(kMyTabsField
, fBottom
);
1082 return archiver
.Finish(err
);
1087 BALMLayout::Instantiate(BMessage
* from
)
1089 if (validate_instantiation(from
, "BALM::BALMLayout"))
1090 return new BALMLayout(from
);
1096 BALMLayout::ItemArchived(BMessage
* into
, BLayoutItem
* item
, int32 index
) const
1098 BArchiver
archiver(into
);
1099 status_t err
= BAbstractLayout::ItemArchived(into
, item
, index
);
1103 Area
* area
= AreaFor(item
);
1104 err
= into
->AddSize(kItemPenalties
, area
->fShrinkPenalties
);
1106 err
= into
->AddSize(kItemPenalties
, area
->fGrowPenalties
);
1108 err
= into
->AddSize(kItemInsets
, area
->fLeftTopInset
);
1110 err
= into
->AddSize(kItemInsets
, area
->fRightBottomInset
);
1112 err
= into
->AddDouble(kItemAspectRatio
, area
->fContentAspectRatio
);
1114 err
= archiver
.AddArchivable(kTabsField
, area
->Left());
1116 archiver
.AddArchivable(kTabsField
, area
->Top());
1118 archiver
.AddArchivable(kTabsField
, area
->Right());
1120 archiver
.AddArchivable(kTabsField
, area
->Bottom());
1127 BALMLayout::ItemUnarchived(const BMessage
* from
, BLayoutItem
* item
,
1130 BUnarchiver
unarchiver(from
);
1131 status_t err
= BAbstractLayout::ItemUnarchived(from
, item
, index
);
1135 Area
* area
= AreaFor(item
);
1140 err
= unarchiver
.FindObject(kTabsField
, index
* 4, left
);
1142 err
= unarchiver
.FindObject(kTabsField
, index
* 4 + 1, top
);
1144 err
= unarchiver
.FindObject(kTabsField
, index
* 4 + 2, right
);
1146 err
= unarchiver
.FindObject(kTabsField
, index
* 4 + 3, bottom
);
1151 area
->_Init(Solver(), left
, top
, right
, bottom
, fRowColumnManager
);
1152 fRowColumnManager
->AddArea(area
);
1154 err
= from
->FindSize(kItemPenalties
, index
* 2, &area
->fShrinkPenalties
);
1158 err
= from
->FindSize(kItemPenalties
, index
* 2 + 1, &area
->fGrowPenalties
);
1162 err
= from
->FindSize(kItemInsets
, index
* 2, &area
->fLeftTopInset
);
1166 err
= from
->FindSize(kItemInsets
, index
* 2 + 1, &area
->fRightBottomInset
);
1169 double contentAspectRatio
;
1170 err
= from
->FindDouble(kItemAspectRatio
, index
, &contentAspectRatio
);
1172 area
->SetContentAspectRatio(contentAspectRatio
);
1180 BALMLayout::AllUnarchived(const BMessage
* archive
)
1182 BUnarchiver
unarchiver(archive
);
1184 SharedSolver
* solver
;
1185 status_t err
= unarchiver
.FindObject(kSolverField
, solver
);
1192 if (archive
->GetInfo(kBadLayoutPolicyField
, NULL
) == B_OK
) {
1193 BadLayoutPolicy
* policy
;
1194 err
= unarchiver
.FindObject(kBadLayoutPolicyField
, policy
);
1196 SetBadLayoutPolicy(policy
);
1199 LinearSpec
* spec
= Solver();
1201 archive
->GetInfo(kXTabsField
, NULL
, &tabCount
);
1202 for (int32 i
= 0; i
< tabCount
&& err
== B_OK
; i
++) {
1204 err
= unarchiver
.FindObject(kXTabsField
, i
,
1205 BUnarchiver::B_DONT_ASSUME_OWNERSHIP
, tab
);
1206 spec
->AddVariable(tab
);
1207 TabAddTransaction
<XTab
> adder(this);
1208 if (adder
.AttempAdd(tab
))
1214 archive
->GetInfo(kYTabsField
, NULL
, &tabCount
);
1215 for (int32 i
= 0; i
< tabCount
; i
++) {
1217 unarchiver
.FindObject(kYTabsField
, i
,
1218 BUnarchiver::B_DONT_ASSUME_OWNERSHIP
, tab
);
1219 spec
->AddVariable(tab
);
1220 TabAddTransaction
<YTab
> adder(this);
1221 if (adder
.AttempAdd(tab
))
1229 XTab
* leftTab
= NULL
;
1230 err
= unarchiver
.FindObject(kMyTabsField
, 0, leftTab
);
1235 YTab
* topTab
= NULL
;
1236 err
= unarchiver
.FindObject(kMyTabsField
, 1, topTab
);
1241 XTab
* rightTab
= NULL
;
1242 err
= unarchiver
.FindObject(kMyTabsField
, 2, rightTab
);
1247 YTab
* bottomTab
= NULL
;
1248 err
= unarchiver
.FindObject(kMyTabsField
, 3, bottomTab
);
1249 fBottom
= bottomTab
;
1253 fLeft
->SetRange(0, 0);
1254 fTop
->SetRange(0, 0);
1256 err
= BAbstractLayout::AllUnarchived(archive
);
1263 BALMLayout::AllArchived(BMessage
* archive
) const
1265 status_t err
= BAbstractLayout::AllArchived(archive
);
1272 * Invalidates the layout.
1273 * Resets minimum/maximum/preferred size.
1276 BALMLayout::LayoutInvalidated(bool children
)
1278 fMinSize
= kUnsetSize
;
1279 fMaxSize
= kUnsetSize
;
1280 fPreferredSize
= kUnsetSize
;
1281 fXTabsSorted
= false;
1282 fYTabsSorted
= false;
1285 fSolver
->Invalidate(children
);
1290 BALMLayout::ItemAdded(BLayoutItem
* item
, int32 atIndex
)
1292 item
->SetLayoutData(new(std::nothrow
) Area(item
));
1293 return item
->LayoutData() != NULL
;
1298 BALMLayout::ItemRemoved(BLayoutItem
* item
, int32 fromIndex
)
1300 if (Area
* area
= AreaFor(item
)) {
1301 fRowColumnManager
->RemoveArea(area
);
1302 item
->SetLayoutData(NULL
);
1309 * Calculate and set the layout.
1310 * If no layout specification is given, a specification is reverse engineered automatically.
1313 BALMLayout::DoLayout()
1315 BLayoutContext
* context
= LayoutContext();
1316 ResultType result
= fSolver
->ValidateLayout(context
);
1317 if (result
!= kOptimal
1318 && !fBadLayoutPolicy
->OnBadLayout(this, result
, context
)) {
1322 // set the calculated positions and sizes for every area
1323 for (int32 i
= 0; i
< CountItems(); i
++)
1324 AreaFor(ItemAt(i
))->_DoLayout(LayoutArea().LeftTop());
1326 fXTabsSorted
= false;
1327 fYTabsSorted
= false;
1332 BALMLayout::Solver() const
1334 return fSolver
->Solver();
1339 BALMLayout::ValidateLayout()
1341 // we explicitly recaluclate the layout so set the invalidate flag first
1342 fSolver
->Invalidate(true);
1344 BLayoutContext
* context
= LayoutContext();
1345 return fSolver
->ValidateLayout(context
);
1350 BALMLayout::SetInsets(float left
, float top
, float right
,
1353 fLeftInset
= BControlLook::ComposeSpacing(left
);
1354 fTopInset
= BControlLook::ComposeSpacing(top
);
1355 fRightInset
= BControlLook::ComposeSpacing(right
);
1356 fBottomInset
= BControlLook::ComposeSpacing(bottom
);
1363 BALMLayout::SetInsets(float horizontal
, float vertical
)
1365 fLeftInset
= BControlLook::ComposeSpacing(horizontal
);
1366 fRightInset
= fLeftInset
;
1368 fTopInset
= BControlLook::ComposeSpacing(vertical
);
1369 fBottomInset
= fTopInset
;
1376 BALMLayout::SetInsets(float insets
)
1378 fLeftInset
= BControlLook::ComposeSpacing(insets
);
1379 fRightInset
= fLeftInset
;
1380 fTopInset
= fLeftInset
;
1381 fBottomInset
= fLeftInset
;
1388 BALMLayout::GetInsets(float* left
, float* top
, float* right
,
1389 float* bottom
) const
1396 *right
= fRightInset
;
1398 *bottom
= fBottomInset
;
1403 BALMLayout::SetSpacing(float hSpacing
, float vSpacing
)
1405 fHSpacing
= BControlLook::ComposeSpacing(hSpacing
);
1406 fVSpacing
= BControlLook::ComposeSpacing(vSpacing
);
1411 BALMLayout::GetSpacing(float *_hSpacing
, float *_vSpacing
) const
1414 *_hSpacing
= fHSpacing
;
1416 *_vSpacing
= fVSpacing
;
1421 BALMLayout::InsetForTab(XTab
* tab
) const
1423 if (tab
== fLeft
.Get())
1425 if (tab
== fRight
.Get())
1427 return fHSpacing
/ 2;
1432 BALMLayout::InsetForTab(YTab
* tab
) const
1434 if (tab
== fTop
.Get())
1436 if (tab
== fBottom
.Get())
1437 return fBottomInset
;
1438 return fVSpacing
/ 2;
1443 BALMLayout::UpdateConstraints(BLayoutContext
* context
)
1445 for (int i
= 0; i
< CountItems(); i
++)
1446 AreaFor(ItemAt(i
))->InvalidateSizeConstraints();
1447 fRowColumnManager
->UpdateConstraints();
1451 void BALMLayout::_RemoveSelfFromTab(XTab
* tab
) { tab
->LayoutLeaving(this); }
1452 void BALMLayout::_RemoveSelfFromTab(YTab
* tab
) { tab
->LayoutLeaving(this); }
1454 bool BALMLayout::_HasTabInLayout(XTab
* tab
) { return tab
->IsInLayout(this); }
1455 bool BALMLayout::_HasTabInLayout(YTab
* tab
) { return tab
->IsInLayout(this); }
1457 bool BALMLayout::_AddedTab(XTab
* tab
) { return tab
->AddedToLayout(this); }
1458 bool BALMLayout::_AddedTab(YTab
* tab
) { return tab
->AddedToLayout(this); }
1462 BALMLayout::_LayoutItemToAdd(BView
* view
)
1464 if (view
->GetLayout())
1465 return view
->GetLayout();
1466 return new(std::nothrow
) BViewLayoutItem(view
);
1471 BALMLayout::_SetSolver(SharedSolver
* solver
)
1474 fSolver
->AcquireReference();
1475 fSolver
->RegisterLayout(this);
1476 fRowColumnManager
= new RowColumnManager(Solver());
1481 BALMLayout::Perform(perform_code d
, void* arg
)
1483 return BAbstractLayout::Perform(d
, arg
);
1487 void BALMLayout::_ReservedALMLayout1() {}
1488 void BALMLayout::_ReservedALMLayout2() {}
1489 void BALMLayout::_ReservedALMLayout3() {}
1490 void BALMLayout::_ReservedALMLayout4() {}
1491 void BALMLayout::_ReservedALMLayout5() {}
1492 void BALMLayout::_ReservedALMLayout6() {}
1493 void BALMLayout::_ReservedALMLayout7() {}
1494 void BALMLayout::_ReservedALMLayout8() {}
1495 void BALMLayout::_ReservedALMLayout9() {}
1496 void BALMLayout::_ReservedALMLayout10() {}