invoke the layout's InvalidateLayout() anymore. This could cause problems when the layout caches layout related information and also updates those on calls other than LayoutView(). A call to such a method after an InvalidateLayout() would mark the cached info valid and the layout would use the cached info until the first InvalidateLayout() after the next LayoutView(), even if BView::InvalidateLayout() had been called again in the meantime. * Introduced a new method BView::ResetLayoutInvalidation(), which must be called by layout implementations whenever they have updated their cached information and need further InvalidateLayout() notifications. * Adjusted the existing layout implementations to use the method. Fixes bug #4047. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31316 a95241bf-73f2-0310-859d-f6bbb57e9c96
240 lines
4.5 KiB
C++
240 lines
4.5 KiB
C++
/*
|
|
* Copyright 2006-2009, Ingo Weinhold <[email protected]>.
|
|
* All rights reserved. Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
#include <CardLayout.h>
|
|
|
|
#include <LayoutItem.h>
|
|
#include <View.h>
|
|
|
|
// constructor
|
|
BCardLayout::BCardLayout()
|
|
: BLayout(),
|
|
fMin(0, 0),
|
|
fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
|
|
fPreferred(0, 0),
|
|
fVisibleItem(NULL),
|
|
fMinMaxValid(false)
|
|
{
|
|
}
|
|
|
|
// destructor
|
|
BCardLayout::~BCardLayout()
|
|
{
|
|
}
|
|
|
|
// VisibleItem
|
|
BLayoutItem*
|
|
BCardLayout::VisibleItem() const
|
|
{
|
|
return fVisibleItem;
|
|
}
|
|
|
|
// VisibleIndex
|
|
int32
|
|
BCardLayout::VisibleIndex() const
|
|
{
|
|
return IndexOfItem(fVisibleItem);
|
|
}
|
|
|
|
// SetVisibleItem
|
|
void
|
|
BCardLayout::SetVisibleItem(int32 index)
|
|
{
|
|
SetVisibleItem(ItemAt(index));
|
|
}
|
|
|
|
// SetVisibleItem
|
|
void
|
|
BCardLayout::SetVisibleItem(BLayoutItem* item)
|
|
{
|
|
if (item == fVisibleItem)
|
|
return;
|
|
|
|
if (item != NULL && IndexOfItem(item) < 0)
|
|
return;
|
|
|
|
if (fVisibleItem != NULL)
|
|
fVisibleItem->SetVisible(false);
|
|
|
|
fVisibleItem = item;
|
|
|
|
if (fVisibleItem != NULL) {
|
|
fVisibleItem->SetVisible(true);
|
|
|
|
LayoutView();
|
|
}
|
|
}
|
|
|
|
// MinSize
|
|
BSize
|
|
BCardLayout::MinSize()
|
|
{
|
|
_ValidateMinMax();
|
|
return fMin;
|
|
}
|
|
|
|
// MaxSize
|
|
BSize
|
|
BCardLayout::MaxSize()
|
|
{
|
|
_ValidateMinMax();
|
|
return fMax;
|
|
}
|
|
|
|
// PreferredSize
|
|
BSize
|
|
BCardLayout::PreferredSize()
|
|
{
|
|
_ValidateMinMax();
|
|
return fPreferred;
|
|
}
|
|
|
|
// Alignment
|
|
BAlignment
|
|
BCardLayout::Alignment()
|
|
{
|
|
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
|
|
}
|
|
|
|
// HasHeightForWidth
|
|
bool
|
|
BCardLayout::HasHeightForWidth()
|
|
{
|
|
int32 count = CountItems();
|
|
for (int32 i = 0; i < count; i++) {
|
|
if (ItemAt(i)->HasHeightForWidth())
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// GetHeightForWidth
|
|
void
|
|
BCardLayout::GetHeightForWidth(float width, float* min, float* max,
|
|
float* preferred)
|
|
{
|
|
_ValidateMinMax();
|
|
|
|
// init with useful values
|
|
float minHeight = fMin.height;
|
|
float maxHeight = fMax.height;
|
|
float preferredHeight = fPreferred.height;
|
|
|
|
// apply the items' constraints
|
|
int32 count = CountItems();
|
|
for (int32 i = 0; i < count; i++) {
|
|
BLayoutItem* item = ItemAt(i);
|
|
if (item->HasHeightForWidth()) {
|
|
float itemMinHeight;
|
|
float itemMaxHeight;
|
|
float itemPreferredHeight;
|
|
item->GetHeightForWidth(width, &itemMinHeight, &itemMaxHeight,
|
|
&itemPreferredHeight);
|
|
minHeight = max_c(minHeight, itemMinHeight);
|
|
maxHeight = min_c(maxHeight, itemMaxHeight);
|
|
preferredHeight = min_c(preferredHeight, itemPreferredHeight);
|
|
}
|
|
}
|
|
|
|
// adjust max and preferred, if necessary
|
|
maxHeight = max_c(maxHeight, minHeight);
|
|
preferredHeight = max_c(preferredHeight, minHeight);
|
|
preferredHeight = min_c(preferredHeight, maxHeight);
|
|
|
|
if (min)
|
|
*min = minHeight;
|
|
if (max)
|
|
*max = maxHeight;
|
|
if (preferred)
|
|
*preferred = preferredHeight;
|
|
}
|
|
|
|
// InvalidateLayout
|
|
void
|
|
BCardLayout::InvalidateLayout()
|
|
{
|
|
BLayout::InvalidateLayout();
|
|
|
|
fMinMaxValid = false;
|
|
}
|
|
|
|
// LayoutView
|
|
void
|
|
BCardLayout::LayoutView()
|
|
{
|
|
_ValidateMinMax();
|
|
|
|
BSize size = View()->Bounds().Size();
|
|
size.width = max_c(size.width, fMin.width);
|
|
size.height = max_c(size.height, fMin.height);
|
|
|
|
if (fVisibleItem != NULL)
|
|
fVisibleItem->AlignInFrame(BRect(0, 0, size.width, size.height));
|
|
}
|
|
|
|
// ItemAdded
|
|
void
|
|
BCardLayout::ItemAdded(BLayoutItem* item)
|
|
{
|
|
item->SetVisible(false);
|
|
}
|
|
|
|
// ItemRemoved
|
|
void
|
|
BCardLayout::ItemRemoved(BLayoutItem* item)
|
|
{
|
|
if (fVisibleItem == item) {
|
|
BLayoutItem* newVisibleItem = NULL;
|
|
SetVisibleItem(newVisibleItem);
|
|
}
|
|
}
|
|
|
|
// _ValidateMinMax
|
|
void
|
|
BCardLayout::_ValidateMinMax()
|
|
{
|
|
if (fMinMaxValid)
|
|
return;
|
|
|
|
fMin.width = 0;
|
|
fMin.height = 0;
|
|
fMax.width = B_SIZE_UNLIMITED;
|
|
fMax.height = B_SIZE_UNLIMITED;
|
|
fPreferred.width = 0;
|
|
fPreferred.height = 0;
|
|
|
|
int32 itemCount = CountItems();
|
|
for (int32 i = 0; i < itemCount; i++) {
|
|
BLayoutItem* item = ItemAt(i);
|
|
|
|
BSize min = item->MinSize();
|
|
BSize max = item->MaxSize();
|
|
BSize preferred = item->PreferredSize();
|
|
|
|
fMin.width = max_c(fMin.width, min.width);
|
|
fMin.height = max_c(fMin.height, min.height);
|
|
|
|
fMax.width = min_c(fMax.width, max.width);
|
|
fMax.height = min_c(fMax.height, max.height);
|
|
|
|
fPreferred.width = max_c(fPreferred.width, preferred.width);
|
|
fPreferred.height = max_c(fPreferred.height, preferred.height);
|
|
}
|
|
|
|
fMax.width = max_c(fMax.width, fMin.width);
|
|
fMax.height = max_c(fMax.height, fMin.height);
|
|
|
|
fPreferred.width = max_c(fPreferred.width, fMin.width);
|
|
fPreferred.height = max_c(fPreferred.height, fMin.height);
|
|
fPreferred.width = min_c(fPreferred.width, fMax.width);
|
|
fPreferred.height = min_c(fPreferred.height, fMax.height);
|
|
|
|
fMinMaxValid = true;
|
|
|
|
if (BView* view = View())
|
|
view->ResetLayoutInvalidation();
|
|
}
|