[Libreoffice-commits] core.git: Branch 'feature/vclref' - 3 commits - dbaccess/source extensions/source include/svtools include/vcl sd/source vcl/qa vcl/source

Michael Meeks michael.meeks at collabora.com
Thu Jan 1 09:36:03 PST 2015


 dbaccess/source/ui/control/curledit.cxx           |    5 -
 extensions/source/propctrlr/standardcontrol.cxx   |   13 ---
 extensions/source/propctrlr/standardcontrol.hxx   |    2 
 include/svtools/svmedit.hxx                       |    2 
 include/vcl/button.hxx                            |    2 
 include/vcl/combobox.hxx                          |   13 +--
 include/vcl/dialog.hxx                            |   16 ++-
 include/vcl/edit.hxx                              |   13 +--
 include/vcl/layout.hxx                            |   26 +++++-
 include/vcl/vclmedit.hxx                          |    2 
 include/vcl/vclref.hxx                            |    3 
 include/vcl/window.hxx                            |    3 
 sd/source/ui/animations/CustomAnimationDialog.cxx |   45 +++++------
 vcl/qa/cppunit/lifecycle.cxx                      |   34 ++++++++
 vcl/source/control/combobox.cxx                   |   11 +-
 vcl/source/control/edit.cxx                       |   89 ++++++++++++----------
 vcl/source/window/dialog.cxx                      |    8 -
 vcl/source/window/layout.cxx                      |   53 +++++--------
 vcl/source/window/mouse.cxx                       |    2 
 vcl/source/window/stacking.cxx                    |    6 +
 vcl/source/window/window.cxx                      |    3 
 vcl/source/window/window2.cxx                     |    2 
 22 files changed, 211 insertions(+), 142 deletions(-)

New commits:
commit 6398aac649c0c56ec019bc18f12a6913853e4347
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Thu Jan 1 09:42:15 2015 +0000

    vcl: manage SubEdit with references - and fix leak / cleanup.
    
    Change-Id: Icbfe237a55cfbd83739b055350d5a6a54a2fa36d

