[Libreoffice-commits] .: Branch 'feature/cmclayouttrans' - vcl/inc vcl/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Aug 23 07:20:54 PDT 2012


 vcl/inc/vcl/layout.hxx         |    5 +
 vcl/inc/vcl/tabctrl.hxx        |   13 +++++
 vcl/source/control/tabctrl.cxx |  105 ++++++++++++++++++++++++-----------------
 vcl/source/window/layout.cxx   |   53 ++++++++------------
 vcl/source/window/window2.cxx  |   38 ++++++++++++--
 5 files changed, 134 insertions(+), 80 deletions(-)

New commits:
commit 8a2a5d01e8e8e25525d5873ca5caecbac5946a03
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Aug 23 15:18:14 2012 +0100

    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

diff --git a/vcl/inc/vcl/layout.hxx b/vcl/inc/vcl/layout.hxx
index 42071ce..c7af5b9 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 7d9257e..c8c92c6 100644
--- a/vcl/inc/vcl/tabctrl.hxx
+++ b/vcl/inc/vcl/tabctrl.hxx
@@ -67,6 +67,7 @@ private:
     sal_Bool                mbRestoreHelpId;
     sal_Bool                mbRestoreUnqId;
     sal_Bool                mbSmallInvalidate;
+    bool                    mbLayoutDirty;
     Link                maActivateHdl;
     Link                maDeactivateHdl;
 
@@ -197,6 +198,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 11ea115..9a3e2f9 100644
--- a/vcl/source/control/tabctrl.cxx
+++ b/vcl/source/control/tabctrl.cxx
@@ -102,6 +102,8 @@ struct ImplTabCtrlData
 
 void TabControl::ImplInit( Window* pParent, WinBits nStyle )
 {
+    mbLayoutDirty = true;
+
     if ( !(nStyle & WB_NOTABSTOP) )
         nStyle |= WB_TABSTOP;
     if ( !(nStyle & WB_NOGROUP) )
@@ -1238,7 +1240,7 @@ void TabControl::ImplPaint( const Rectangle& rRect, bool bLayout )
 
 // -----------------------------------------------------------------------
 
-void TabControl::Resize()
+void TabControl::setAllocation(const Size &rAllocation)
 {
     ImplFreeLayoutData();
 
@@ -1262,7 +1264,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 )
@@ -1295,6 +1297,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());
 }
 
 // -----------------------------------------------------------------------
@@ -2142,57 +2167,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 67b4af8..2290edd 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 4a38819..5cdf4d3 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


More information about the Libreoffice-commits mailing list