vcl: ensure that VclBuilder is disposed before parent window.

Move VclBuilder to use VclPtr, link to documentation, and fix more
double dispose issues.

Change-Id: I4900b69dbb381bd7d6fda97f2a5e623bb58e0a9f
diff --git a/cui/source/options/optcolor.cxx b/cui/source/options/optcolor.cxx
index 3eb0229..c96cb62 100644
--- a/cui/source/options/optcolor.cxx
+++ b/cui/source/options/optcolor.cxx
@@ -174,6 +174,8 @@ class ColorConfigWindow_Impl
{
public:
    ColorConfigWindow_Impl(vcl::Window* pParent);
    ~ColorConfigWindow_Impl() { dispose(); }
    virtual void dispose() SAL_OVERRIDE;

public:
    void SetLinks (Link const&, Link const&, Link const&);
@@ -508,6 +510,12 @@ ColorConfigWindow_Impl::ColorConfigWindow_Impl(vcl::Window* pParent)
    SetAppearance();
}

void ColorConfigWindow_Impl::dispose()
{
    disposeBuilder();
    VclContainer::dispose();
}

Size ColorConfigWindow_Impl::calculateRequisition() const
{
    return getLayoutRequisition(*m_pGrid);
@@ -913,9 +921,14 @@ ColorConfigCtrl_Impl::~ColorConfigCtrl_Impl()
void ColorConfigCtrl_Impl::dispose()
{
    delete m_pVScroll;
    m_pVScroll = NULL;
    delete m_pScrollWindow;
    m_pScrollWindow = NULL;
    delete m_pBody;
    m_pBody = NULL;
    delete m_pHeaderHB;
    m_pHeaderHB = NULL;

    VclVBox::dispose();
}

diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx
index 179ca33..aba3f08 100644
--- a/include/vcl/builder.hxx
+++ b/include/vcl/builder.hxx
@@ -16,6 +16,7 @@
#include <tools/fldunit.hxx>
#include <vcl/dllapi.h>
#include <vcl/window.hxx>
#include <vcl/vclptr.hxx>
#include <map>
#include <set>
#include <stack>
@@ -55,6 +56,9 @@ public:
                            const css::uno::Reference<css::frame::XFrame> &rFrame = css::uno::Reference<css::frame::XFrame>());
                    ~VclBuilder();

    ///releases references and disposes all children.
    void disposeBuilder();

    //sID must exist and be of type T
    template <typename T> T* get(T*& ret, const OString& sID);

@@ -146,7 +150,7 @@ private:
    struct WinAndId
    {
        OString m_sID;
        vcl::Window *m_pWindow;
        VclPtr<vcl::Window> m_pWindow;
        short m_nResponseId;
        PackingData m_aPackingData;
        WinAndId(const OString &rId, vcl::Window *pWindow, bool bVertical)
@@ -445,12 +449,17 @@ inline PopupMenu* VclBuilder::get_menu(PopupMenu*& ret, const OString& sID)
//
//i.e.  class Dialog : public SystemWindow, public VclBuilderContainer
//not   class Dialog : public VclBuilderContainer, public SystemWindow
//
//With the new 'dispose' framework, it is necessary to force the builder
//dispose before the Window dispose; so a Dialog::dispose() method would
//finish: disposeBuilder(); SystemWindow::dispose() to capture this ordering.

class VCL_DLLPUBLIC VclBuilderContainer
{
public:
                    VclBuilderContainer();
    virtual         ~VclBuilderContainer();
    void            disposeBuilder();

    static OUString getUIRootDir();
    bool            hasBuilder() const { return m_pUIBuilder != NULL; }
diff --git a/include/vcl/tabpage.hxx b/include/vcl/tabpage.hxx
index c736197..7294d48 100644
--- a/include/vcl/tabpage.hxx
+++ b/include/vcl/tabpage.hxx
@@ -41,6 +41,8 @@ private:
public:
    explicit        TabPage( vcl::Window* pParent, WinBits nStyle = 0 );
    explicit        TabPage( vcl::Window *pParent, const OString& rID, const OUString& rUIXMLDescription );
                   ~TabPage();
    virtual void    dispose() SAL_OVERRIDE;

    virtual void    Paint( const Rectangle& rRect ) SAL_OVERRIDE;
    virtual void    Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) SAL_OVERRIDE;
diff --git a/include/vcl/vclptr.hxx b/include/vcl/vclptr.hxx
index 37da714..50a87ba 100644
--- a/include/vcl/vclptr.hxx
+++ b/include/vcl/vclptr.hxx
@@ -70,6 +70,9 @@ public:

/**
 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
 *
 * For more details on the design please see vcl/README.lifecycle
 *
 * @param reference_type must be a subclass of vcl::Window
 */
template <class reference_type>
@@ -136,6 +139,11 @@ public:
        m_rInnerRef.set(pBody);
    }

    inline void SAL_CALL reset(reference_type *pBody)
    {
        m_rInnerRef.set(pBody);
    }

    inline VclPtr<reference_type>& SAL_CALL operator= (reference_type * pBody)
    {
        m_rInnerRef.set(pBody);
@@ -152,6 +160,16 @@ public:
        return m_rInnerRef.get() != NULL;
    }

    inline void SAL_CALL clear()
    {
        m_rInnerRef.clear();
    }

    inline void SAL_CALL reset()
    {
        m_rInnerRef.clear();
    }

    inline void disposeAndClear()
    {
        // hold it alive for the lifetime of this method
diff --git a/reportdesign/source/ui/dlg/Condition.cxx b/reportdesign/source/ui/dlg/Condition.cxx
index c5e131a2..fb86522 100644
--- a/reportdesign/source/ui/dlg/Condition.cxx
+++ b/reportdesign/source/ui/dlg/Condition.cxx
@@ -162,6 +162,7 @@ OColorPopup::~OColorPopup()
void OColorPopup::dispose()
{
    m_aColorSet.disposeAndClear();
    disposeBuilder();
    FloatingWindow::dispose();
}

diff --git a/sfx2/source/appl/newhelp.cxx b/sfx2/source/appl/newhelp.cxx
index 9a80a2e..78c2df2 100644
--- a/sfx2/source/appl/newhelp.cxx
+++ b/sfx2/source/appl/newhelp.cxx
@@ -1457,6 +1457,9 @@ void SfxHelpIndexWindow_Impl::dispose()

    SvtViewOptions aViewOpt( E_TABDIALOG, CONFIGNAME_INDEXWIN );
    aViewOpt.SetPageID( (sal_Int32)m_pTabCtrl->GetCurPageId() );

    disposeBuilder();

    vcl::Window::dispose();
}