diff --git a/dbaccess/source/ui/control/curledit.cxx b/dbaccess/source/ui/control/curledit.cxx
index 22d8241..4924df6 100644
--- a/dbaccess/source/ui/control/curledit.cxx
+++ b/dbaccess/source/ui/control/curledit.cxx
@@ -40,10 +40,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeConnectionURLEdit(vcl:
 
 OConnectionURLEdit::~OConnectionURLEdit()
 {
-    // delete my sub controls
-    Edit* pSubEdit = GetSubEdit();
     SetSubEdit(NULL);
-    delete pSubEdit;
     delete m_pForcedPrefix;
 }
 
@@ -71,7 +68,7 @@ void OConnectionURLEdit::SetText(const OUString& _rStr, const Selection& /*_rNew
 {
     // create new sub controls, if necessary
     if (!GetSubEdit())
-        SetSubEdit(new Edit(this, 0));
+        SetSubEdit(EditRef(new Edit(this, 0)));
     if ( !m_pForcedPrefix )
     {
         m_pForcedPrefix = new FixedText(this, WB_VCENTER);
diff --git a/extensions/source/propctrlr/standardcontrol.cxx b/extensions/source/propctrlr/standardcontrol.cxx
index 4e1c600..d0ca9e7 100644
--- a/extensions/source/propctrlr/standardcontrol.cxx
+++ b/extensions/source/propctrlr/standardcontrol.cxx
@@ -1025,15 +1025,14 @@ namespace pcr
     DropDownEditControl::DropDownEditControl( vcl::Window* _pParent, WinBits _nStyle )
         :DropDownEditControl_Base( _pParent, _nStyle )
         ,m_pFloatingEdit( NULL )
-        ,m_pImplEdit( NULL )
         ,m_pDropdownButton( NULL )
         ,m_nOperationMode( eStringList )
         ,m_bDropdown( false )
     {
         SetCompoundControl( true );
 
-        m_pImplEdit = new MultiLineEdit( this, WB_TABSTOP | WB_IGNORETAB | WB_NOBORDER | (_nStyle & WB_READONLY) );
-        SetSubEdit( m_pImplEdit );
+        m_pImplEdit = MultiLineEditRef( new MultiLineEdit( this, WB_TABSTOP | WB_IGNORETAB | WB_NOBORDER | (_nStyle & WB_READONLY) ) );
+        SetSubEdit( m_pImplEdit.get() );
         m_pImplEdit->Show();
 
         if ( _nStyle & WB_DROPDOWN )
@@ -1067,11 +1066,7 @@ namespace pcr
             boost::scoped_ptr<vcl::Window> aTemp(m_pFloatingEdit);
             m_pFloatingEdit = NULL;
         }
-        {
-            boost::scoped_ptr<vcl::Window> aTemp(m_pImplEdit);
-            SetSubEdit( NULL );
-            m_pImplEdit = NULL;
-        }
+        SetSubEdit(EditRef());
         {
             boost::scoped_ptr<vcl::Window> aTemp(m_pDropdownButton);
             m_pDropdownButton = NULL;
@@ -1108,7 +1103,7 @@ namespace pcr
             {
                 if ( m_pHelper )
                 {
-                    m_pHelper->LoseFocusHdl( m_pImplEdit );
+                    m_pHelper->LoseFocusHdl( m_pImplEdit.get() );
                     m_pHelper->activateNextControl();
                 }
             }
diff --git a/extensions/source/propctrlr/standardcontrol.hxx b/extensions/source/propctrlr/standardcontrol.hxx
index a78b43e..6fae7db 100644
--- a/extensions/source/propctrlr/standardcontrol.hxx
+++ b/extensions/source/propctrlr/standardcontrol.hxx
@@ -375,7 +375,7 @@ namespace pcr
     {
     private:
         OMultilineFloatingEdit*             m_pFloatingEdit;
-        MultiLineEdit*                      m_pImplEdit;
+        VclReference<MultiLineEdit>         m_pImplEdit;
         PushButton*                         m_pDropdownButton;
         MultiLineOperationMode              m_nOperationMode;
         bool                                m_bDropdown : 1;
diff --git a/include/svtools/svmedit.hxx b/include/svtools/svmedit.hxx
index 33c2b90..726980f 100644
--- a/include/svtools/svmedit.hxx
+++ b/include/svtools/svmedit.hxx
@@ -27,7 +27,6 @@
 #include <svtools/colorcfg.hxx>
 
 
-
 class SVT_DLLPUBLIC MultiLineEdit : public VclMultiLineEdit
 {
 public:
@@ -36,6 +35,7 @@ public:
     virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >
     GetComponentInterface(bool bCreate = true) SAL_OVERRIDE;
 };
+typedef VclReference<MultiLineEdit> MultiLineEditRef;
 
 
 #endif // INCLUDED_SVTOOLS_SVMEDIT_HXX
diff --git a/include/vcl/button.hxx b/include/vcl/button.hxx
index c8aa69d..65c586d 100644
--- a/include/vcl/button.hxx
+++ b/include/vcl/button.hxx
@@ -177,7 +177,7 @@ public:
     void            SetSymbolAlign( SymbolAlign eAlign );
 
     void            SetDropDown( sal_uInt16 nStyle );
-    sal_uInt16          GetDropDown() const { return mnDDStyle; }
+    sal_uInt16      GetDropDown() const { return mnDDStyle; }
 
     void            SetState( TriState eState );
     TriState        GetState() const { return meState; }
diff --git a/include/vcl/combobox.hxx b/include/vcl/combobox.hxx
index 2da1f1b..5f5f6ea 100644
--- a/include/vcl/combobox.hxx
+++ b/include/vcl/combobox.hxx
@@ -39,7 +39,7 @@ class ImplBtn;
 class VCL_DLLPUBLIC ComboBox : public Edit
 {
 private:
-    Edit*                       mpSubEdit;
+    VclReference<Edit>          mpSubEdit;
     ImplListBox*                mpImplLB;
     ImplBtn*                    mpBtn;
     ImplListBoxFloatingWindow*  mpFloatWin;
@@ -48,7 +48,7 @@ private:
     bool                        mbDDAutoSize        : 1;
     bool                        mbSyntheticModify   : 1;
     bool                        mbMatchCase         : 1;
-    sal_Int32 m_nMaxWidthChars;
+    sal_Int32                   m_nMaxWidthChars;
     Link                        maSelectHdl;
     Link                        maDoubleClickHdl;
     boost::signals2::scoped_connection mAutocompleteConnection;
@@ -73,7 +73,7 @@ private:
     DECL_DLLPRIVATE_LINK(   ImplDoubleClickHdl, void* );
     DECL_DLLPRIVATE_LINK(   ImplPopupModeEndHdl, void* );
     DECL_DLLPRIVATE_LINK(   ImplSelectionChangedHdl, void* );
-    DECL_DLLPRIVATE_LINK( ImplListItemSelectHdl , void* );
+    DECL_DLLPRIVATE_LINK(   ImplListItemSelectHdl , void* );
 
     SAL_DLLPRIVATE void ImplClickButtonHandler( ImplBtn* );
     SAL_DLLPRIVATE void ImplUserDrawHandler( UserDrawEvent* );
@@ -90,7 +90,7 @@ protected:
 protected:
     bool            IsDropDownBox() const { return mpFloatWin ? true : false; }
 
-    virtual void  FillLayoutData() const SAL_OVERRIDE;
+    virtual void    FillLayoutData() const SAL_OVERRIDE;
 public:
     explicit        ComboBox( vcl::Window* pParent, WinBits nStyle = 0 );
     explicit        ComboBox( vcl::Window* pParent, const ResId& );
@@ -119,12 +119,12 @@ public:
 
     Rectangle       GetDropDownPosSizePixel() const;
 
-    void AdaptDropDownLineCountToMaximum();
+    void            AdaptDropDownLineCountToMaximum();
     void            SetDropDownLineCount( sal_uInt16 nLines );
     sal_uInt16      GetDropDownLineCount() const;
 
     void            EnableAutoSize( bool bAuto );
-    bool        IsAutoSizeEnabled() const               { return mbDDAutoSize; }
+    bool            IsAutoSizeEnabled() const               { return mbDDAutoSize; }
 
     void            EnableDDAutoWidth( bool b );
 
@@ -224,6 +224,7 @@ public:
 
     virtual bool set_property(const OString &rKey, const OString &rValue) SAL_OVERRIDE;
 };
+typedef VclReference<ComboBox> ComboBoxPtr;
 
 #endif  // _COMBOBOX_HXX
 
diff --git a/include/vcl/edit.hxx b/include/vcl/edit.hxx
index e61d31f..93868c7 100644
--- a/include/vcl/edit.hxx
+++ b/include/vcl/edit.hxx
@@ -27,6 +27,7 @@
 #include <vcl/ctrl.hxx>
 #include <vcl/menu.hxx>
 #include <vcl/dndhelp.hxx>
+#include <vcl/vclref.hxx>
 #include <com/sun/star/uno/Reference.h>
 
 namespace com {
@@ -67,7 +68,7 @@ enum AutocompleteAction{ AUTOCOMPLETE_KEYINPUT, AUTOCOMPLETE_TABFORWARD, AUTOCOM
 class VCL_DLLPUBLIC Edit : public Control, public vcl::unohelper::DragAndDropClient
 {
 private:
-    Edit*               mpSubEdit;
+    VclReference<Edit>  mpSubEdit;
     Timer*              mpUpdateDataTimer;
     TextFilter*         mpFilterText;
     DDInfo*             mpDDInfo;
@@ -84,7 +85,7 @@ private:
     sal_Int32           mnMaxWidthChars;
     AutocompleteAction  meAutocompleteAction;
     sal_Unicode         mcEchoChar;
-    bool            mbModified:1,
+    bool                mbModified:1,
                         mbInternModified:1,
                         mbReadOnly:1,
                         mbInsertMode:1,
@@ -163,6 +164,7 @@ public:
                         Edit( vcl::Window* pParent, WinBits nStyle = WB_BORDER );
                         Edit( vcl::Window* pParent, const ResId& rResId );
                         virtual ~Edit();
+                        virtual void dispose() SAL_OVERRIDE;
 
     virtual void        MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     virtual void        MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
@@ -185,7 +187,7 @@ public:
 
     virtual void        SetModifyFlag();
     virtual void        ClearModifyFlag();
-    virtual bool        IsModified() const { return mpSubEdit ? mpSubEdit->mbModified : mbModified; }
+    virtual bool        IsModified() const { return mpSubEdit.get() ? mpSubEdit->mbModified : mbModified; }
 
     virtual void        EnableUpdateData( sal_uLong nTimeout = EDIT_UPDATEDATA_TIMEOUT );
     virtual void        DisableUpdateData() { delete mpUpdateDataTimer; mpUpdateDataTimer = NULL; }
@@ -234,8 +236,8 @@ public:
     virtual const Link& GetModifyHdl() const { return maModifyHdl; }
     virtual void        SetUpdateDataHdl( const Link& rLink ) { maUpdateDataHdl = rLink; }
 
-    void                SetSubEdit( Edit* pEdit );
-    Edit*               GetSubEdit() const { return mpSubEdit; }
+    void                SetSubEdit( VclReference<Edit> pEdit );
+    Edit*               GetSubEdit() const { return mpSubEdit.get(); }
 
     boost::signals2::signal< void ( Edit* ) > autocompleteSignal;
     AutocompleteAction  GetAutocompleteAction() const { return meAutocompleteAction; }
@@ -267,6 +269,7 @@ public:
     // global style settings (needed by sc's inputwin.cxx)
     static Size GetMinimumEditSize();
 };
+typedef VclReference<Edit> EditRef;
 
 #endif // INCLUDED_VCL_EDIT_HXX
 
diff --git a/include/vcl/vclmedit.hxx b/include/vcl/vclmedit.hxx
index fe5280d..751a627 100644
--- a/include/vcl/vclmedit.hxx
+++ b/include/vcl/vclmedit.hxx
@@ -25,7 +25,6 @@
 #include <vcl/edit.hxx>
 #include <vcl/dllapi.h>
 
-
 class ImpVclMEdit;
 class Timer;
 class ExtTextEngine;
@@ -131,6 +130,7 @@ public:
 
     virtual bool set_property(const OString &rKey, const OString &rValue) SAL_OVERRIDE;
 };
+typedef VclReference<VclMultiLineEdit> VclMultiLineEditRef;
 
 #endif // INCLUDED_VCL_VCLMEDIT_HXX
 
diff --git a/include/vcl/vclref.hxx b/include/vcl/vclref.hxx
index b9b7b53..ba3fdaa 100644
--- a/include/vcl/vclref.hxx
+++ b/include/vcl/vclref.hxx
@@ -75,7 +75,6 @@ public:
         // hold it alive for the lifetime of this method
         ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
         m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
-        assert(aTmp.get());
         if (aTmp.get())
             aTmp->dispose();
     }
diff --git a/sd/source/ui/animations/CustomAnimationDialog.cxx b/sd/source/ui/animations/CustomAnimationDialog.cxx
index 97f9559..90a2dad 100644
--- a/sd/source/ui/animations/CustomAnimationDialog.cxx
+++ b/sd/source/ui/animations/CustomAnimationDialog.cxx
@@ -320,7 +320,7 @@ Control* FontPropertyBox::getControl()
 class DropdownMenuBox : public Edit
 {
 public:
-    DropdownMenuBox( vcl::Window* pParent, Edit* pSubControl, PopupMenu* pMenu );
+    DropdownMenuBox( vcl::Window* pParent, const EditRef &pSubControl, PopupMenu* pMenu );
     virtual ~DropdownMenuBox();
 
     void Resize() SAL_OVERRIDE;
@@ -329,12 +329,12 @@ public:
     void SetMenuSelectHdl( const Link& rLink ) { mpDropdownButton->SetSelectHdl( rLink ); }
 
 private:
-    Edit* mpSubControl;
+    EditRef     mpSubControl;
     MenuButton* mpDropdownButton;
-    PopupMenu* mpMenu;
+    PopupMenu*  mpMenu;
 };
 
-DropdownMenuBox::DropdownMenuBox( vcl::Window* pParent, Edit* pSubControl, PopupMenu* pMenu )
+DropdownMenuBox::DropdownMenuBox( vcl::Window* pParent, const EditRef &pSubControl, PopupMenu* pMenu )
 :   Edit( pParent, WB_BORDER|WB_TABSTOP| WB_DIALOGCONTROL ),
     mpSubControl(pSubControl),mpDropdownButton(0),mpMenu(pMenu)
 {
@@ -350,8 +350,7 @@ DropdownMenuBox::DropdownMenuBox( vcl::Window* pParent, Edit* pSubControl, Popup
 
 DropdownMenuBox::~DropdownMenuBox()
 {
-    SetSubEdit( 0 );
-    delete mpSubControl;
+    SetSubEdit(EditRef());
     delete mpDropdownButton;
     delete mpMenu;
 }
@@ -407,7 +406,7 @@ public:
 private:
     DropdownMenuBox* mpControl;
     PopupMenu* mpMenu;
-    MetricField* mpMetric;
+    VclReference<MetricField> mpMetric;
 };
 
 CharHeightPropertyBox::CharHeightPropertyBox( sal_Int32 nControlType, vcl::Window* pParent, const Any& rValue, const Link& rModifyHdl )
@@ -419,7 +418,7 @@ CharHeightPropertyBox::CharHeightPropertyBox( sal_Int32 nControlType, vcl::Windo
     mpMetric->SetMax( 1000 );
 
     mpMenu = new PopupMenu(SdResId( RID_CUSTOMANIMATION_FONTSIZE_POPUP ) );
-    mpControl = new DropdownMenuBox( pParent, mpMetric, mpMenu );
+    mpControl = new DropdownMenuBox( pParent, mpMetric.get(), mpMenu );
     mpControl->SetMenuSelectHdl( LINK( this, CharHeightPropertyBox, implMenuSelectHdl ));
     mpControl->SetModifyHdl( rModifyHdl );
     mpControl->SetHelpId( HID_SD_CUSTOMANIMATIONPANE_CHARHEIGHTPROPERTYBOX );
@@ -450,7 +449,7 @@ IMPL_LINK( CharHeightPropertyBox, implMenuSelectHdl, MenuButton*, pPb )
 
 void CharHeightPropertyBox::setValue( const Any& rValue, const OUString& )
 {
-    if( mpMetric )
+    if( mpMetric.get() )
     {
         double fValue = 0.0;
         rValue >>= fValue;
@@ -487,7 +486,7 @@ public:
 private:
     DropdownMenuBox* mpControl;
     PopupMenu* mpMenu;
-    MetricField* mpMetric;
+    VclReference<MetricField> mpMetric;
     Link maModifyHdl;
 };
 
@@ -508,7 +507,7 @@ TransparencyPropertyBox::TransparencyPropertyBox( sal_Int32 nControlType, vcl::W
         mpMenu->InsertItem( i, aStr );
     }
 
-    mpControl = new DropdownMenuBox( pParent, mpMetric, mpMenu );
+    mpControl = new DropdownMenuBox( pParent, mpMetric.get(), mpMenu );
     mpControl->SetMenuSelectHdl( LINK( this, TransparencyPropertyBox, implMenuSelectHdl ));
     mpControl->SetHelpId( HID_SD_CUSTOMANIMATIONPANE_TRANSPARENCYPROPERTYBOX );
 
@@ -534,7 +533,7 @@ void TransparencyPropertyBox::updateMenu()
 IMPL_LINK_NOARG(TransparencyPropertyBox, implModifyHdl)
 {
     updateMenu();
-    maModifyHdl.Call(mpMetric);
+    maModifyHdl.Call(mpMetric.get());
 
     return 0;
 }
@@ -552,7 +551,7 @@ IMPL_LINK( TransparencyPropertyBox, implMenuSelectHdl, MenuButton*, pPb )
 
 void TransparencyPropertyBox::setValue( const Any& rValue, const OUString& )
 {
-    if( mpMetric )
+    if( mpMetric.get() )
     {
         double fValue = 0.0;
         rValue >>= fValue;
@@ -591,7 +590,7 @@ public:
 private:
     DropdownMenuBox* mpControl;
     PopupMenu* mpMenu;
-    MetricField* mpMetric;
+    VclReference<MetricField> mpMetric;
     Link maModifyHdl;
 };
 
@@ -606,7 +605,7 @@ RotationPropertyBox::RotationPropertyBox( sal_Int32 nControlType, vcl::Window* p
     mpMetric->SetMax( 10000 );
 
     mpMenu = new PopupMenu(SdResId( RID_CUSTOMANIMATION_ROTATION_POPUP ) );
-    mpControl = new DropdownMenuBox( pParent, mpMetric, mpMenu );
+    mpControl = new DropdownMenuBox( pParent, mpMetric.get(), mpMenu );
     mpControl->SetMenuSelectHdl( LINK( this, RotationPropertyBox, implMenuSelectHdl ));
     mpControl->SetHelpId( HID_SD_CUSTOMANIMATIONPANE_ROTATIONPROPERTYBOX );
 
@@ -640,7 +639,7 @@ void RotationPropertyBox::updateMenu()
 IMPL_LINK_NOARG(RotationPropertyBox, implModifyHdl)
 {
     updateMenu();
-    maModifyHdl.Call(mpMetric);
+    maModifyHdl.Call(mpMetric.get());
 
     return 0;
 }
@@ -677,7 +676,7 @@ IMPL_LINK( RotationPropertyBox, implMenuSelectHdl, MenuButton*, pPb )
 
 void RotationPropertyBox::setValue( const Any& rValue, const OUString& )
 {
-    if( mpMetric )
+    if( mpMetric.get() )
     {
         double fValue = 0.0;
         rValue >>= fValue;
@@ -716,7 +715,7 @@ public:
 private:
     DropdownMenuBox* mpControl;
     PopupMenu* mpMenu;
-    MetricField* mpMetric;
+    VclReference<MetricField> mpMetric;
     Link maModifyHdl;
     int mnDirection;
 };
@@ -731,7 +730,7 @@ ScalePropertyBox::ScalePropertyBox( sal_Int32 nControlType, vcl::Window* pParent
     mpMetric->SetMax( 10000 );
 
     mpMenu = new PopupMenu(SdResId( RID_CUSTOMANIMATION_SCALE_POPUP ) );
-    mpControl = new DropdownMenuBox( pParent, mpMetric, mpMenu );
+    mpControl = new DropdownMenuBox( pParent, mpMetric.get(), mpMenu );
     mpControl->SetMenuSelectHdl( LINK( this, ScalePropertyBox, implMenuSelectHdl ));
     mpControl->SetHelpId( HID_SD_CUSTOMANIMATIONPANE_SCALEPROPERTYBOX );
 
@@ -764,7 +763,7 @@ void ScalePropertyBox::updateMenu()
 IMPL_LINK_NOARG(ScalePropertyBox, implModifyHdl)
 {
     updateMenu();
-    maModifyHdl.Call(mpMetric);
+    maModifyHdl.Call(mpMetric.get());
 
     return 0;
 }
@@ -810,7 +809,7 @@ IMPL_LINK( ScalePropertyBox, implMenuSelectHdl, MenuButton*, pPb )
 
 void ScalePropertyBox::setValue( const Any& rValue, const OUString& )
 {
-    if( mpMetric )
+    if( mpMetric.get() )
     {
         ValuePair aValues;
         rValue >>= aValues;
@@ -878,7 +877,7 @@ public:
 private:
     DropdownMenuBox* mpControl;
     PopupMenu* mpMenu;
-    Edit* mpEdit;
+    EditRef mpEdit;
     Link maModifyHdl;
 
     float mfFontWeight;
@@ -950,7 +949,7 @@ IMPL_LINK( FontStylePropertyBox, implMenuSelectHdl, MenuButton*, pPb )
     }
 
     update();
-    maModifyHdl.Call(mpEdit);
+    maModifyHdl.Call(mpEdit.get());
 
     return 0;
 }
diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx
index 1c887b9..e054672 100644
--- a/vcl/qa/cppunit/lifecycle.cxx
+++ b/vcl/qa/cppunit/lifecycle.cxx
@@ -12,6 +12,9 @@
 
 #include <vcl/wrkwin.hxx>
 #include <vcl/button.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/combobox.hxx>
+#include <vcl/field.hxx>
 
 class LifecycleTest : public test::BootstrapFixture
 {
@@ -20,6 +23,7 @@ class LifecycleTest : public test::BootstrapFixture
 public:
     LifecycleTest() : BootstrapFixture(true, false) {}
 
+    void testCast();
     void testMultiDispose();
     void testIsolatedWidgets();
     void testParentedWidgets();
@@ -31,6 +35,17 @@ public:
     CPPUNIT_TEST_SUITE_END();
 };
 
+// A compile time sanity check
+void LifecycleTest::testCast()
+{
+//    VclReference<PushButton> xButton(new PushButton(NULL, 0));
+//    VclReference<vcl::Window> xWindow(xButton);
+
+//    VclReference<MetricField> xField(new MetricField(NULL, 0));
+//    VclReference<SpinField> xSpin(xField);
+//    VclReference<Edit> xEdit(xField);
+}
+
 void LifecycleTest::testMultiDispose()
 {
     VclReference<WorkWindow> xWin(new WorkWindow((vcl::Window *)NULL,
@@ -54,7 +69,9 @@ void LifecycleTest::testWidgets(vcl::Window *pParent)
     // Some widgets really insist on adoption.
     if (pParent)
     {
-        { CheckBoxPtr     aPtr(new CheckBox(pParent));  }
+        { CheckBoxPtr     aPtr(new CheckBox(pParent));    }
+//        { EditRef         aPtr(new Edit(pParent));        }
+//        { ComboBoxPtr     aPtr(new ComboBox(pParent)); }
     }
 //    { RadioButtonPtr  aPtr(new RadioButton(pParent));  }
 }
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
index 9706941..7caa6a6 100644
--- a/vcl/source/control/combobox.cxx
+++ b/vcl/source/control/combobox.cxx
@@ -68,8 +68,7 @@ ComboBox::ComboBox( vcl::Window* pParent, const ResId& rResId ) :
 
 ComboBox::~ComboBox()
 {
-    SetSubEdit( NULL );
-    delete mpSubEdit;
+    SetSubEdit(VclReference<Edit>());
 
     ImplListBox *pImplLB = mpImplLB;
     mpImplLB = NULL;
@@ -579,7 +578,7 @@ void ComboBox::Resize()
 void ComboBox::FillLayoutData() const
 {
     mpControlData->mpLayoutData = new vcl::ControlLayoutData();
-    AppendLayoutData( *mpSubEdit );
+    AppendLayoutData( *mpSubEdit.get() );
     mpSubEdit->SetLayoutDataParent( this );
     ImplListBoxWindowPtr rMainWindow = mpImplLB->GetMainWindow();
     if( mpFloatWin )
@@ -693,7 +692,7 @@ bool ComboBox::PreNotify( NotifyEvent& rNEvt )
 bool ComboBox::Notify( NotifyEvent& rNEvt )
 {
     bool nDone = false;
-    if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( rNEvt.GetWindow() == mpSubEdit )
+    if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( rNEvt.GetWindow() == mpSubEdit.get() )
             && !IsReadOnly() )
     {
         KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
@@ -731,7 +730,7 @@ bool ComboBox::Notify( NotifyEvent& rNEvt )
 
             case KEY_RETURN:
             {
-                if( ( rNEvt.GetWindow() == mpSubEdit ) && IsInDropDown() )
+                if( ( rNEvt.GetWindow() == mpSubEdit.get() ) && IsInDropDown() )
                 {
                     mpImplLB->ProcessKeyInput( aKeyEvt );
                     nDone = true;
@@ -749,7 +748,7 @@ bool ComboBox::Notify( NotifyEvent& rNEvt )
     }
     else if( (rNEvt.GetType() == MouseNotifyEvent::COMMAND) &&
              (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
-             (rNEvt.GetWindow() == mpSubEdit) )
+             (rNEvt.GetWindow() == mpSubEdit.get()) )
     {
         sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
         if  (   ( nWheelBehavior == MOUSE_WHEEL_ALWAYS )
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index 821d535..b1e9c66 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -239,7 +239,14 @@ bool Edit::set_property(const OString &rKey, const OString &rValue)
 
 Edit::~Edit()
 {
+    dispose();
+}
+
+void Edit::dispose()
+{
     delete mpDDInfo;
+    mpDDInfo = NULL;
+
     vcl::Cursor* pCursor = GetCursor();
     if ( pCursor )
     {
@@ -248,8 +255,10 @@ Edit::~Edit()
     }
 
     delete mpIMEInfos;
+    mpIMEInfos = NULL;
 
     delete mpUpdateDataTimer;
+    mpUpdateDataTimer = NULL;
 
     if ( mxDnDListener.is() )
     {
@@ -266,6 +275,7 @@ Edit::~Edit()
 
         uno::Reference< lang::XEventListener> xEL( mxDnDListener, uno::UNO_QUERY );
         xEL->disposing( lang::EventObject() );  // #95154# #96585# Empty Source means it's the Client
+        mxDnDListener.clear();
     }
 
     SetType(WINDOW_WINDOW);
@@ -273,7 +283,7 @@ Edit::~Edit()
 
 void Edit::ImplInitEditData()
 {
-    mpSubEdit               = NULL;
+    mpSubEdit               = EditRef();
     mpUpdateDataTimer       = NULL;
     mpFilterText            = NULL;
     mnXOffset               = 0;
@@ -1319,7 +1329,7 @@ void Edit::ImplPaste( uno::Reference< datatransfer::clipboard::XClipboard >& rxC
 
 void Edit::MouseButtonDown( const MouseEvent& rMEvt )
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
     {
         Control::MouseButtonDown( rMEvt );
         return;
@@ -1741,7 +1751,7 @@ void Edit::KeyInput( const KeyEvent& rKEvt )
     if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() )
         mpUpdateDataTimer->Start();//do not update while the user is still travelling in the control
 
-    if ( mpSubEdit || !ImplHandleKeyEvent( rKEvt ) )
+    if ( mpSubEdit.get() || !ImplHandleKeyEvent( rKEvt ) )
         Control::KeyInput( rKEvt );
 }
 
@@ -1753,13 +1763,13 @@ void Edit::FillLayoutData() const
 
 void Edit::Paint( const Rectangle& )
 {
-    if ( !mpSubEdit )
+    if ( !mpSubEdit.get() )
         ImplRepaint();
 }
 
 void Edit::Resize()
 {
-    if ( !mpSubEdit && IsReallyVisible() )
+    if ( !mpSubEdit.get() && IsReallyVisible() )
     {
         Control::Resize();
         // Wegen vertikaler Zentrierung...
@@ -1872,7 +1882,7 @@ void Edit::ImplInvalidateOutermostBorder( vcl::Window* pWin )
 
 void Edit::GetFocus()
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->ImplGrabFocus( GetGetFocusFlags() );
     else if ( !mbActivePopup )
     {
@@ -1925,7 +1935,7 @@ void Edit::GetFocus()
 
 vcl::Window* Edit::GetPreferredKeyInputWindow()
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         return mpSubEdit->GetPreferredKeyInputWindow();
     else
         return this;
@@ -1940,7 +1950,7 @@ void Edit::LoseFocus()
         mpUpdateDataTimer->Timeout();
     }
 
-    if ( !mpSubEdit )
+    if ( !mpSubEdit.get() )
     {
         // FIXME: this is currently only on OS X
         // check for other platforms that need similar handling
@@ -2196,11 +2206,11 @@ void Edit::StateChanged( StateChangedType nType )
 {
     if ( nType == StateChangedType::INITSHOW )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             mnXOffset = 0;  // if GrabFocus before while size was still wrong
             ImplAlign();
-            if ( !mpSubEdit )
+            if ( !mpSubEdit.get() )
                 ImplShowCursor( false );
         }
         // update background (eventual SetPaintTransparent)
@@ -2208,7 +2218,7 @@ void Edit::StateChanged( StateChangedType nType )
     }
     else if ( nType == StateChangedType::ENABLE )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             // change text color only
             ImplInvalidateOrRepaint();
@@ -2255,7 +2265,7 @@ void Edit::StateChanged( StateChangedType nType )
     }
     else if ( nType == StateChangedType::ZOOM )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             ImplInitSettings( true, false, false );
             ImplShowCursor( true );
@@ -2264,7 +2274,7 @@ void Edit::StateChanged( StateChangedType nType )
     }
     else if ( nType == StateChangedType::CONTROLFONT )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             ImplInitSettings( true, false, false );
             ImplShowCursor();
@@ -2273,7 +2283,7 @@ void Edit::StateChanged( StateChangedType nType )
     }
     else if ( nType == StateChangedType::CONTROLFOREGROUND )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             ImplInitSettings( false, true, false );
             Invalidate();
@@ -2281,7 +2291,7 @@ void Edit::StateChanged( StateChangedType nType )
     }
     else if ( nType == StateChangedType::CONTROLBACKGROUND )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             ImplInitSettings( false, false, true );
             Invalidate();
@@ -2298,7 +2308,7 @@ void Edit::DataChanged( const DataChangedEvent& rDCEvt )
          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
     {
-        if ( !mpSubEdit )
+        if ( !mpSubEdit.get() )
         {
             ImplInitSettings( true, true, true );
             ImplShowCursor( true );
@@ -2431,7 +2441,7 @@ void Edit::EnableUpdateData( sal_uLong nTimeout )
 void Edit::SetEchoChar( sal_Unicode c )
 {
     mcEchoChar = c;
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->SetEchoChar( c );
 }
 
@@ -2440,7 +2450,7 @@ void Edit::SetReadOnly( bool bReadOnly )
     if ( mbReadOnly != bool(bReadOnly) )
     {
         mbReadOnly = bReadOnly;
-        if ( mpSubEdit )
+        if ( mpSubEdit.get() )
             mpSubEdit->SetReadOnly( bReadOnly );
 
         StateChanged( StateChangedType::READONLY );
@@ -2452,7 +2462,7 @@ void Edit::SetInsertMode( bool bInsert )
     if ( bInsert != mbInsertMode )
     {
         mbInsertMode = bInsert;
-        if ( mpSubEdit )
+        if ( mpSubEdit.get() )
             mpSubEdit->SetInsertMode( bInsert );
         else
             ImplShowCursor();
@@ -2461,7 +2471,7 @@ void Edit::SetInsertMode( bool bInsert )
 
 bool Edit::IsInsertMode() const
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         return mpSubEdit->IsInsertMode();
     else
         return mbInsertMode;
@@ -2471,7 +2481,7 @@ void Edit::SetMaxTextLen(sal_Int32 nMaxLen)
 {
     mnMaxTextLen = nMaxLen > 0 ? nMaxLen : EDIT_NOLIMIT;
 
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->SetMaxTextLen( mnMaxTextLen );
     else
     {
@@ -2486,7 +2496,7 @@ void Edit::SetSelection( const Selection& rSelection )
     // directly afterwards which would change the selection again
     if ( IsTracking() )
         EndTracking();
-    else if ( mpSubEdit && mpSubEdit->IsTracking() )
+    else if ( mpSubEdit.get() && mpSubEdit->IsTracking() )
         mpSubEdit->EndTracking();
 
     ImplSetSelection( rSelection );
@@ -2494,7 +2504,7 @@ void Edit::SetSelection( const Selection& rSelection )
 
 void Edit::ImplSetSelection( const Selection& rSelection, bool bPaint )
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->ImplSetSelection( rSelection );
     else
     {
@@ -2556,7 +2566,7 @@ void Edit::ImplSetSelection( const Selection& rSelection, bool bPaint )
 
 const Selection& Edit::GetSelection() const
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         return mpSubEdit->GetSelection();
     else
         return maSelection;
@@ -2564,7 +2574,7 @@ const Selection& Edit::GetSelection() const
 
 void Edit::ReplaceSelected( const OUString& rStr )
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->ReplaceSelected( rStr );
     else
         ImplInsertText( rStr );
@@ -2572,7 +2582,7 @@ void Edit::ReplaceSelected( const OUString& rStr )
 
 void Edit::DeleteSelected()
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->DeleteSelected();
     else
     {
@@ -2583,7 +2593,7 @@ void Edit::DeleteSelected()
 
 OUString Edit::GetSelected() const
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         return mpSubEdit->GetSelected();
     else
     {
@@ -2619,7 +2629,7 @@ void Edit::Paste()
 
 void Edit::Undo()
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->Undo();
     else
     {
@@ -2633,7 +2643,7 @@ void Edit::Undo()
 
 void Edit::SetText( const OUString& rStr )
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->SetText( rStr );     // not directly ImplSetText if SetText overloaded
     else
     {
@@ -2644,7 +2654,7 @@ void Edit::SetText( const OUString& rStr )
 
 void Edit::SetText( const OUString& rStr, const Selection& rSelection )
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->SetText( rStr, rSelection );
     else
         ImplSetText( rStr, &rSelection );
@@ -2652,7 +2662,7 @@ void Edit::SetText( const OUString& rStr, const Selection& rSelection )
 
 OUString Edit::GetText() const
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         return mpSubEdit->GetText();
     else
         return maText.toString();
@@ -2660,7 +2670,7 @@ OUString Edit::GetText() const
 
 void Edit::SetPlaceholderText( const OUString& rStr )
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->SetPlaceholderText( rStr );
     else if ( maPlaceholderText != rStr )
     {
@@ -2672,7 +2682,7 @@ void Edit::SetPlaceholderText( const OUString& rStr )
 
 OUString Edit::GetPlaceholderText() const
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         return mpSubEdit->GetPlaceholderText();
 
     return maPlaceholderText;
@@ -2680,7 +2690,7 @@ OUString Edit::GetPlaceholderText() const
 
 void Edit::SetModifyFlag()
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->mbModified = true;
     else
         mbModified = true;
@@ -2688,16 +2698,17 @@ void Edit::SetModifyFlag()
 
 void Edit::ClearModifyFlag()
 {
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
         mpSubEdit->mbModified = false;
     else
         mbModified = false;
 }
 
-void Edit::SetSubEdit( Edit* pEdit )
+void Edit::SetSubEdit( VclReference<Edit> pEdit )
 {
+    mpSubEdit.disposeAndClear();
     mpSubEdit = pEdit;
-    if ( mpSubEdit )
+    if ( mpSubEdit.get() )
     {
         SetPointer( POINTER_ARROW );    // Nur das SubEdit hat den BEAM...
         mpSubEdit->mbIsSubEdit = true;
@@ -2793,7 +2804,7 @@ Size Edit::CalcSize(sal_Int32 nChars) const
 
 sal_Int32 Edit::GetMaxVisChars() const
 {
-    const vcl::Window* pW = mpSubEdit ? mpSubEdit : this;
+    const vcl::Window* pW = mpSubEdit.get() ? mpSubEdit.get() : this;
     sal_Int32 nOutWidth = pW->GetOutputSizePixel().Width();
     sal_Int32 nCharWidth = GetTextWidth( OUString('x') );
     return nCharWidth ? nOutWidth/nCharWidth : 0;
@@ -3025,7 +3036,7 @@ void Edit::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEv
 
 OUString Edit::GetSurroundingText() const
 {
-    if (mpSubEdit)
+    if (mpSubEdit.get())
         return mpSubEdit->GetSurroundingText();
     return maText.toString();
 }
diff --git a/vcl/source/window/mouse.cxx b/vcl/source/window/mouse.cxx
index 054f10b..abec4d7 100644
--- a/vcl/source/window/mouse.cxx
+++ b/vcl/source/window/mouse.cxx
@@ -649,6 +649,8 @@ void Window::ImplStartDnd()
 
 Reference< css::datatransfer::dnd::XDropTarget > Window::GetDropTarget()
 {
+    if( !mpWindowImpl )
+        return Reference< css::datatransfer::dnd::XDropTarget >();
 
     if( ! mpWindowImpl->mxDNDListenerContainer.is() )
     {
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
index 3f9df5e..1815cdd 100644
--- a/vcl/source/window/window2.cxx
+++ b/vcl/source/window/window2.cxx
@@ -1317,6 +1317,8 @@ bool Window::IsWait() const
 
 vcl::Cursor* Window::GetCursor() const
 {
+    if (!mpWindowImpl)
+        return NULL;
     return mpWindowImpl->mpCursor;
 }
 
commit 7ecaa563b78eb80e9a50e3fa82bee248f9b385f1
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Dec 31 14:05:46 2014 +0000

    vcl: convert MessageDialog to use VclReferences.
    
    Change-Id: I24035c67c99ce431e94b39bd6d0d3b274fa55fa8

diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 11b8625..d9cb949 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -24,6 +24,7 @@
 #include <vcl/dllapi.h>
 #include <vcl/syswin.hxx>
 #include <vcl/timer.hxx>
+#include <vcl/vclref.hxx>
 
 // parameter to pass to the dialog constructor if really no parent is wanted
 // whereas NULL chooses the default dialog parent
@@ -47,8 +48,8 @@ private:
     bool            mbInClose;
     bool            mbModalMode;
 
-    VclButtonBox*   mpActionArea;
-    VclBox*         mpContentArea;
+    VclReference<VclButtonBox> mpActionArea;
+    VclReference<VclBox>       mpContentArea;
 
     SAL_DLLPRIVATE void    ImplInitDialogData();
     SAL_DLLPRIVATE void    ImplInitSettings();
@@ -75,8 +76,8 @@ protected:
 
 protected:
     friend class VclBuilder;
-    void set_action_area(VclButtonBox *pBox);
-    void set_content_area(VclBox *pBox);
+    void set_action_area(const VclReference<VclButtonBox> &xBox);
+    void set_content_area(const VclReference<VclBox> &xBox);
 
 public:
     explicit        Dialog( vcl::Window* pParent, WinBits nStyle = WB_STDDIALOG );
@@ -89,8 +90,8 @@ public:
 
     virtual void queue_resize(StateChangedType eReason = StateChangedType::LAYOUT) SAL_OVERRIDE;
     virtual bool set_property(const OString &rKey, const OString &rValue) SAL_OVERRIDE;
-    VclButtonBox* get_action_area() { return mpActionArea;}
-    VclBox* get_content_area() { return mpContentArea;}
+    VclButtonBox* get_action_area() { return mpActionArea.get(); }
+    VclBox* get_content_area() { return mpContentArea.get(); }
 
     virtual bool    Close() SAL_OVERRIDE;
 
@@ -122,6 +123,7 @@ public:
 
     void            GrabFocusToFirstControl();
 };
+typedef VclReference<Dialog> DialogRef;
 
 // - ModelessDialog -
 class VCL_DLLPUBLIC ModelessDialog : public Dialog
@@ -133,6 +135,7 @@ class VCL_DLLPUBLIC ModelessDialog : public Dialog
 public:
     explicit        ModelessDialog( vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription );
 };
+typedef VclReference<ModelessDialog> ModelessDialogRef;
 
 // - ModalDialog -
 class VCL_DLLPUBLIC ModalDialog : public Dialog
@@ -153,6 +156,7 @@ private:
     SAL_DLLPRIVATE         ModalDialog (const ModalDialog &);
     SAL_DLLPRIVATE         ModalDialog & operator= (const ModalDialog &);
 };
+typedef VclReference<ModalDialog> ModalDialogRef;
 
 #endif // INCLUDED_VCL_DIALOG_HXX
 
diff --git a/include/vcl/layout.hxx b/include/vcl/layout.hxx
index 4025d91..843366b 100644
--- a/include/vcl/layout.hxx
+++ b/include/vcl/layout.hxx
@@ -17,6 +17,7 @@
 #include <vcl/scrbar.hxx>
 #include <vcl/vclmedit.hxx>
 #include <vcl/window.hxx>
+#include <vcl/vclref.hxx>
 #include <boost/multi_array.hpp>
 #include <set>
 
@@ -58,6 +59,7 @@ public:
 private:
     bool m_bLayoutDirty;
 };
+typedef VclReference<VclContainer> VclContainerRef;
 
 class VCL_DLLPUBLIC VclBox : public VclContainer
 {
@@ -109,6 +111,7 @@ protected:
 
     virtual bool getPrimaryDimensionChildExpand(const vcl::Window &rWindow) const = 0;
 };
+typedef VclReference<VclBox> VclBoxRef;
 
 class VCL_DLLPUBLIC VclVBox : public VclBox
 {
@@ -156,6 +159,7 @@ protected:
         return rWindow.get_expand() || rWindow.get_vexpand();
     }
 };
+typedef VclReference<VclVBox> VclVBoxRef;
 
 class VCL_DLLPUBLIC VclHBox : public VclBox
 {
@@ -203,6 +207,7 @@ protected:
         return rWindow.get_expand() || rWindow.get_hexpand();
     }
 };
+typedef VclReference<VclHBox> VclHBoxRef;
 
 enum VclButtonBoxStyle
 {
@@ -248,6 +253,7 @@ private:
     Requisition calculatePrimarySecondaryRequisitions() const;
     Size addReqGroups(const VclButtonBox::Requisition &rReq) const;
 };
+typedef VclReference<VclButtonBox> VclButtonBoxRef;
 
 class VCL_DLLPUBLIC VclVButtonBox : public VclButtonBox
 {
@@ -295,6 +301,7 @@ protected:
         return rWindow.get_expand() || rWindow.get_vexpand();
     }
 };
+typedef VclReference<VclVButtonBox> VclVButtonBoxRef;
 
 class VCL_DLLPUBLIC VclHButtonBox : public VclButtonBox
 {
@@ -342,6 +349,7 @@ protected:
         return rWindow.get_expand() || rWindow.get_hexpand();
     }
 };
+typedef VclReference<VclHButtonBox> VclHButtonBoxRef;
 
 class VCL_DLLPUBLIC VclGrid : public VclContainer
 {
@@ -435,6 +443,7 @@ public:
     }
     virtual bool set_property(const OString &rKey, const OString &rValue) SAL_OVERRIDE;
 };
+typedef VclReference<VclGrid> VclGridRef;
 
 VCL_DLLPUBLIC void setGridAttach(vcl::Window &rWidget, sal_Int32 nLeft, sal_Int32 nTop,
     sal_Int32 nWidth = 1, sal_Int32 nHeight = 1);
@@ -451,6 +460,7 @@ public:
     virtual Size calculateRequisition() const SAL_OVERRIDE;
     virtual void setAllocation(const Size &rAllocation) SAL_OVERRIDE;
 };
+typedef VclReference<VclBin> VclBinRef;
 
 class VCL_DLLPUBLIC VclFrame : public VclBin
 {
@@ -477,6 +487,7 @@ protected:
     virtual void setAllocation(const Size &rAllocation) SAL_OVERRIDE;
     virtual OUString getDefaultAccessibleName() const SAL_OVERRIDE;
 };
+typedef VclReference<VclFrame> VclFrameRef;
 
 class VCL_DLLPUBLIC VclAlignment : public VclBin
 {
@@ -507,6 +518,7 @@ private:
     float m_fYAlign;
     float m_fYScale;
 };
+typedef VclReference<VclAlignment> VclAlignmentRef;
 
 class VCL_DLLPUBLIC VclExpander : public VclBin
 {
@@ -551,6 +563,7 @@ private:
     Link maExpandedHdl;
     DECL_DLLPRIVATE_LINK(ClickHdl, DisclosureButton* pBtn);
 };
+typedef VclReference<VclExpander> VclExpanderRef;
 
 class VCL_DLLPUBLIC VclScrolledWindow : public VclBin
 {
@@ -578,6 +591,7 @@ private:
     ScrollBarPtr m_pHScroll;
     ScrollBarBox m_aScrollBarBox;
 };
+typedef VclReference<VclScrolledWindow> VclScrolledWindowRef;
 
 class VCL_DLLPUBLIC VclViewport : public VclBin
 {
@@ -589,6 +603,7 @@ public:
 protected:
     virtual void setAllocation(const Size &rAllocation) SAL_OVERRIDE;
 };
+typedef VclReference<VclViewport> VclViewportRef;
 
 //Enforces that its children are always the same size as itself.
 //Intercepts any Commands intended for its children.
@@ -633,6 +648,7 @@ public:
 
     virtual void Command(const CommandEvent& rCEvt) SAL_OVERRIDE;
 };
+typedef VclReference<VclEventBox> VclEventBoxRef;
 
 enum VclSizeGroupMode
 {
@@ -684,6 +700,7 @@ public:
     }
     bool set_property(const OString &rKey, const OString &rValue);
 };
+typedef VclReference<VclSizeGroup> VclSizeGroupRef;
 
 enum VclButtonsType
 {
@@ -708,13 +725,13 @@ class VCL_DLLPUBLIC MessageDialog : public Dialog
 private:
     VclButtonsType m_eButtonsType;
     VclMessageType m_eMessageType;
-    VclBox *m_pOwnedContentArea;
-    VclButtonBox *m_pOwnedActionArea;
-    VclGrid* m_pGrid;
+    VclBoxRef m_pOwnedContentArea;
+    VclButtonBoxRef m_pOwnedActionArea;
+    VclGridRef m_pGrid;
     FixedImage* m_pImage;
     VclMultiLineEdit* m_pPrimaryMessage;
     VclMultiLineEdit* m_pSecondaryMessage;
-    std::vector<PushButton*> m_aOwnedButtons;
+    std::vector<PushButtonPtr> m_aOwnedButtons;
     std::map<const vcl::Window*, short> m_aResponses;
     OUString m_sPrimaryString;
     OUString m_sSecondaryString;
@@ -747,6 +764,7 @@ public:
     static void SetMessagesWidths(vcl::Window *pParent, VclMultiLineEdit *pPrimaryMessage,
         VclMultiLineEdit *pSecondaryMessage);
 };
+typedef VclReference<MessageDialog> MessageDialogRef;
 
 VCL_DLLPUBLIC Size bestmaxFrameSizeForScreenSize(const Size &rScreenSize);
 
diff --git a/include/vcl/vclref.hxx b/include/vcl/vclref.hxx
index ddbff3e..b9b7b53 100644
--- a/include/vcl/vclref.hxx
+++ b/include/vcl/vclref.hxx
@@ -50,7 +50,7 @@ public:
     /** Copy constructor...
      */
     inline VclReference (const VclReference<reference_type> & handle)
-        : m_rInnerRef (handle)
+        : m_rInnerRef (handle.m_rInnerRef)
     {}
 
 
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 6848c29..29dc077 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -513,14 +513,14 @@ Dialog::Dialog(vcl::Window* pParent, WinBits nStyle)
     ImplInit( pParent, nStyle );
 }
 
-void Dialog::set_action_area(VclButtonBox* pActionArea)
+void Dialog::set_action_area(const VclButtonBoxRef &xBox)
 {
-    mpActionArea = pActionArea;
+    mpActionArea = xBox;
 }
 
-void Dialog::set_content_area(VclBox* pContentArea)
+void Dialog::set_content_area(const VclBoxRef &xBox)
 {
-    mpContentArea = pContentArea;
+    mpContentArea = xBox;
 }
 
 void Dialog::settingOptimalLayoutSize(VclBox *pBox)
diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx
index ea68811..efe3adf 100644
--- a/vcl/source/window/layout.cxx
+++ b/vcl/source/window/layout.cxx
@@ -1942,7 +1942,7 @@ void MessageDialog::create_owned_areas()
     m_pOwnedContentArea = new VclVBox(this, false, 24);
     set_content_area(m_pOwnedContentArea);
     m_pOwnedContentArea->Show();
-    m_pOwnedActionArea = new VclHButtonBox(m_pOwnedContentArea);
+    m_pOwnedActionArea = new VclHButtonBox(m_pOwnedContentArea.get());
     set_action_area(m_pOwnedActionArea);
     m_pOwnedActionArea->Show();
 }
