summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2012-08-23 15:18:14 +0100
committerCaolán McNamara <caolanm@redhat.com>2012-09-28 08:48:38 +0100
commit7e1a1d4c846946c6c97078149f176e90438387de (patch)
treee7994c6fb9624df91d8458d80ab40563456a40ad
parente1f31827afa040487a6f72e182947fa852b691ac (diff)
we can need to redo the layout even when the sizes don't change
i.e. container remains the same size, but something inside it has disappeared, requiring contents to be readjusted We still want to minimize recalculations, so mark parent containers as dirty on queue_resize of a widget and we can retain the layout tree of the clean ones and just move them into their new positions as big fat blocks Change-Id: I8c5d9b836b48c98765b5cc41be72eaa2913ae7d8
-rw-r--r--vcl/inc/vcl/layout.hxx5
-rw-r--r--vcl/inc/vcl/tabctrl.hxx13
-rw-r--r--vcl/source/control/tabctrl.cxx105
-rw-r--r--vcl/source/window/layout.cxx53
-rw-r--r--vcl/source/window/window2.cxx38
5 files changed, 134 insertions, 80 deletions
diff --git a/vcl/inc/vcl/layout.hxx b/vcl/inc/vcl/layout.hxx
index 42071ce4f4cd..c7af5b95bff4 100644
--- a/vcl/inc/vcl/layout.hxx
+++ b/vcl/inc/vcl/layout.hxx
@@ -52,11 +52,16 @@ public:
{
return m_nBorderWidth;
}
+ void markLayoutDirty()
+ {
+ m_bLayoutDirty = true;
+ }
protected:
virtual Size calculateRequisition() const = 0;
virtual void setAllocation(const Size &rAllocation) = 0;
private:
int m_nBorderWidth;
+ bool m_bLayoutDirty;
};
class VCL_DLLPUBLIC VclBox : public VclContainer
diff --git a/vcl/inc/vcl/tabctrl.hxx b/vcl/inc/vcl/tabctrl.hxx
index 1710ec84d0cc..cc3d78b1124e 100644
--- a/vcl/inc/vcl/tabctrl.hxx
+++ b/vcl/inc/vcl/tabctrl.hxx
@@ -66,6 +66,7 @@ private:
sal_Bool mbRestoreHelpId;
sal_Bool mbRestoreUnqId;
sal_Bool mbSmallInvalidate;
+ bool mbLayoutDirty;
Link maActivateHdl;
Link maDeactivateHdl;
@@ -195,6 +196,18 @@ public:
// rename nOldId to nNewId);
void ReassignPageId(sal_uInt16 nOldId, sal_uInt16 nNewId);
+
+ using Control::SetPosSizePixel;
+ virtual void SetPosSizePixel(const Point& rNewPos, const Size& rNewSize);
+ virtual void SetSizePixel(const Size& rNewSize);
+
+ Size calculateRequisition() const;
+ void setAllocation(const Size &rAllocation);
+
+ void markLayoutDirty()
+ {
+ mbLayoutDirty = true;
+ }
};
#endif // _SV_TABCTRL_HXX
diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx
index ff680ba60a9a..46bfbbd1d4bb 100644
--- a/vcl/source/control/tabctrl.cxx
+++ b/vcl/source/control/tabctrl.cxx
@@ -101,6 +101,8 @@ struct ImplTabCtrlData
void TabControl::ImplInit( Window* pParent, WinBits nStyle )
{
+ mbLayoutDirty = true;
+
if ( !(nStyle & WB_NOTABSTOP) )
nStyle |= WB_TABSTOP;
if ( !(nStyle & WB_NOGROUP) )
@@ -1225,7 +1227,7 @@ void TabControl::ImplPaint( const Rectangle& rRect, bool bLayout )
// -----------------------------------------------------------------------
-void TabControl::Resize()
+void TabControl::setAllocation(const Size &rAllocation)
{
ImplFreeLayoutData();
@@ -1249,7 +1251,7 @@ void TabControl::Resize()
// Aktuelle TabPage resizen/positionieren
sal_Bool bTabPage = ImplPosCurTabPage();
// Feststellen, was invalidiert werden muss
- Size aNewSize = Control::GetOutputSizePixel();
+ Size aNewSize = rAllocation;
long nNewWidth = aNewSize.Width();
for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
it != mpTabCtrlData->maItemList.end(); ++it )
@@ -1282,6 +1284,29 @@ void TabControl::Resize()
else
Invalidate();
}
+
+ mbLayoutDirty = false;
+}
+
+void TabControl::SetPosSizePixel(const Point& rNewPos, const Size& rNewSize)
+{
+ Window::SetPosSizePixel(rNewPos, rNewSize);
+ //if size changed, TabControl::Resize got called already
+ if (mbLayoutDirty)
+ setAllocation(rNewSize);
+}
+
+void TabControl::SetSizePixel(const Size& rNewSize)
+{
+ Window::SetSizePixel(rNewSize);
+ //if size changed, TabControl::Resize got called already
+ if (mbLayoutDirty)
+ setAllocation(rNewSize);
+}
+
+void TabControl::Resize()
+{
+ setAllocation(Control::GetOutputSizePixel());
}
// -----------------------------------------------------------------------
@@ -2125,57 +2150,55 @@ Point TabControl::GetItemsOffset() const
// -----------------------------------------------------------------------
-Size TabControl::GetOptimalSize(WindowSizeType eType) const
+Size TabControl::calculateRequisition() const
{
- switch (eType) {
- case WINDOWSIZE_MINIMUM:
- return mpTabCtrlData ? mpTabCtrlData->maMinSize : Size();
+ Size aOptimalPageSize(0, 0);
+ long nTabLabelsBottom = 0;
+ long nTotalTabLabelWidths = 0;
- default:
+ for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
+ it != mpTabCtrlData->maItemList.end(); ++it )
{
- Size aOptimalPageSize(0, 0);
- long nTabLabelsBottom = 0;
- long nTotalTabLabelWidths = 0;
+ Size aPageSize;
+ const TabPage *pPage = it->mpTabPage;
+ //it's a real nuisance if the page is not inserted yet :-(
+ if (pPage)
+ aPageSize = pPage->GetOptimalSize(WINDOWSIZE_PREFERRED);
- for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
- it != mpTabCtrlData->maItemList.end(); ++it )
- {
- Size aPageSize;
- const TabPage *pPage = it->mpTabPage;
- if (pPage)
- aPageSize = pPage->GetOptimalSize(eType);
- else
- fprintf(stderr, "nuisance, page not inserted yet :-(\n");
+ if (aPageSize.Width() > aOptimalPageSize.Width())
+ aOptimalPageSize.Width() = aPageSize.Width();
+ if (aPageSize.Height() > aOptimalPageSize.Height())
+ aOptimalPageSize.Height() = aPageSize.Height();
- if (aPageSize.Width() > aOptimalPageSize.Width())
- aOptimalPageSize.Width() = aPageSize.Width();
- if (aPageSize.Height() > aOptimalPageSize.Height())
- aOptimalPageSize.Height() = aPageSize.Height();
+ TabControl* pThis = const_cast<TabControl*>(this);
- TabControl* pThis = const_cast<TabControl*>(this);
+ sal_uInt16 nPos = it - mpTabCtrlData->maItemList.begin();
+ Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aPageSize.Width(), aPageSize.Height());
+ if (aTabRect.Bottom() > nTabLabelsBottom)
+ nTabLabelsBottom = aTabRect.Bottom();
- sal_uInt16 nPos = it - mpTabCtrlData->maItemList.begin();
- Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aPageSize.Width(), aPageSize.Height());
- if (aTabRect.Bottom() > nTabLabelsBottom)
- nTabLabelsBottom = aTabRect.Bottom();
+ ImplTabItem* pItem = const_cast<ImplTabItem*>(&(*it));
+ Size aTabSize = pThis->ImplGetItemSize(pItem, LONG_MAX);
+ nTotalTabLabelWidths += aTabSize.Width();
+ }
- ImplTabItem* pItem = const_cast<ImplTabItem*>(&(*it));
- Size aTabSize = pThis->ImplGetItemSize(pItem, LONG_MAX);
- nTotalTabLabelWidths += aTabSize.Width();
- }
+ Size aOptimalSize(aOptimalPageSize);
+ aOptimalSize.Height() += nTabLabelsBottom;
- Size aOptimalSize(aOptimalPageSize);
- aOptimalSize.Height() += nTabLabelsBottom;
+ if (nTotalTabLabelWidths > aOptimalSize.Width())
+ aOptimalSize.Width() = nTotalTabLabelWidths;
- if (nTotalTabLabelWidths > aOptimalSize.Width())
- aOptimalSize.Width() = nTotalTabLabelWidths;
+ aOptimalSize.Width() += TAB_OFFSET * 2;
+ aOptimalSize.Height() += TAB_OFFSET * 2;
- aOptimalSize.Width() += TAB_OFFSET * 2;
- aOptimalSize.Height() += TAB_OFFSET * 2;
+ return aOptimalSize;
+}
- return aOptimalSize;
- }
- }
+Size TabControl::GetOptimalSize(WindowSizeType eType) const
+{
+ if (eType == WINDOWSIZE_MINIMUM)
+ return mpTabCtrlData ? mpTabCtrlData->maMinSize : Size();
+ return calculateRequisition();
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx
index 67b4af8f5b1a..2290edd5a410 100644
--- a/vcl/source/window/layout.cxx
+++ b/vcl/source/window/layout.cxx
@@ -33,6 +33,7 @@
VclContainer::VclContainer(Window *pParent)
: Window(WINDOW_CONTAINER)
, m_nBorderWidth(0)
+ , m_bLayoutDirty(true)
{
ImplInit(pParent, 0, NULL);
}
@@ -67,8 +68,11 @@ void VclContainer::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocati
else if (bSizeChanged)
Window::SetSizePixel(aAllocation);
- if (bSizeChanged)
+ if (m_bLayoutDirty || bSizeChanged)
+ {
setAllocation(aAllocation);
+ m_bLayoutDirty = false;
+ }
}
void VclContainer::SetPosPixel(const Point& rAllocPos)
@@ -86,11 +90,13 @@ void VclContainer::SetSizePixel(const Size& rAllocation)
Size aAllocation = rAllocation;
aAllocation.Width() -= m_nBorderWidth*2;
aAllocation.Height() -= m_nBorderWidth*2;
-
- if (aAllocation != GetSizePixel())
- {
+ bool bSizeChanged = aAllocation != GetSizePixel();
+ if (bSizeChanged)
Window::SetSizePixel(aAllocation);
+ if (m_bLayoutDirty || bSizeChanged)
+ {
setAllocation(aAllocation);
+ m_bLayoutDirty = false;
}
}
@@ -143,22 +149,6 @@ Size VclBox::calculateRequisition() const
return aSize;
}
-namespace
-{
- //avoid redraws when size/pos is unchanged
- void setPosSizePixel(Window &rWindow, const Point& rAllocPos, const Size& rAllocation)
- {
- bool bPosChanged = rAllocPos != rWindow.GetPosPixel();
- bool bSizeChanged = rAllocation != rWindow.GetSizePixel();
- if (bPosChanged && bSizeChanged)
- rWindow.SetPosSizePixel(rAllocPos, rAllocation);
- else if (bPosChanged)
- rWindow.SetPosPixel(rAllocPos);
- else if (bSizeChanged)
- rWindow.SetSizePixel(rAllocation);
- }
-}
-
void VclBox::setAllocation(const Size &rAllocation)
{
//SetBackground( Color(0x00, 0xFF, 0x00) );
@@ -263,7 +253,7 @@ void VclBox::setAllocation(const Size &rAllocation)
getPrimaryDimension(aBoxSize));
}
- setPosSizePixel(*pChild, aChildPos, aChildSize);
+ pChild->SetPosSizePixel(aChildPos, aChildSize);
}
}
}
@@ -390,7 +380,7 @@ void VclButtonBox::setAllocation(const Size &rAllocation)
setSecondaryDimension(aChildSize, getSecondaryDimension(aSize));
setPrimaryDimension(aChildSize, nHomogeneousDimension);
- setPosSizePixel(*pChild, aPos, aChildSize);
+ pChild->SetPosSizePixel(aPos, aChildSize);
nPrimaryCoordinate = getPrimaryCoordinate(aPos);
setPrimaryCoordinate(aPos, nPrimaryCoordinate + nHomogeneousDimension + m_nSpacing);
@@ -723,7 +713,7 @@ void VclGrid::setAllocation(const Size& rAllocation)
break;
}
- setPosSizePixel(*pChild, aChildPos, aChildSize);
+ pChild->SetPosSizePixel(aChildPos, aChildSize);
}
aAllocPos.Y() += aHeights[y].m_nValue + get_row_spacing();
}
@@ -786,7 +776,7 @@ void VclBin::setAllocation(const Size &rAllocation)
{
Window *pChild = get_child();
if (pChild && pChild->IsVisible())
- setPosSizePixel(*pChild, Point(0, 0), rAllocation);
+ pChild->SetPosSizePixel(Point(0, 0), rAllocation);
}
//To-Do, hook a DecorationView into VclFrame ?
@@ -839,13 +829,13 @@ void VclFrame::setAllocation(const Size &rAllocation)
Size aLabelSize = pLabel->GetOptimalSize(WINDOWSIZE_PREFERRED);
aLabelSize.Height() = std::min(aLabelSize.Height(), aAllocation.Height());
aLabelSize.Width() = std::min(aLabelSize.Width(), aAllocation.Width());
- setPosSizePixel(*pLabel, aChildPos, aLabelSize);
+ pLabel->SetPosSizePixel(aChildPos, aLabelSize);
aAllocation.Height() -= aLabelSize.Height();
aChildPos.Y() += aLabelSize.Height();
}
if (pChild && pChild->IsVisible())
- setPosSizePixel(*pChild, aChildPos, aAllocation);
+ pChild->SetPosSizePixel(aChildPos, aAllocation);
}
Size VclAlignment::calculateRequisition() const
@@ -876,7 +866,7 @@ void VclAlignment::setAllocation(const Size &rAllocation)
aAllocation.Width() = rAllocation.Width() - (m_nLeftPadding + m_nRightPadding);
aAllocation.Height() = rAllocation.Height() - (m_nTopPadding + m_nBottomPadding);
- setPosSizePixel(*pChild, aChildPos, aAllocation);
+ pChild->SetPosSizePixel(aChildPos, aAllocation);
}
bool VclAlignment::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
@@ -980,7 +970,7 @@ void VclExpander::setAllocation(const Size &rAllocation)
long nExtraExpanderHeight = aExpanderSize.Height() - aButtonSize.Height();
Point aButtonPos(aChildPos.X(), aChildPos.Y() + nExtraExpanderHeight/2);
- setPosSizePixel(m_aDisclosureButton, aButtonPos, aButtonSize);
+ m_aDisclosureButton.SetPosSizePixel(aButtonPos, aButtonSize);
if (pLabel && pLabel->IsVisible())
{
@@ -990,7 +980,7 @@ void VclExpander::setAllocation(const Size &rAllocation)
long nExtraLabelHeight = aExpanderSize.Height() - aLabelSize.Height();
Point aLabelPos(aChildPos.X() + aButtonSize.Width(), aChildPos.Y() + nExtraLabelHeight/2);
- setPosSizePixel(*pLabel, aLabelPos, aLabelSize);
+ pLabel->SetPosSizePixel(aLabelPos, aLabelSize);
}
aAllocation.Height() -= aExpanderSize.Height();
@@ -1000,7 +990,7 @@ void VclExpander::setAllocation(const Size &rAllocation)
{
if (!m_aDisclosureButton.IsChecked())
aAllocation = Size();
- setPosSizePixel(*pChild, aChildPos, aAllocation);
+ pChild->SetPosSizePixel(aChildPos, aAllocation);
}
}
@@ -1021,11 +1011,10 @@ IMPL_LINK( VclExpander, ClickHdl, DisclosureButton*, pBtn )
if (pChild)
{
pChild->Show(pBtn->IsChecked());
+ queue_resize();
Dialog* pResizeDialog = m_bResizeTopLevel ? GetParentDialog() : NULL;
if (pResizeDialog)
pResizeDialog->setInitialLayoutSize();
- else
- queue_resize();
}
return 0;
}
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
index 9b51446260dd..5e27f5eed9e7 100644
--- a/vcl/source/window/window2.cxx
+++ b/vcl/source/window/window2.cxx
@@ -41,6 +41,7 @@
#include <vcl/window.hxx>
#include <vcl/scrbar.hxx>
#include <vcl/dockwin.hxx>
+#include <vcl/tabctrl.hxx>
#include <window.h>
#include <outfont.hxx>
@@ -1749,16 +1750,39 @@ void Window::SetBackgroundBitmap( const BitmapEx& rBitmapEx )
}
}
-//When a widget wants to renegotiate size, get toplevel parent dialog and call
-//resize on it. Maybe better to just find direct parent and if its a container
-//chain it upwards one step at a time until a dialog is found.
+//When a widget wants to renegotiate layout, get toplevel parent dialog and call
+//resize on it. Mark all intermediate containers (or container-alike) widgets
+//as dirty for the size remains unchanged, but layout changed circumstances
void Window::queue_resize()
{
- Dialog *pParent = GetParentDialog();
- if (!pParent || pParent == this)
+ Dialog *pDialog = NULL;
+
+ Window *pWindow = this;
+
+ while( pWindow )
+ {
+ if (pWindow->GetType() == WINDOW_CONTAINER)
+ {
+ VclContainer *pContainer = static_cast<VclContainer*>(pWindow);
+ pContainer->markLayoutDirty();
+ }
+ else if (pWindow->GetType() == WINDOW_TABCONTROL)
+ {
+ TabControl *pTabControl = static_cast<TabControl*>(pWindow);
+ pTabControl->markLayoutDirty();
+ }
+ else if (pWindow->IsDialog())
+ {
+ pDialog = dynamic_cast<Dialog*>(pWindow);
+ break;
+ }
+ pWindow = pWindow->GetParent();
+ }
+
+ if (!pDialog || pDialog == this)
return;
- if (pParent->isLayoutEnabled())
- pParent->Resize();
+ if (pDialog->isLayoutEnabled())
+ pDialog->Resize();
}
//We deliberately do not overwrite our maHelpId here