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 #ifndef __FRAMEWORK_DISPATCH_CLOSEDISPATCHER_HXX_
29 #define __FRAMEWORK_DISPATCH_CLOSEDISPATCHER_HXX_
30 
31 //_______________________________________________
32 // my own includes
33 
34 #include <threadhelp/threadhelpbase.hxx>
35 #include <macros/xinterface.hxx>
36 #include <macros/xtypeprovider.hxx>
37 #include <macros/debug.hxx>
38 #include <macros/generic.hxx>
39 #include <stdtypes.h>
40 #include <general.h>
41 
42 //_______________________________________________
43 // interface includes
44 #include <com/sun/star/lang/XTypeProvider.hpp>
45 #include <com/sun/star/frame/XFrame.hpp>
46 #include <com/sun/star/frame/XStatusListener.hpp>
47 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
48 #include <com/sun/star/frame/XDispatchInformationProvider.hpp>
49 #include <com/sun/star/util/URL.hpp>
50 #include <com/sun/star/frame/XDispatchResultListener.hpp>
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #include <com/sun/star/frame/DispatchResultState.hpp>
53 
54 //_______________________________________________
55 // other includes
56 #include <cppuhelper/weak.hxx>
57 #include <vcl/evntpost.hxx>
58 
59 //_______________________________________________
60 // namespace
61 
62 namespace framework{
63 
64 //-----------------------------------------------
65 /**
66     @short          helper to dispatch the URLs ".uno:CloseDoc"/".uno:CloseWin"/".uno:CloseFrame"
67                     to close a frame/document or the whole application implicitly in case it was the last frame
68 
69     @descr          These URLs implements a special functionality to close a document or the whole frame ...
70                     and handle the state, it was the last frame or document. Then we create the
71                     default backing document which can be used to open new ones using the file open dialog
72                     or some other menu entries. Or we terminate the whole application in case this backing mode shouldnt
73                     be used.
74  */
75 class CloseDispatcher : public css::lang::XTypeProvider
76                       , public css::frame::XNotifyingDispatch             // => XDispatch
77                       , public css::frame::XDispatchInformationProvider
78                         // baseclasses ... order is neccessary for right initialization!
79                       , private ThreadHelpBase
80                       , public  ::cppu::OWeakObject
81 {
82     //-------------------------------------------
83     // types
84 
85     private:
86 
87         //---------------------------------------
88         /** @short  describe, which request must be done here.
89         @descr      The incoming URLs {.uno:CloseDoc/CloseWin and CloseFrame
90                     can be classified so and checked later performant.}*/
91         enum EOperation
92         {
93             E_CLOSE_DOC,
94             E_CLOSE_FRAME,
95             E_CLOSE_WIN
96         };
97 
98     //-------------------------------------------
99     // member
100 
101     private:
102 
103         //---------------------------------------
104         /** @short reference to an uno service manager,
105                    which can be used to create own needed
106                    uno resources. */
107         css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;
108 
109         //---------------------------------------
110         /** @short  reference to the target frame, which should be
111                     closed by this dispatch. */
112         css::uno::WeakReference< css::frame::XFrame > m_xCloseFrame;
113 
114         //---------------------------------------
115         /** @short  used for asynchronous callbacks within the main thread.
116             @descr  Internaly we work asynchronous. Because our callis
117                     are not aware, that her request can kill its own environment ... */
118         ::vcl::EventPoster m_aAsyncCallback;
119 
120         //---------------------------------------
121         /** @short  used inside asyncronous callback to decide,
122                     which operation must be executed. */
123         EOperation m_eOperation;
124 
125         //---------------------------------------
126         /** @short  for asynchronous operations we must hold us self alive! */
127         css::uno::Reference< css::uno::XInterface > m_xSelfHold;
128 
129         //---------------------------------------
130         /** @short  list of registered status listener */
131         ListenerHash m_lStatusListener;
132 
133         //---------------------------------------
134         /** @short  holded alive for internaly asynchronous operations! */
135         css::uno::Reference< css::frame::XDispatchResultListener > m_xResultListener;
136 
137     //-------------------------------------------
138     // native interface
139 
140 	public:
141 
142         //---------------------------------------
143         /** @short  connect a new CloseDispatcher instance to its frame.
144             @descr  One CloseDispatcher instance is bound to onw frame only.
145                     That makes an implementation (e.g. of listener support)
146                     much more easier .-)
147 
148             @param  xSMGR
149                     an un oservice manager, which is needed to create uno resource
150                     internaly.
151 
152             @param  xFrame
153                     the frame where the corresponding dispatch was started.
154 
155             @param  sTarget
156                     help us to find the right target for this close operation.
157          */
158         CloseDispatcher(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR  ,
159                         const css::uno::Reference< css::frame::XFrame >&              xFrame ,
160                         const ::rtl::OUString&                                        sTarget);
161 
162         //---------------------------------------
163         /** @short  does nothing real. */
164         virtual ~CloseDispatcher();
165 
166     //-------------------------------------------
167     // uno interface
168 
169     public:
170 
171         //---------------------------------------
172         FWK_DECLARE_XINTERFACE
173         FWK_DECLARE_XTYPEPROVIDER
174 
175         //---------------------------------------
176         // XNotifyingDispatch
177         virtual void SAL_CALL dispatchWithNotification( const css::util::URL&                                             aURL      ,
178                                                         const css::uno::Sequence< css::beans::PropertyValue >&            lArguments,
179                                                         const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw(css::uno::RuntimeException);
180 
181         //---------------------------------------
182         // XDispatch
183         virtual void SAL_CALL dispatch            ( const css::util::URL&                                     aURL      ,
184                                                     const css::uno::Sequence< css::beans::PropertyValue >&    lArguments) throw(css::uno::RuntimeException);
185         virtual void SAL_CALL addStatusListener   ( const css::uno::Reference< css::frame::XStatusListener >& xListener ,
186                                                     const css::util::URL&                                     aURL      ) throw(css::uno::RuntimeException);
187         virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener ,
188                                                     const css::util::URL&                                     aURL      ) throw(css::uno::RuntimeException);
189 
190         //---------------------------------------
191         // XDispatchInformationProvider
192         virtual css::uno::Sequence< sal_Int16 >                       SAL_CALL getSupportedCommandGroups         (                         ) throw (css::uno::RuntimeException);
193         virtual css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL getConfigurableDispatchInformation( sal_Int16 nCommandGroup ) throw (css::uno::RuntimeException);
194 
195     //-------------------------------------------
196     // internal helper
197 
198     private:
199 
200         //---------------------------------------
201         /** @short  a callback for asynchronous started operations.
202 
203             @descr  As already mentione, we make internaly all operations
204                     asynchronous. Otherwhise our callis kill its own environment
205                     during they call us ...
206         */
207         DECL_LINK( impl_asyncCallback, void* );
208 
209         //---------------------------------------
210         /** @short  prepare m_xCloseFrame so it should be closeable without problems.
211 
212             @descr  Thats needed to be shure, that the document cant disagree
213                     later with e.g. an office termination.
214                     The problem: Closing of documents can show UI. If the user
215                     ignores it and open/close other documents, we cant know
216                     which state the office has after closing of this frame.
217 
218             @param  bAllowSuspend
219                     force calling of XController->suspend().
220 
221             @param  bCloseAllOtherViewsToo
222                     if there are other top level frames, which
223                     contains views to the same document then our m_xCloseFrame,
224                     they are forced to be closed too.
225                     We need it to implement the CLOSE_DOC semantic.
226 
227             @return [boolean]
228                     sal_True if closing was successfully.
229          */
230         sal_Bool implts_prepareFrameForClosing(const css::uno::Reference< css::frame::XFrame >& xFrame                ,
231                                                      sal_Bool                                   bAllowSuspend         ,
232                                                      sal_Bool                                   bCloseAllOtherViewsToo,
233                                                      sal_Bool&                                  bControllerSuspended  );
234 
235         //---------------------------------------
236         /** @short  close the member m_xCloseFrame.
237 
238             @descr  This method does not look for any document
239                     inside this frame. Such views must be cleared
240                     before (e.g. by calling implts_closeView()!
241 
242                     Otherwhise e.g. the XController->suspend()
243                     call isnt made and no UI warn the user about
244                     loosing document changes. Because the
245                     frame is closed ....
246 
247             @return [bool]
248                     sal_True if closing was successfully.
249          */
250         sal_Bool implts_closeFrame();
251 
252         //---------------------------------------
253         /** @short  set the special BackingComponent (now StartModule)
254                     as new component of our m_xCloseFrame.
255 
256             @return [bool]
257                     sal_True if operation was successfully.
258          */
259         sal_Bool implts_establishBackingMode();
260 
261         //---------------------------------------
262         /** @short  calls XDesktop->terminate().
263 
264             @descr  No office code has to be called
265                     afterwards! Because the process is dieing ...
266                     The only exception is a might be registered
267                     listener at this instance here.
268                     Because he should know, that such things will happen :-)
269 
270             @return [bool]
271                     sal_True if termination of the application was started ...
272          */
273         sal_Bool implts_terminateApplication();
274 
275         //---------------------------------------
276         /** @short  notify a DispatchResultListener.
277 
278             @descr  We check the listener reference before we use it.
279                     So this method can be called everytimes!
280 
281             @parama xListener
282                     the listener, which should be notified.
283                     Can be null!
284 
285             @param  nState
286                     directly used as css::frame::DispatchResultState value.
287 
288             @param  aResult
289                     not used yet realy ...
290          */
291         void implts_notifyResultListener(const css::uno::Reference< css::frame::XDispatchResultListener >& xListener,
292                                                sal_Int16                                                   nState   ,
293                                          const css::uno::Any&                                              aResult  );
294 
295         //---------------------------------------
296         /** @short  try to find the right target frame where this close request
297                     must be realy done.
298 
299             @descr  The problem behind: closing some resources depends sometimes from the
300                     context where its dispatched. Sometimes the start frame of the dispatch
301                     has to be closed itself (target=_self) ... sometimes it's parent frame
302                     has to be closed - BUT(!) it means a parent frame containing a top level
303                     window. _top cant be used then for dispatch - because it adress TopFrames
304                     not frames containg top level windows. So normaly _magic (which btw does not
305                     exists at the moment .-) ) should be used. So we interpret target=<empty>
306                     as _magic !
307 
308             @param  xFrame
309                     start point for search of right dispatch frame.
310 
311             @param  sTarget
312                     give us an idea how this target frame must be searched.
313         */
314 
315         static css::uno::Reference< css::frame::XFrame > static_impl_searchRightTargetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame ,
316                                                                                             const ::rtl::OUString&                           sTarget);
317 
318 }; // class CloseDispatcher
319 
320 } // namespace framework
321 
322 #endif // #ifndef __FRAMEWORK_DISPATCH_CLOSEDISPATCHER_HXX_
323