@@ -1995,7 +1995,7 @@ MessageDialog::MessageDialog(vcl::Window* pParent, const OString& rID, const OUS
 void MessageDialog::dispose()
 {
     for (size_t i = 0; i < m_aOwnedButtons.size(); ++i)
-        delete m_aOwnedButtons[i];
+        m_aOwnedButtons[i].disposeAndClear();
     m_aOwnedButtons.clear();
 
     delete m_pSecondaryMessage;
@@ -2007,14 +2007,9 @@ void MessageDialog::dispose()
     delete m_pImage;
     m_pImage = NULL;
 
-    delete m_pGrid;
-    m_pGrid = NULL;
-
-    delete m_pOwnedActionArea;
-    m_pOwnedActionArea = NULL;
-
-    delete m_pOwnedContentArea;
-    m_pOwnedContentArea = NULL;
+    m_pGrid.disposeAndClear();
+    m_pOwnedActionArea.disposeAndClear();
+    m_pOwnedContentArea.disposeAndClear();
 
     Dialog::dispose();
 }
@@ -2105,7 +2100,7 @@ short MessageDialog::Execute()
 {
     setDeferredProperties();
 
-    if (!m_pGrid)
+    if (!m_pGrid.get())
     {
         VclContainer *pContainer = get_content_area();
         assert(pContainer);
@@ -2115,7 +2110,7 @@ short MessageDialog::Execute()
         m_pGrid->set_column_spacing(12);
         m_pGrid->set_row_spacing(GetTextHeight());
 
-        m_pImage = new FixedImage(m_pGrid, WB_CENTER | WB_VCENTER | WB_3DLOOK);
+        m_pImage = new FixedImage(m_pGrid.get(), WB_CENTER | WB_VCENTER | WB_3DLOOK);
         switch (m_eMessageType)
         {
             case VCL_MESSAGE_INFO:
@@ -2140,7 +2135,7 @@ short MessageDialog::Execute()
 
         bool bHasSecondaryText = !m_sSecondaryString.isEmpty();
 
-        m_pPrimaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
+        m_pPrimaryMessage = new VclMultiLineEdit(m_pGrid.get(), nWinStyle);
         m_pPrimaryMessage->SetPaintTransparent(true);
         m_pPrimaryMessage->EnableCursor(false);
 
@@ -2150,7 +2145,7 @@ short MessageDialog::Execute()
         m_pPrimaryMessage->SetText(m_sPrimaryString);
         m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
 
-        m_pSecondaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
+        m_pSecondaryMessage = new VclMultiLineEdit(m_pGrid.get(), nWinStyle);
         m_pSecondaryMessage->SetPaintTransparent(true);
         m_pSecondaryMessage->EnableCursor(false);
         m_pSecondaryMessage->set_grid_left_attach(1);
@@ -2164,56 +2159,56 @@ short MessageDialog::Execute()
         VclButtonBox *pButtonBox = get_action_area();
         assert(pButtonBox);
 
-        PushButton *pBtn;
+        PushButtonPtr pBtn;
         switch (m_eButtonsType)
         {
             case VCL_BUTTONS_NONE:
                 break;
             case VCL_BUTTONS_OK:
-                pBtn = new OKButton(pButtonBox);
+                pBtn = PushButtonPtr(new OKButton(pButtonBox));
                 pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
                 pBtn->Show();
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_OK;
+                m_aResponses[pBtn.get()] = RET_OK;
                 break;
             case VCL_BUTTONS_CLOSE:
-                pBtn = new CloseButton(pButtonBox);
+                pBtn = PushButtonPtr(new CloseButton(pButtonBox));
                 pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
                 pBtn->Show();
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_CLOSE;
+                m_aResponses[pBtn.get()] = RET_CLOSE;
                 break;
             case VCL_BUTTONS_CANCEL:
-                pBtn = new CancelButton(pButtonBox);
+                pBtn = PushButtonPtr(new CancelButton(pButtonBox));
                 pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_CANCEL;
+                m_aResponses[pBtn.get()] = RET_CANCEL;
                 break;
             case VCL_BUTTONS_YES_NO:
-                pBtn = new PushButton(pButtonBox);
+                pBtn = PushButtonPtr(new PushButton(pButtonBox));
                 pBtn->SetText(Button::GetStandardText(BUTTON_YES));
                 pBtn->Show();
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_YES;
+                m_aResponses[pBtn.get()] = RET_YES;
 
-                pBtn = new PushButton(pButtonBox);
+                pBtn = PushButtonPtr(new PushButton(pButtonBox));
                 pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
                 pBtn->SetText(Button::GetStandardText(BUTTON_NO));
                 pBtn->Show();
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_NO;
+                m_aResponses[pBtn.get()] = RET_NO;
                 break;
             case VCL_BUTTONS_OK_CANCEL:
-                pBtn = new OKButton(pButtonBox);
+                pBtn = PushButtonPtr(new OKButton(pButtonBox));
                 pBtn->Show();
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_OK;
+                m_aResponses[pBtn.get()] = RET_OK;
 
-                pBtn = new CancelButton(pButtonBox);
+                pBtn = PushButtonPtr(new CancelButton(pButtonBox));
                 pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
                 pBtn->Show();
                 m_aOwnedButtons.push_back(pBtn);
-                m_aResponses[pBtn] = RET_CANCEL;
+                m_aResponses[pBtn.get()] = RET_CANCEL;
                 break;
         }
         setButtonHandlers(pButtonBox);
commit a21739aae82976a720e25d71a513e20d6d13e2e4
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Dec 31 13:30:00 2014 +0000

    vcl: double dispose protection & unit test.
    
    Widgets must be able to tolerate multiple 'dispose' calls.
    
    Change-Id: I76069a10b83b8384ad84dd146766054cab5bd222

diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index dfd3d09..b13d0ad 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -348,6 +348,8 @@ class VclBuilder;
 class ImplDockingWindowWrapper;
 class ImplPopupFloatWin;
 class MenuFloatingWindow;
+class LifecycleTest;
+
 namespace svt { class PopupWindowControllerImpl; }
 
 struct WindowResHeader
@@ -377,6 +379,7 @@ class VCL_DLLPUBLIC Window : public ::OutputDevice, public Resource
     friend class ::ImplBorderWindow;
     friend class ::VclBuilder;
     friend class ::PaintHelper;
+    friend class ::LifecycleTest;
 
     // TODO: improve missing functionality
     // only required because of SetFloatingMode()
diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx
index d635dd6..1c887b9 100644
--- a/vcl/qa/cppunit/lifecycle.cxx
+++ b/vcl/qa/cppunit/lifecycle.cxx
@@ -20,15 +20,30 @@ class LifecycleTest : public test::BootstrapFixture
 public:
     LifecycleTest() : BootstrapFixture(true, false) {}
 
+    void testMultiDispose();
     void testIsolatedWidgets();
     void testParentedWidgets();
 
     CPPUNIT_TEST_SUITE(LifecycleTest);
+    CPPUNIT_TEST(testMultiDispose);
     CPPUNIT_TEST(testIsolatedWidgets);
     CPPUNIT_TEST(testParentedWidgets);
     CPPUNIT_TEST_SUITE_END();
 };
 
+void LifecycleTest::testMultiDispose()
+{
+    VclReference<WorkWindow> xWin(new WorkWindow((vcl::Window *)NULL,
+                                                 WB_APP|WB_STDWORK));
+    CPPUNIT_ASSERT(xWin.get() != NULL);
+    xWin->dispose();
+    xWin->dispose();
+    xWin->dispose();
+    CPPUNIT_ASSERT(xWin->GetWindow(0) == NULL);
+    CPPUNIT_ASSERT(xWin->GetChild(0) == NULL);
+    CPPUNIT_ASSERT(xWin->GetChildCount() == 0);
+}
+
 void LifecycleTest::testWidgets(vcl::Window *pParent)
 {
     { PushButtonPtr   aPtr(new PushButton(pParent));   }
diff --git a/vcl/source/window/stacking.cxx b/vcl/source/window/stacking.cxx
index ad533cf..ef112af 100644
--- a/vcl/source/window/stacking.cxx
+++ b/vcl/source/window/stacking.cxx
@@ -1023,6 +1023,8 @@ void Window::SetParent( vcl::Window* pNewParent )
 
 sal_uInt16 Window::GetChildCount() const
 {
+    if (!mpWindowImpl)
+        return 0;
 
     sal_uInt16  nChildCount = 0;
     vcl::Window* pChild = mpWindowImpl->mpFirstChild;
@@ -1037,6 +1039,8 @@ sal_uInt16 Window::GetChildCount() const
 
 vcl::Window* Window::GetChild( sal_uInt16 nChild ) const
 {
+    if (!mpWindowImpl)
+        return NULL;
 
     sal_uInt16  nChildCount = 0;
     vcl::Window* pChild = mpWindowImpl->mpFirstChild;
@@ -1053,6 +1057,8 @@ vcl::Window* Window::GetChild( sal_uInt16 nChild ) const
 
 vcl::Window* Window::GetWindow( sal_uInt16 nType ) const
 {
+    if (!mpWindowImpl)
+        return 0;
 
     switch ( nType )
     {
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 4cd587b..df1440e 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -133,6 +133,9 @@ namespace
 
 void Window::dispose()
 {
+    if (!mpWindowImpl)
+        return;
+
     // remove Key and Mouse events issued by Application::PostKey/MouseEvent
     Application::RemoveMouseAndKeyEvents( this );
 


More information about the Libreoffice-commits mailing list