xref: /trunk/main/svtools/source/hatchwindow/documentcloser.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 #include <com/sun/star/util/XCloseBroadcaster.hpp>
31 #include <com/sun/star/util/XCloseable.hpp>
32 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 #include <com/sun/star/frame/DoubleInitializationException.hpp>
35 #include <com/sun/star/frame/DoubleInitializationException.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/awt/XVclWindowPeer.hpp>
38 
39 #include <vos/mutex.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/dialog.hxx>
42 #include <tools/link.hxx>
43 #include <toolkit/helper/vclunohelper.hxx>
44 
45 #include "documentcloser.hxx"
46 
47 using namespace ::com::sun::star;
48 
49 
50 // ====================================================================
51 // MainThreadFrameCloserRequest
52 // ====================================================================
53 
54 class MainThreadFrameCloserRequest
55 {
56     uno::Reference< frame::XFrame > m_xFrame;
57 
58     public:
59         MainThreadFrameCloserRequest( const uno::Reference< frame::XFrame >& xFrame )
60         : m_xFrame( xFrame )
61         {}
62 
63         DECL_STATIC_LINK( MainThreadFrameCloserRequest, worker, MainThreadFrameCloserRequest* );
64 
65         static void Start( MainThreadFrameCloserRequest* pRequest );
66 };
67 
68 // --------------------------------------------------------
69 void MainThreadFrameCloserRequest::Start( MainThreadFrameCloserRequest* pMTRequest )
70 {
71     if ( pMTRequest )
72     {
73         if ( Application::GetMainThreadIdentifier() == osl_getThreadIdentifier( NULL ) )
74         {
75             // this is the main thread
76             worker( NULL, pMTRequest );
77         }
78         else
79             Application::PostUserEvent( STATIC_LINK( NULL, MainThreadFrameCloserRequest, worker ), pMTRequest );
80     }
81 }
82 
83 // --------------------------------------------------------
84 IMPL_STATIC_LINK( MainThreadFrameCloserRequest, worker, MainThreadFrameCloserRequest*, pMTRequest )
85 {
86     (void) pThis; // unused
87     if ( pMTRequest )
88     {
89         if ( pMTRequest->m_xFrame.is() )
90         {
91             // this is the main thread, the solar mutex must be locked
92             ::vos::OGuard aGuard( Application::GetSolarMutex() );
93 
94             try
95             {
96                 uno::Reference< awt::XWindow > xWindow = pMTRequest->m_xFrame->getContainerWindow();
97                 uno::Reference< awt::XVclWindowPeer > xWinPeer( xWindow, uno::UNO_QUERY_THROW );
98 
99                 xWindow->setVisible( sal_False );
100 
101                 // reparent the window
102                 xWinPeer->setProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PluginParent" ) ),
103                                         uno::makeAny( (sal_Int64) 0 ) );
104 
105                 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
106                 if ( pWindow )
107                     Dialog::EndAllDialogs( pWindow );
108             }
109             catch( uno::Exception& )
110             {
111                 // ignore all the errors
112             }
113 
114             try
115             {
116                 uno::Reference< util::XCloseable > xCloseable( pMTRequest->m_xFrame, uno::UNO_QUERY_THROW );
117                 xCloseable->close( sal_True );
118             }
119             catch( uno::Exception& )
120             {
121                 // ignore all the errors
122             }
123         }
124 
125         delete pMTRequest;
126     }
127 
128     return 0;
129 }
130 
131 
132 // ====================================================================
133 // ODocumentCloser
134 // ====================================================================
135 
136 // --------------------------------------------------------
137 ODocumentCloser::ODocumentCloser( const uno::Reference< uno::XComponentContext >& xContext )
138 : m_xContext( xContext )
139 , m_pListenersContainer( NULL )
140 , m_bDisposed( sal_False )
141 , m_bInitialized( sal_False )
142 {
143 }
144 
145 // --------------------------------------------------------
146 ODocumentCloser::~ODocumentCloser()
147 {
148     if ( m_pListenersContainer )
149     {
150         delete m_pListenersContainer;
151         m_pListenersContainer = NULL;
152     }
153 }
154 
155 // XComponent
156 // --------------------------------------------------------
157 void SAL_CALL ODocumentCloser::dispose()
158     throw (uno::RuntimeException)
159 {
160     ::osl::MutexGuard aGuard( m_aMutex );
161 
162     if ( m_bDisposed )
163         throw lang::DisposedException();
164 
165     lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
166     if ( m_pListenersContainer )
167         m_pListenersContainer->disposeAndClear( aSource );
168 
169     // TODO: trigger a main thread execution to close the frame
170     if ( m_xFrame.is() )
171     {
172         // the created object will be deleted after thread execution
173         MainThreadFrameCloserRequest* pCloser = new MainThreadFrameCloserRequest( m_xFrame );
174         MainThreadFrameCloserRequest::Start( pCloser );
175     }
176 
177     m_bDisposed = sal_True;
178 }
179 
180 // --------------------------------------------------------
181 void SAL_CALL ODocumentCloser::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
182     throw (uno::RuntimeException)
183 {
184     ::osl::MutexGuard aGuard( m_aMutex );
185     if ( m_bDisposed )
186         throw lang::DisposedException(); // TODO
187 
188     if ( !m_pListenersContainer )
189         m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
190 
191     m_pListenersContainer->addInterface( xListener );
192 }
193 
194 // --------------------------------------------------------
195 void SAL_CALL ODocumentCloser::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
196     throw (uno::RuntimeException)
197 {
198     ::osl::MutexGuard aGuard( m_aMutex );
199     if ( m_pListenersContainer )
200         m_pListenersContainer->removeInterface( xListener );
201 }
202 
203 // XInitialization
204 // --------------------------------------------------------
205 void SAL_CALL ODocumentCloser::initialize( const uno::Sequence< uno::Any >& aArguments )
206     throw (uno::Exception, uno::RuntimeException)
207 {
208     ::osl::MutexGuard aGuard( m_aMutex );
209     if ( m_bInitialized )
210         throw frame::DoubleInitializationException();
211 
212     if ( m_bDisposed )
213         throw lang::DisposedException(); // TODO
214 
215     if ( !m_refCount )
216         throw uno::RuntimeException(); // the object must be refcounted already!
217 
218     sal_Int32 nLen = aArguments.getLength();
219     if ( nLen != 1 )
220         throw lang::IllegalArgumentException(
221                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ),
222                         uno::Reference< uno::XInterface >(),
223                         0 );
224 
225     if ( !( aArguments[0] >>= m_xFrame ) || !m_xFrame.is() )
226         throw lang::IllegalArgumentException(
227                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ),
228                 uno::Reference< uno::XInterface >(),
229                 0 );
230 
231     m_bInitialized = sal_True;
232 }
233 
234 
235 // XServiceInfo
236 // --------------------------------------------------------
237 ::rtl::OUString SAL_CALL ODocumentCloser::getImplementationName(  )
238     throw (uno::RuntimeException)
239 {
240     return impl_staticGetImplementationName();
241 }
242 
243 // --------------------------------------------------------
244 ::sal_Bool SAL_CALL ODocumentCloser::supportsService( const ::rtl::OUString& ServiceName )
245     throw (uno::RuntimeException)
246 {
247     uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
248 
249     for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
250         if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
251             return sal_True;
252 
253     return sal_False;
254 }
255 
256 // --------------------------------------------------------
257 uno::Sequence< ::rtl::OUString > SAL_CALL ODocumentCloser::getSupportedServiceNames()
258     throw (uno::RuntimeException)
259 {
260     return impl_staticGetSupportedServiceNames();
261 }
262 
263 // Static methods
264 // --------------------------------------------------------
265 uno::Sequence< ::rtl::OUString > SAL_CALL ODocumentCloser::impl_staticGetSupportedServiceNames()
266 {
267     const rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.DocumentCloser" ) );
268     return uno::Sequence< rtl::OUString >( &aServiceName, 1 );
269 }
270 
271 // --------------------------------------------------------
272 ::rtl::OUString SAL_CALL ODocumentCloser::impl_staticGetImplementationName()
273 {
274     return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.DocumentCloser" ) );
275 }
276 
277 // --------------------------------------------------------
278 uno::Reference< uno::XInterface > SAL_CALL ODocumentCloser::impl_staticCreateSelfInstance(
279                                 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
280 {
281     uno::Reference< uno::XComponentContext > xContext;
282     uno::Reference< beans::XPropertySet > xPropSet( xServiceManager, uno::UNO_QUERY );
283     if ( xPropSet.is() )
284         xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) >>= xContext;
285 
286     if ( !xContext.is() )
287     {
288         throw uno::RuntimeException(
289             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unable to obtain component context from service manager!" ) ),
290             uno::Reference< uno::XInterface >() );
291     }
292 
293     return static_cast< cppu::OWeakObject * >( new ODocumentCloser( xContext ) );
294 }
295 
296