include/vcl/vclref.hxx | 61 +++++++++++++++++++++++++++++++++++++++++++ vcl/qa/cppunit/lifecycle.cxx | 14 ++++++--- vcl/source/window/layout.cxx | 14 ++++----- 3 files changed, 77 insertions(+), 12 deletions(-)
New commits: commit 39354e856a1135aa83e92072c86e4344ac30eef4 Author: Noel Grandin <[email protected]> Date: Mon Jan 5 14:01:17 2015 +0200 vcl: implement upcasting of VclReference types to make code less verbose Change-Id: I0e28bfc412d50e798e6c215434cffc2183b104a6 diff --git a/include/vcl/vclref.hxx b/include/vcl/vclref.hxx index ba3fdaa..b8c15ea 100644 --- a/include/vcl/vclref.hxx +++ b/include/vcl/vclref.hxx @@ -22,6 +22,52 @@ #include <rtl/ref.hxx> +/// @cond INTERNAL +namespace vcl { namespace detail { + +// A mechanism to enable up-casts, used by the VclReference conversion constructor, +// heavily borrowed from boost::is_base_and_derived +// (which manages to avoid compilation problems with ambiguous bases and cites +// comp.lang.c++.moderated mail <http://groups.google.com/groups? +// selm=df893da6.0301280859.522081f7%40posting.google.com> "SuperSubclass +// (is_base_and_derived) complete implementation!" by Rani Sharoni and cites +// Aleksey Gurtovoy for the workaround for MSVC), to avoid including Boost +// headers in URE headers (could ultimately be based on C++11 std::is_base_of): + +template< typename T1, typename T2 > struct UpCast { +private: + template< bool, typename U1, typename > struct C + { typedef U1 t; }; + + template< typename U1, typename U2 > struct C< false, U1, U2 > + { typedef U2 t; }; + + struct S { char c[2]; }; + +#if defined _MSC_VER + static char f(T2 *, long); + static S f(T1 * const &, int); +#else + template< typename U > static char f(T2 *, U); + static S f(T1 *, int); +#endif + + struct H { + H(); // avoid C2514 "class has no constructors" from MSVC 2008 +#if defined _MSC_VER + operator T1 * const & () const; +#else + operator T1 * () const; +#endif + operator T2 * (); + }; + +public: + typedef typename C< sizeof (f(H(), 0)) == 1, void *, void >::t t; +}; + +}; }; // namespace detail, namespace vcl + /** * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses. * @param reference_type must be a subclass of vcl::Window @@ -53,6 +99,21 @@ public: : m_rInnerRef (handle.m_rInnerRef) {} + /** Up-casting conversion constructor: Copies interface reference. + + Does not work for up-casts to ambiguous bases. For the special case of + up-casting to Reference< XInterface >, see the corresponding conversion + operator. + + @param rRef another reference + */ + template< class derived_type > + inline VclReference( + const VclReference< derived_type > & rRef, + typename ::vcl::detail::UpCast< reference_type, derived_type >::t = 0 ) + : m_rInnerRef( static_cast<reference_type*>(rRef.get()) ) + { + } /** Get the body. Can be used instead of operator->(). I.e. handle->someBodyOp() and handle.get()->someBodyOp() diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx index e054672..a2d75df 100644 --- a/vcl/qa/cppunit/lifecycle.cxx +++ b/vcl/qa/cppunit/lifecycle.cxx @@ -29,6 +29,7 @@ public: void testParentedWidgets(); CPPUNIT_TEST_SUITE(LifecycleTest); + CPPUNIT_TEST(testCast); CPPUNIT_TEST(testMultiDispose); CPPUNIT_TEST(testIsolatedWidgets); CPPUNIT_TEST(testParentedWidgets); @@ -38,12 +39,15 @@ public: // A compile time sanity check void LifecycleTest::testCast() { -// VclReference<PushButton> xButton(new PushButton(NULL, 0)); -// VclReference<vcl::Window> xWindow(xButton); + 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); + VclReference<MetricField> xField(new MetricField(NULL, 0)); + VclReference<SpinField> xSpin(xField); + VclReference<Edit> xEdit(xField); + +// the following line should NOT compile +// VclReference<PushButton> xButton2(xWindow); } void LifecycleTest::testMultiDispose() diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index efe3adf..30c616c3 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -2165,33 +2165,33 @@ short MessageDialog::Execute() case VCL_BUTTONS_NONE: break; case VCL_BUTTONS_OK: - pBtn = PushButtonPtr(new OKButton(pButtonBox)); + pBtn = new OKButton(pButtonBox); pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON); pBtn->Show(); m_aOwnedButtons.push_back(pBtn); m_aResponses[pBtn.get()] = RET_OK; break; case VCL_BUTTONS_CLOSE: - pBtn = PushButtonPtr(new CloseButton(pButtonBox)); + pBtn = new CloseButton(pButtonBox); pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON); pBtn->Show(); m_aOwnedButtons.push_back(pBtn); m_aResponses[pBtn.get()] = RET_CLOSE; break; case VCL_BUTTONS_CANCEL: - pBtn = PushButtonPtr(new CancelButton(pButtonBox)); + pBtn = new CancelButton(pButtonBox); pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON); m_aOwnedButtons.push_back(pBtn); m_aResponses[pBtn.get()] = RET_CANCEL; break; case VCL_BUTTONS_YES_NO: - pBtn = PushButtonPtr(new PushButton(pButtonBox)); + pBtn = new PushButton(pButtonBox); pBtn->SetText(Button::GetStandardText(BUTTON_YES)); pBtn->Show(); m_aOwnedButtons.push_back(pBtn); m_aResponses[pBtn.get()] = RET_YES; - pBtn = PushButtonPtr(new PushButton(pButtonBox)); + pBtn = new PushButton(pButtonBox); pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON); pBtn->SetText(Button::GetStandardText(BUTTON_NO)); pBtn->Show(); @@ -2199,12 +2199,12 @@ short MessageDialog::Execute() m_aResponses[pBtn.get()] = RET_NO; break; case VCL_BUTTONS_OK_CANCEL: - pBtn = PushButtonPtr(new OKButton(pButtonBox)); + pBtn = new OKButton(pButtonBox); pBtn->Show(); m_aOwnedButtons.push_back(pBtn); m_aResponses[pBtn.get()] = RET_OK; - pBtn = PushButtonPtr(new CancelButton(pButtonBox)); + pBtn = new CancelButton(pButtonBox); pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON); pBtn->Show(); m_aOwnedButtons.push_back(pBtn); _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