diff --git a/sfx2/source/dialog/backingwindow.cxx b/sfx2/source/dialog/backingwindow.cxx
index fa3f403..fcb9074e 100644
--- a/sfx2/source/dialog/backingwindow.cxx
+++ b/sfx2/source/dialog/backingwindow.cxx
@@ -217,6 +217,7 @@ void BackingWindow::dispose()
        }
        mxDropTargetListener = css::uno::Reference< css::datatransfer::dnd::XDropTargetListener >();
    }
    disposeBuilder();
    vcl::Window::dispose();
}

diff --git a/sfx2/source/dialog/dockwin.cxx b/sfx2/source/dialog/dockwin.cxx
index c3e0e3d..e17c3b2 100644
--- a/sfx2/source/dialog/dockwin.cxx
+++ b/sfx2/source/dialog/dockwin.cxx
@@ -259,6 +259,8 @@ SfxTitleDockingWindow::~SfxTitleDockingWindow()
void SfxTitleDockingWindow::dispose()
{
    delete m_pWrappedWindow;
    m_pWrappedWindow = NULL;

    SfxDockingWindow::dispose();
}

diff --git a/svx/source/dialog/ctredlin.cxx b/svx/source/dialog/ctredlin.cxx
index 48b50b0..0d2e530 100644
--- a/svx/source/dialog/ctredlin.cxx
+++ b/svx/source/dialog/ctredlin.cxx
@@ -118,6 +118,7 @@ SvxRedlinTable::~SvxRedlinTable()
void SvxRedlinTable::dispose()
{
    delete pCommentSearcher;
    pCommentSearcher = NULL;
    SvSimpleTable::dispose();
}

@@ -1084,7 +1085,10 @@ SvxAcceptChgCtr::~SvxAcceptChgCtr()
void SvxAcceptChgCtr::dispose()
{
    delete pTPView;
    pTPView = NULL;
    delete pTPFilter;
    pTPFilter = NULL;
    disposeBuilder();
    TabControl::dispose();
}

diff --git a/svx/source/form/datanavi.cxx b/svx/source/form/datanavi.cxx
index 148a747..c09637e 100644
--- a/svx/source/form/datanavi.cxx
+++ b/svx/source/form/datanavi.cxx
@@ -1419,17 +1419,23 @@ namespace svxform
        aViewOpt.SetUserItem(CFGNAME_SHOWDETAILS,aAny);

        delete m_pInstPage;
        m_pInstPage = NULL;
        delete m_pSubmissionPage;
        m_pSubmissionPage = NULL;
        delete m_pBindingPage;
        m_pBindingPage = NULL;

        sal_Int32 i, nCount = m_aPageList.size();
        for ( i = 0; i < nCount; ++i )
            delete m_aPageList[i];
        m_aPageList.clear();

        Reference< XFrameActionListener > xListener(
            static_cast< XFrameActionListener* >( m_xDataListener.get() ), UNO_QUERY );
        m_xFrame->removeFrameActionListener( xListener );
        RemoveBroadcaster();
        m_xDataListener.clear();
        disposeBuilder();
        vcl::Window::dispose();
    }

