235 lines
4.8 KiB
C++
235 lines
4.8 KiB
C++
/*
|
|
* Copyright 2011, Haiku, Inc. All rights reserved.
|
|
* Copyright 2011, Clemens Zeidler <[email protected]>
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include "RowColumnManager.h"
|
|
|
|
|
|
#include <LayoutItem.h>
|
|
|
|
|
|
using namespace LinearProgramming;
|
|
|
|
|
|
namespace BALM {
|
|
|
|
|
|
RowColumnManager::RowColumnManager(LinearSpec* spec)
|
|
:
|
|
fLinearSpec(spec)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
RowColumnManager::~RowColumnManager()
|
|
{
|
|
for (int32 i = 0; i < fRows.CountItems(); i++)
|
|
delete fRows.ItemAt(i)->fPrefSizeConstraint;
|
|
|
|
for (int32 i = 0; i < fColumns.CountItems(); i++)
|
|
delete fColumns.ItemAt(i)->fPrefSizeConstraint;
|
|
}
|
|
|
|
|
|
void
|
|
RowColumnManager::AddArea(Area* area)
|
|
{
|
|
Row* row = _FindRowFor(area);
|
|
if (row == NULL) {
|
|
row = new Row(fLinearSpec, area->Top(), area->Bottom());
|
|
fRows.AddItem(row);
|
|
}
|
|
area->fRow = row;
|
|
row->fAreas.AddItem(area);
|
|
|
|
Column* column = _FindColumnFor(area);
|
|
if (column == NULL) {
|
|
column = new Column(fLinearSpec, area->Left(), area->Right());
|
|
fColumns.AddItem(column);
|
|
}
|
|
area->fColumn = column;
|
|
column->fAreas.AddItem(area);
|
|
|
|
_UpdateConstraints(row);
|
|
_UpdateConstraints(column);
|
|
}
|
|
|
|
|
|
void
|
|
RowColumnManager::RemoveArea(Area* area)
|
|
{
|
|
Row* row = area->fRow;
|
|
if (row) {
|
|
row->fAreas.RemoveItem(area);
|
|
area->fRow = NULL;
|
|
if (row->fAreas.CountItems() == 0) {
|
|
fRows.RemoveItem(row);
|
|
delete row;
|
|
} else
|
|
_UpdateConstraints(row);
|
|
}
|
|
|
|
Column* column = area->fColumn;
|
|
if (column) {
|
|
column->fAreas.RemoveItem(area);
|
|
area->fColumn = NULL;
|
|
if (column->fAreas.CountItems() == 0) {
|
|
fColumns.RemoveItem(column);
|
|
delete column;
|
|
} else
|
|
_UpdateConstraints(column);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
RowColumnManager::UpdateConstraints()
|
|
{
|
|
for (int32 i = 0; i < fRows.CountItems(); i++)
|
|
_UpdateConstraints(fRows.ItemAt(i));
|
|
for (int32 i = 0; i < fColumns.CountItems(); i++)
|
|
_UpdateConstraints(fColumns.ItemAt(i));
|
|
}
|
|
|
|
|
|
void
|
|
RowColumnManager::TabsChanged(Area* area)
|
|
{
|
|
RemoveArea(area);
|
|
AddArea(area);
|
|
}
|
|
|
|
|
|
Row*
|
|
RowColumnManager::_FindRowFor(Area* area)
|
|
{
|
|
for (int32 i = 0; i < fRows.CountItems(); i++) {
|
|
Row* row = fRows.ItemAt(i);
|
|
if (row->fTop.Get() == area->Top()
|
|
&& row->fBottom.Get() == area->Bottom())
|
|
return row;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
Column*
|
|
RowColumnManager::_FindColumnFor(Area* area)
|
|
{
|
|
for (int32 i = 0; i < fColumns.CountItems(); i++) {
|
|
Column* column = fColumns.ItemAt(i);
|
|
if (column->fLeft.Get() == area->Left()
|
|
&& column->fRight.Get() == area->Right())
|
|
return column;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
double
|
|
RowColumnManager::_PreferredHeight(Row* row, double& weight)
|
|
{
|
|
weight = 0;
|
|
int nAreas = 0;
|
|
double pref = 0;
|
|
for (int32 i = 0; i < row->fAreas.CountItems(); i++) {
|
|
BSize prefSize = row->fAreas.ItemAt(i)->Item()->PreferredSize();
|
|
if (prefSize.height <= 0)
|
|
continue;
|
|
nAreas++;
|
|
pref += prefSize.height;
|
|
double negPen = row->fAreas.ItemAt(i)->ShrinkPenalties().height;
|
|
if (negPen > 0)
|
|
weight += negPen;
|
|
}
|
|
if (nAreas == 0) {
|
|
pref = -1;
|
|
weight = 1;
|
|
} else {
|
|
pref /= nAreas;
|
|
weight /= nAreas;
|
|
}
|
|
return pref;
|
|
}
|
|
|
|
|
|
double
|
|
RowColumnManager::_PreferredWidth(Column* column, double& weight)
|
|
{
|
|
weight = 0;
|
|
int nAreas = 0;
|
|
double pref = 0;
|
|
for (int32 i = 0; i < column->fAreas.CountItems(); i++) {
|
|
BSize prefSize = column->fAreas.ItemAt(i)->Item()->PreferredSize();
|
|
if (prefSize.width <= 0)
|
|
continue;
|
|
nAreas++;
|
|
pref += prefSize.width;
|
|
|
|
double negPen = column->fAreas.ItemAt(i)->ShrinkPenalties().height;
|
|
if (negPen > 0)
|
|
weight += negPen;
|
|
}
|
|
if (nAreas == 0) {
|
|
pref = -1;
|
|
weight = 1;
|
|
} else {
|
|
pref /= nAreas;
|
|
weight /= nAreas;
|
|
}
|
|
return pref;
|
|
}
|
|
|
|
|
|
void
|
|
RowColumnManager::_UpdateConstraints(Row* row)
|
|
{
|
|
double weight;
|
|
double prefSize = _PreferredHeight(row, weight);
|
|
if (prefSize >= 0) {
|
|
if (row->fPrefSizeConstraint == NULL) {
|
|
row->fPrefSizeConstraint = fLinearSpec->AddConstraint(1,
|
|
row->fBottom, -1, row->fTop, kEQ, prefSize, weight, weight);
|
|
row->fPrefSizeConstraint->SetLabel("Pref Height");
|
|
} else {
|
|
row->fPrefSizeConstraint->SetRightSide(prefSize);
|
|
row->fPrefSizeConstraint->SetPenaltyNeg(weight);
|
|
row->fPrefSizeConstraint->SetPenaltyPos(weight);
|
|
}
|
|
} else {
|
|
delete row->fPrefSizeConstraint;
|
|
row->fPrefSizeConstraint = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
RowColumnManager::_UpdateConstraints(Column* column)
|
|
{
|
|
double weight;
|
|
double prefSize = _PreferredWidth(column, weight);
|
|
if (prefSize >= 0) {
|
|
if (column->fPrefSizeConstraint == NULL) {
|
|
column->fPrefSizeConstraint = fLinearSpec->AddConstraint(1,
|
|
column->fRight, -1, column->fLeft, kEQ, prefSize, weight,
|
|
weight);
|
|
column->fPrefSizeConstraint->SetLabel("Pref Width");
|
|
} else {
|
|
column->fPrefSizeConstraint->SetRightSide(prefSize);
|
|
column->fPrefSizeConstraint->SetPenaltyNeg(weight);
|
|
column->fPrefSizeConstraint->SetPenaltyPos(weight);
|
|
}
|
|
} else {
|
|
delete column->fPrefSizeConstraint;
|
|
column->fPrefSizeConstraint = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
} // end BALM namespace
|
|
|