/* * Copyright 2011, Haiku, Inc. All rights reserved. * Copyright 2011, Clemens Zeidler * Distributed under the terms of the MIT License. */ #include "RowColumnManager.h" #include 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