diff --git a/svx/source/sidebar/PanelLayout.cxx b/svx/source/sidebar/PanelLayout.cxx
index 23934f6..5224725 100644
--- a/svx/source/sidebar/PanelLayout.cxx
+++ b/svx/source/sidebar/PanelLayout.cxx
@@ -33,6 +33,7 @@ void PanelLayout::dispose()
{
    m_bInClose = true;
    m_aPanelLayoutIdle.Stop();
    disposeBuilder();
    Control::dispose();
}

diff --git a/sw/source/ui/index/cnttab.cxx b/sw/source/ui/index/cnttab.cxx
index 9bcaa1f..0005136 100644
--- a/sw/source/ui/index/cnttab.cxx
+++ b/sw/source/ui/index/cnttab.cxx
@@ -2658,6 +2658,8 @@ void SwTokenWindow::dispose()
        pControl->SetLoseFocusHdl( Link() );
        delete pControl;
    }
    aControlList.clear();
    disposeBuilder();
    VclHBox::dispose();
}

diff --git a/sw/source/uibase/sidebar/PagePropertyPanel.cxx b/sw/source/uibase/sidebar/PagePropertyPanel.cxx
index dd2fac9..13db321 100644
--- a/sw/source/uibase/sidebar/PagePropertyPanel.cxx
+++ b/sw/source/uibase/sidebar/PagePropertyPanel.cxx
@@ -206,7 +206,15 @@ PagePropertyPanel::~PagePropertyPanel()
void PagePropertyPanel::dispose()
{
    delete[] maImgSize;
    maImgSize = NULL;
    delete[] maImgSize_L;
    maImgSize_L = NULL;

    mpPageItem.reset();
    mpPageLRMarginItem.reset();
    mpPageULMarginItem.reset();
    mpPageSizeItem.reset();

    PanelLayout::dispose();
}

diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 3efccec..278a3e5 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -525,17 +525,24 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr

VclBuilder::~VclBuilder()
{
    disposeBuilder();
}

void VclBuilder::disposeBuilder()
{
    for (std::vector<WinAndId>::reverse_iterator aI = m_aChildren.rbegin(),
         aEnd = m_aChildren.rend(); aI != aEnd; ++aI)
    {
        delete aI->m_pWindow;
        aI->m_pWindow.disposeAndClear();
    }
    m_aChildren.clear();

    for (std::vector<MenuAndId>::reverse_iterator aI = m_aMenus.rbegin(),
         aEnd = m_aMenus.rend(); aI != aEnd; ++aI)
    {
        delete aI->m_pMenu;
    }
    m_aMenus.clear();
}

void VclBuilder::handleTranslations(xmlreader::XmlReader &reader)
@@ -3213,7 +3220,7 @@ void VclBuilder::collectAccelerator(xmlreader::XmlReader &reader, stringmap &rMa

vcl::Window *VclBuilder::get_widget_root()
{
    return m_aChildren.empty() ? NULL : m_aChildren[0].m_pWindow;
    return m_aChildren.empty() ? NULL : m_aChildren[0].m_pWindow.get();
}

vcl::Window *VclBuilder::get_by_name(const OString& sID)
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 8178788..9975c97 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -456,6 +456,12 @@ Dialog::Dialog( WindowType nType )
    ImplInitDialogData();
}

void VclBuilderContainer::disposeBuilder()
{
    if (m_pUIBuilder)
        m_pUIBuilder->disposeBuilder();
}

OUString VclBuilderContainer::getUIRootDir()
{
    /*to-do, check if user config has an override before using shared one, etc*/
diff --git a/vcl/source/window/dockwin.cxx b/vcl/source/window/dockwin.cxx
index 549d8c4..bc1740e 100644
--- a/vcl/source/window/dockwin.cxx
+++ b/vcl/source/window/dockwin.cxx
@@ -119,6 +119,9 @@ void ImplDockFloatWin::dispose()
{
    if( mnLastUserEvent )
        Application::RemoveUserEvent( mnLastUserEvent );

    disposeBuilder();

    FloatingWindow::dispose();
}

diff --git a/vcl/source/window/syswin.cxx b/vcl/source/window/syswin.cxx
index 19768d7..3bc802f 100644
--- a/vcl/source/window/syswin.cxx
+++ b/vcl/source/window/syswin.cxx
@@ -118,6 +118,7 @@ void SystemWindow::dispose()
    // Hack to make sure code called from base ~Window does not interpret this
    // as a SystemWindow (which it no longer is by then):
    mpWindowImpl->mbSysWin = false;
    disposeBuilder();

    Window::dispose();
}
diff --git a/vcl/source/window/tabpage.cxx b/vcl/source/window/tabpage.cxx
index d554964..995438f 100644
--- a/vcl/source/window/tabpage.cxx
+++ b/vcl/source/window/tabpage.cxx
@@ -85,6 +85,17 @@ TabPage::TabPage(vcl::Window *pParent, const OString& rID, const OUString& rUIXM
    set_expand(true);
}

TabPage::~TabPage()
{
    dispose();
}

void TabPage::dispose()
{
    disposeBuilder();
    vcl::Window::dispose();
}

void TabPage::StateChanged( StateChangedType nType )
{
    Window::StateChanged( nType );