Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include <tools/debug.hxx>
22 : : #include <svl/eitem.hxx>
23 : : #include <svl/stritem.hxx>
24 : : #include <svl/intitem.hxx>
25 : : #include <svl/itemset.hxx>
26 : : #include <svl/visitem.hxx>
27 : : #include <svtools/javacontext.hxx>
28 : : #include <svl/itempool.hxx>
29 : : #include <tools/urlobj.hxx>
30 : : #include <com/sun/star/util/URLTransformer.hpp>
31 : : #include <com/sun/star/util/XURLTransformer.hpp>
32 : : #include <com/sun/star/frame/XController.hpp>
33 : : #include <com/sun/star/frame/XFrameActionListener.hpp>
34 : : #include <com/sun/star/frame/XComponentLoader.hpp>
35 : : #include <com/sun/star/frame/XFrame.hpp>
36 : : #include <com/sun/star/frame/FrameActionEvent.hpp>
37 : : #include <com/sun/star/frame/FrameAction.hpp>
38 : : #include <com/sun/star/frame/status/ItemStatus.hpp>
39 : : #include <com/sun/star/frame/status/ItemState.hpp>
40 : : #include <com/sun/star/frame/DispatchResultState.hpp>
41 : : #include <com/sun/star/frame/status/Visibility.hpp>
42 : : #include <comphelper/processfactory.hxx>
43 : : #include <comphelper/sequence.hxx>
44 : : #include <osl/mutex.hxx>
45 : : #include <uno/current_context.hxx>
46 : : #include <vcl/svapp.hxx>
47 : :
48 : : #include <sfx2/app.hxx>
49 : : #include <sfx2/unoctitm.hxx>
50 : : #include <sfx2/viewfrm.hxx>
51 : : #include <sfx2/frame.hxx>
52 : : #include <sfx2/ctrlitem.hxx>
53 : : #include <sfx2/sfxuno.hxx>
54 : : #include <sfx2/bindings.hxx>
55 : : #include <sfx2/dispatch.hxx>
56 : : #include <sfx2/sfxsids.hrc>
57 : : #include <sfx2/request.hxx>
58 : : #include "statcach.hxx"
59 : : #include <sfx2/msgpool.hxx>
60 : : #include <sfx2/objsh.hxx>
61 : :
62 : : #include <boost/scoped_ptr.hpp>
63 : :
64 : : namespace css = ::com::sun::star;
65 : : using namespace ::com::sun::star::uno;
66 : : using namespace ::com::sun::star::util;
67 : :
68 : : enum URLTypeId
69 : : {
70 : : URLType_BOOL,
71 : : URLType_BYTE,
72 : : URLType_SHORT,
73 : : URLType_LONG,
74 : : URLType_HYPER,
75 : : URLType_STRING,
76 : : URLType_FLOAT,
77 : : URLType_DOUBLE,
78 : : URLType_COUNT
79 : : };
80 : :
81 : : const char* URLTypeNames[URLType_COUNT] =
82 : : {
83 : : "bool",
84 : : "byte",
85 : : "short",
86 : : "long",
87 : : "hyper",
88 : : "string",
89 : : "float",
90 : : "double"
91 : : };
92 : :
93 [ # # ][ # # ]: 0 : SFX_IMPL_XINTERFACE_2( SfxUnoControllerItem, OWeakObject, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
[ # # ]
94 [ # # ][ # # ]: 0 : SFX_IMPL_XTYPEPROVIDER_2( SfxUnoControllerItem, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
95 : :
96 : 0 : SfxUnoControllerItem::SfxUnoControllerItem( SfxControllerItem *pItem, SfxBindings& rBind, const String& rCmd )
97 : : : pCtrlItem( pItem )
98 : 0 : , pBindings( &rBind )
99 : : {
100 : : DBG_ASSERT( !pCtrlItem || !pCtrlItem->IsBound(), "ControllerItem is incorrect!" );
101 : :
102 [ # # ]: 0 : aCommand.Complete = rCmd;
103 [ # # ][ # # ]: 0 : Reference< XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
104 [ # # ][ # # ]: 0 : xTrans->parseStrict( aCommand );
105 [ # # ]: 0 : pBindings->RegisterUnoController_Impl( this );
106 : 0 : }
107 : :
108 [ # # ]: 0 : SfxUnoControllerItem::~SfxUnoControllerItem()
109 : : {
110 : : // tell bindings to forget this controller ( if still connected )
111 [ # # ]: 0 : if ( pBindings )
112 [ # # ]: 0 : pBindings->ReleaseUnoController_Impl( this );
113 [ # # ]: 0 : }
114 : :
115 : 0 : void SfxUnoControllerItem::UnBind()
116 : : {
117 : : // connection to SfxControllerItem is lost
118 : 0 : pCtrlItem = NULL;
119 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
120 [ # # ]: 0 : ReleaseDispatch();
121 : 0 : }
122 : :
123 : 0 : void SAL_CALL SfxUnoControllerItem::statusChanged(const ::com::sun::star::frame::FeatureStateEvent& rEvent) throw ( ::com::sun::star::uno::RuntimeException )
124 : : {
125 [ # # ]: 0 : SolarMutexGuard aGuard;
126 : : DBG_ASSERT( pCtrlItem, "dispatch implementation didn't respect our previous removeStatusListener call!" );
127 : :
128 [ # # ]: 0 : if ( rEvent.Requery )
129 : : {
130 : : // Error can only happen if the old Dispatch is implemented incorrectly
131 : : // i.e. removeStatusListener did not work. But such things can happen...
132 : : // So protect before ReleaseDispatch from release!
133 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
134 [ # # ]: 0 : ReleaseDispatch();
135 [ # # ]: 0 : if ( pCtrlItem )
136 [ # # ]: 0 : GetNewDispatch(); // asynchronous ??
137 : : }
138 [ # # ]: 0 : else if ( pCtrlItem )
139 : : {
140 : 0 : SfxItemState eState = SFX_ITEM_DISABLED;
141 : 0 : SfxPoolItem* pItem = NULL;
142 [ # # ]: 0 : if ( rEvent.IsEnabled )
143 : : {
144 : 0 : eState = SFX_ITEM_AVAILABLE;
145 : 0 : ::com::sun::star::uno::Type pType = rEvent.State.getValueType();
146 : :
147 [ # # ][ # # ]: 0 : if ( pType == ::getBooleanCppuType() )
148 : : {
149 : 0 : sal_Bool bTemp = false;
150 : 0 : rEvent.State >>= bTemp ;
151 [ # # ][ # # ]: 0 : pItem = new SfxBoolItem( pCtrlItem->GetId(), bTemp );
152 : : }
153 [ # # ][ # # ]: 0 : else if ( pType == ::getCppuType((const sal_uInt16*)0) )
154 : : {
155 : 0 : sal_uInt16 nTemp = 0;
156 : 0 : rEvent.State >>= nTemp ;
157 [ # # ][ # # ]: 0 : pItem = new SfxUInt16Item( pCtrlItem->GetId(), nTemp );
158 : : }
159 [ # # ][ # # ]: 0 : else if ( pType == ::getCppuType((const sal_uInt32*)0) )
160 : : {
161 : 0 : sal_uInt32 nTemp = 0;
162 : 0 : rEvent.State >>= nTemp ;
163 [ # # ][ # # ]: 0 : pItem = new SfxUInt32Item( pCtrlItem->GetId(), nTemp );
164 : : }
165 [ # # ][ # # ]: 0 : else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
166 : : {
167 : 0 : ::rtl::OUString sTemp ;
168 : 0 : rEvent.State >>= sTemp ;
169 [ # # ][ # # ]: 0 : pItem = new SfxStringItem( pCtrlItem->GetId(), sTemp );
[ # # ][ # # ]
170 : : }
171 : : else
172 [ # # ][ # # ]: 0 : pItem = new SfxVoidItem( pCtrlItem->GetId() );
173 : : }
174 : :
175 [ # # ]: 0 : pCtrlItem->StateChanged( pCtrlItem->GetId(), eState, pItem );
176 [ # # ][ # # ]: 0 : delete pItem;
177 [ # # ]: 0 : }
178 : 0 : }
179 : :
180 : 0 : void SAL_CALL SfxUnoControllerItem::disposing( const ::com::sun::star::lang::EventObject& ) throw ( ::com::sun::star::uno::RuntimeException )
181 : : {
182 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
183 [ # # ]: 0 : ReleaseDispatch();
184 : 0 : }
185 : :
186 : 0 : void SfxUnoControllerItem::ReleaseDispatch()
187 : : {
188 [ # # ]: 0 : if ( xDispatch.is() )
189 : : {
190 [ # # ]: 0 : xDispatch->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, aCommand );
191 [ # # ]: 0 : xDispatch = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
192 : : }
193 : 0 : }
194 : :
195 : 0 : void SfxUnoControllerItem::GetNewDispatch()
196 : : {
197 [ # # ]: 0 : if ( !pBindings )
198 : : {
199 : : // Bindings released
200 : : OSL_FAIL( "Tried to get dispatch, but no Bindings!" );
201 : 0 : return;
202 : : }
203 : :
204 : : // forget old dispatch
205 [ # # ]: 0 : xDispatch = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
206 : :
207 : : // no arms, no cookies !
208 [ # # ][ # # ]: 0 : if ( !pBindings->GetDispatcher_Impl() || !pBindings->GetDispatcher_Impl()->GetFrame() )
[ # # ]
209 : 0 : return;
210 : :
211 : 0 : SfxFrame& rFrame = pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame();
212 : 0 : SfxFrame *pParent = rFrame.GetParentFrame();
213 [ # # ]: 0 : if ( pParent )
214 : : // parent may intercept
215 [ # # ]: 0 : xDispatch = TryGetDispatch( pParent );
216 : :
217 [ # # ]: 0 : if ( !xDispatch.is() )
218 : : {
219 : : // no interception
220 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = rFrame.GetFrameInterface();
221 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY );
222 [ # # ]: 0 : if ( xProv.is() )
223 [ # # ][ # # ]: 0 : xDispatch = xProv->queryDispatch( aCommand, ::rtl::OUString(), 0 );
[ # # ]
224 : : }
225 : :
226 [ # # ]: 0 : if ( xDispatch.is() )
227 [ # # ]: 0 : xDispatch->addStatusListener( (::com::sun::star::frame::XStatusListener*) this, aCommand );
228 [ # # ]: 0 : else if ( pCtrlItem )
229 : 0 : pCtrlItem->StateChanged( pCtrlItem->GetId(), SFX_ITEM_DISABLED, NULL );
230 : : }
231 : :
232 : 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SfxUnoControllerItem::TryGetDispatch( SfxFrame *pFrame )
233 : : {
234 : 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
235 : 0 : SfxFrame *pParent = pFrame->GetParentFrame();
236 [ # # ]: 0 : if ( pParent )
237 : : // parent may intercept
238 [ # # ][ # # ]: 0 : xDisp = TryGetDispatch( pParent );
239 : :
240 : : // only components may intercept
241 [ # # ][ # # ]: 0 : if ( !xDisp.is() && pFrame->HasComponent() )
[ # # ][ # # ]
242 : : {
243 : : // no interception
244 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = pFrame->GetFrameInterface();
245 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY );
246 [ # # ]: 0 : if ( xProv.is() )
247 [ # # ][ # # ]: 0 : xDisp = xProv->queryDispatch( aCommand, ::rtl::OUString(), 0 );
[ # # ]
248 : : }
249 : :
250 : 0 : return xDisp;
251 : : }
252 : :
253 : 0 : void SfxUnoControllerItem::ReleaseBindings()
254 : : {
255 : : // connection to binding is lost; so forget the binding and the dispatch
256 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
257 [ # # ]: 0 : ReleaseDispatch();
258 [ # # ]: 0 : if ( pBindings )
259 [ # # ]: 0 : pBindings->ReleaseUnoController_Impl( this );
260 : 0 : pBindings = NULL;
261 : 0 : }
262 : :
263 : 158 : void SfxStatusDispatcher::ReleaseAll()
264 : : {
265 [ + - ]: 158 : ::com::sun::star::lang::EventObject aObject;
266 [ + - ]: 158 : aObject.Source = (::cppu::OWeakObject*) this;
267 [ + - ][ + - ]: 158 : aListeners.disposeAndClear( aObject );
268 : 158 : }
269 : :
270 : 0 : void SAL_CALL SfxStatusDispatcher::dispatch( const ::com::sun::star::util::URL&, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& ) throw ( ::com::sun::star::uno::RuntimeException )
271 : : {
272 : 0 : }
273 : :
274 : 0 : void SAL_CALL SfxStatusDispatcher::dispatchWithNotification(
275 : : const ::com::sun::star::util::URL&,
276 : : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >&,
277 : : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& ) throw( ::com::sun::star::uno::RuntimeException )
278 : : {
279 : 0 : }
280 : :
281 [ + - ][ + + ]: 4871786 : SFX_IMPL_XINTERFACE_2( SfxStatusDispatcher, OWeakObject, ::com::sun::star::frame::XNotifyingDispatch, ::com::sun::star::frame::XDispatch )
[ + - ]
282 [ # # ][ # # ]: 0 : SFX_IMPL_XTYPEPROVIDER_2( SfxStatusDispatcher, ::com::sun::star::frame::XNotifyingDispatch, ::com::sun::star::frame::XDispatch )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
283 : : //IMPLNAME "com.sun.star.comp.sfx2.StatusDispatcher",
284 : :
285 : 103366 : SfxStatusDispatcher::SfxStatusDispatcher()
286 [ + - ][ + - ]: 103366 : : aListeners( aMutex )
287 : : {
288 : 103366 : }
289 : :
290 : 0 : void SAL_CALL SfxStatusDispatcher::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
291 : : {
292 : 0 : aListeners.addInterface( aURL.Complete, aListener );
293 [ # # ]: 0 : if ( aURL.Complete.compareToAscii(".uno:LifeTime")==0 )
294 : : {
295 [ # # ]: 0 : ::com::sun::star::frame::FeatureStateEvent aEvent;
296 : 0 : aEvent.FeatureURL = aURL;
297 [ # # ]: 0 : aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
298 : 0 : aEvent.IsEnabled = sal_True;
299 : 0 : aEvent.Requery = sal_False;
300 [ # # ][ # # ]: 0 : aListener->statusChanged( aEvent );
[ # # ]
301 : : }
302 : 0 : }
303 : :
304 : 106620 : void SAL_CALL SfxStatusDispatcher::removeStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL ) throw ( ::com::sun::star::uno::RuntimeException )
305 : : {
306 : 106620 : aListeners.removeInterface( aURL.Complete, aListener );
307 : 106620 : }
308 : :
309 [ + - ][ + + ]: 5044450 : SFX_IMPL_XINTERFACE_1( SfxOfficeDispatch, SfxStatusDispatcher, ::com::sun::star::lang::XUnoTunnel )
[ + - ]
310 [ # # ][ # # ]: 0 : SFX_IMPL_XTYPEPROVIDER_2( SfxOfficeDispatch, ::com::sun::star::frame::XNotifyingDispatch, ::com::sun::star::lang::XUnoTunnel )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
311 : :
312 : :
313 : : //-------------------------------------------------------------------------
314 : : // XUnoTunnel
315 : 173371 : sal_Int64 SAL_CALL SfxOfficeDispatch::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException)
316 : : {
317 [ + - ]: 173371 : if ( aIdentifier == impl_getStaticIdentifier() )
318 : 173371 : return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ));
319 : : else
320 : 173371 : return 0;
321 : : }
322 : :
323 : 102819 : SfxOfficeDispatch::SfxOfficeDispatch( SfxBindings& rBindings, SfxDispatcher* pDispat, const SfxSlot* pSlot, const ::com::sun::star::util::URL& rURL )
324 : : {
325 : : // this object is an adapter that shows a ::com::sun::star::frame::XDispatch-Interface to the outside and uses a SfxControllerItem to monitor a state
326 [ + - ][ + - ]: 102819 : pControllerItem = new SfxDispatchController_Impl( this, &rBindings, pDispat, pSlot, rURL );
327 : 102819 : }
328 : :
329 : 314 : SfxOfficeDispatch::SfxOfficeDispatch( SfxDispatcher* pDispat, const SfxSlot* pSlot, const ::com::sun::star::util::URL& rURL )
330 : : {
331 : : // this object is an adapter that shows a ::com::sun::star::frame::XDispatch-Interface to the outside and uses a SfxControllerItem to monitor a state
332 [ + - ][ + - ]: 314 : pControllerItem = new SfxDispatchController_Impl( this, NULL, pDispat, pSlot, rURL );
333 : 314 : }
334 : :
335 : 101933 : SfxOfficeDispatch::~SfxOfficeDispatch()
336 : : {
337 [ + - ]: 101933 : if ( pControllerItem )
338 : : {
339 : : // when dispatch object is released, destroy its connection to this object and destroy it
340 [ + - ]: 101933 : pControllerItem->UnBindController();
341 [ + - ][ + - ]: 101933 : delete pControllerItem;
342 : : }
343 [ - + ]: 203866 : }
344 : :
345 : 346742 : const ::com::sun::star::uno::Sequence< sal_Int8 >& SfxOfficeDispatch::impl_getStaticIdentifier()
346 : : {
347 : : // {38 57 CA 80 09 36 11 d4 83 FE 00 50 04 52 6B 21}
348 : : static sal_uInt8 pGUID[16] = { 0x38, 0x57, 0xCA, 0x80, 0x09, 0x36, 0x11, 0xd4, 0x83, 0xFE, 0x00, 0x50, 0x04, 0x52, 0x6B, 0x21 };
349 [ + + ][ + - ]: 346742 : static ::com::sun::star::uno::Sequence< sal_Int8 > seqID((sal_Int8*)pGUID,16) ;
[ + - ][ # # ]
350 : 346742 : return seqID ;
351 : : }
352 : :
353 : :
354 : 54 : void SAL_CALL SfxOfficeDispatch::dispatch( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs ) throw ( ::com::sun::star::uno::RuntimeException )
355 : : {
356 : : // ControllerItem is the Impl class
357 [ + - ]: 54 : if ( pControllerItem )
358 : : {
359 : : // The JavaContext contains an interaction handler which is used when
360 : : // the creation of a Java Virtual Machine fails. The second parameter
361 : : // indicates, that there shall only be one user notification (message box)
362 : : // even if the same error (interaction) reoccurs. The effect is, that if a
363 : : // user selects a menu entry than they may get only one notification that
364 : : // a JRE is not selected.
365 : : com::sun::star::uno::ContextLayer layer(
366 : : new svt::JavaContext( com::sun::star::uno::getCurrentContext(),
367 [ + - ][ + - ]: 54 : true) );
[ + - ][ + - ]
[ + - ]
368 : :
369 [ + - ][ + - ]: 54 : pControllerItem->dispatch( aURL, aArgs, ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchResultListener >() );
370 : : }
371 : 54 : }
372 : :
373 : 8 : void SAL_CALL SfxOfficeDispatch::dispatchWithNotification( const ::com::sun::star::util::URL& aURL,
374 : : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs,
375 : : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& rListener ) throw( ::com::sun::star::uno::RuntimeException )
376 : : {
377 : : // ControllerItem is the Impl class
378 [ + - ]: 8 : if ( pControllerItem )
379 : : {
380 : : // see comment for SfxOfficeDispatch::dispatch
381 : : com::sun::star::uno::ContextLayer layer(
382 : : new svt::JavaContext( com::sun::star::uno::getCurrentContext(),
383 [ + - ][ + - ]: 8 : true) );
[ + - ][ + - ]
[ + - ]
384 : :
385 [ + - ][ + - ]: 8 : pControllerItem->dispatch( aURL, aArgs, rListener );
386 : : }
387 : 8 : }
388 : :
389 : 103069 : void SAL_CALL SfxOfficeDispatch::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
390 : : {
391 : 103069 : GetListeners().addInterface( aURL.Complete, aListener );
392 [ + - ]: 103069 : if ( pControllerItem )
393 : : {
394 : : // ControllerItem is the Impl class
395 : 103069 : pControllerItem->addStatusListener( aListener, aURL );
396 : : }
397 : 103069 : }
398 : :
399 : 173371 : SfxDispatcher* SfxOfficeDispatch::GetDispatcher_Impl()
400 : : {
401 : 173371 : return pControllerItem->GetDispatcher();
402 : : }
403 : :
404 : 108 : void SfxOfficeDispatch::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
405 : : {
406 [ + - ]: 108 : if ( pControllerItem )
407 : 108 : pControllerItem->SetFrame( xFrame );
408 : 108 : }
409 : :
410 : 103133 : void SfxOfficeDispatch::SetMasterUnoCommand( sal_Bool bSet )
411 : : {
412 [ + - ]: 103133 : if ( pControllerItem )
413 : 103133 : pControllerItem->setMasterSlaveCommand( bSet );
414 : 103133 : }
415 : :
416 : : // Determine if URL contains a master/slave command which must be handled a little bit different
417 : 281466 : sal_Bool SfxOfficeDispatch::IsMasterUnoCommand( const ::com::sun::star::util::URL& aURL )
418 : : {
419 [ + - ][ + + ]: 281466 : if ( aURL.Protocol == ".uno:" && ( aURL.Path.indexOf( '.' ) > 0 ))
[ + + ]
420 : 206 : return sal_True;
421 : :
422 : 281466 : return sal_False;
423 : : }
424 : :
425 : 277692 : rtl::OUString SfxOfficeDispatch::GetMasterUnoCommand( const ::com::sun::star::util::URL& aURL )
426 : : {
427 : 277692 : rtl::OUString aMasterCommand;
428 [ + + ][ + - ]: 277692 : if ( IsMasterUnoCommand( aURL ))
429 : : {
430 : 206 : sal_Int32 nIndex = aURL.Path.indexOf( '.' );
431 [ + - ]: 206 : if ( nIndex > 0 )
432 : 206 : aMasterCommand = aURL.Path.copy( 0, nIndex );
433 : : }
434 : :
435 : 277692 : return aMasterCommand;
436 : : }
437 : :
438 : 103133 : SfxDispatchController_Impl::SfxDispatchController_Impl(
439 : : SfxOfficeDispatch* pDisp,
440 : : SfxBindings* pBind,
441 : : SfxDispatcher* pDispat,
442 : : const SfxSlot* pSlot,
443 : : const ::com::sun::star::util::URL& rURL )
444 : : : aDispatchURL( rURL )
445 : : , pDispatcher( pDispat )
446 : : , pBindings( pBind )
447 : : , pLastState( 0 )
448 : 103133 : , nSlot( pSlot->GetSlotId() )
449 : : , pDispatch( pDisp )
450 : : , bMasterSlave( sal_False )
451 : : , bVisible( sal_True )
452 [ + - ]: 206266 : , pUnoName( pSlot->pUnoName )
453 : : {
454 [ - + ][ # # ]: 103133 : if ( aDispatchURL.Protocol == "slot:" && pUnoName )
[ - + ]
455 : : {
456 [ # # ]: 0 : rtl::OStringBuffer aTmp(RTL_CONSTASCII_STRINGPARAM(".uno:"));
457 [ # # ]: 0 : aTmp.append(pUnoName);
458 [ # # ]: 0 : aDispatchURL.Complete = ::rtl::OStringToOUString(aTmp.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
459 [ # # ][ # # ]: 0 : Reference< XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
460 [ # # ][ # # ]: 0 : xTrans->parseStrict( aDispatchURL );
461 : : }
462 : :
463 [ + - ]: 103133 : SetId( nSlot );
464 [ + + ]: 103133 : if ( pBindings )
465 : : {
466 : : // Bind immediately to enable the cache to recycle dispatches when asked for the same command
467 : : // a command in "slot" or in ".uno" notation must be treated as identical commands!
468 [ + - ]: 102819 : pBindings->ENTERREGISTRATIONS();
469 [ + - ]: 102819 : BindInternal_Impl( nSlot, pBindings );
470 [ + - ]: 102819 : pBindings->LEAVEREGISTRATIONS();
471 : : }
472 : 103133 : }
473 : :
474 [ + - ]: 101933 : SfxDispatchController_Impl::~SfxDispatchController_Impl()
475 : : {
476 [ + + ][ + + ]: 101933 : if ( pLastState && !IsInvalidItem( pLastState ) )
[ + + ]
477 [ + - ][ + - ]: 52312 : delete pLastState;
478 : :
479 [ - + ]: 101933 : if ( pDispatch )
480 : : {
481 : : // disconnect
482 : 0 : pDispatch->pControllerItem = NULL;
483 : :
484 : : // force all listeners to release the dispatch object
485 [ # # ]: 0 : ::com::sun::star::lang::EventObject aObject;
486 [ # # ][ # # ]: 0 : aObject.Source = (::cppu::OWeakObject*) pDispatch;
487 [ # # ][ # # ]: 0 : pDispatch->GetListeners().disposeAndClear( aObject );
488 : : }
489 [ - + ]: 203866 : }
490 : :
491 : 108 : void SfxDispatchController_Impl::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _xFrame)
492 : : {
493 : 108 : xFrame = _xFrame;
494 : 108 : }
495 : :
496 : 103133 : void SfxDispatchController_Impl::setMasterSlaveCommand( sal_Bool bSet )
497 : : {
498 : 103133 : bMasterSlave = bSet;
499 : 103133 : }
500 : :
501 : 101933 : void SfxDispatchController_Impl::UnBindController()
502 : : {
503 : 101933 : pDispatch = NULL;
504 [ - + ]: 101933 : if ( IsBound() )
505 : : {
506 : 0 : GetBindings().ENTERREGISTRATIONS();
507 : 0 : SfxControllerItem::UnBind();
508 : 0 : GetBindings().LEAVEREGISTRATIONS();
509 : : }
510 : 101933 : }
511 : :
512 : 0 : void SfxDispatchController_Impl::addParametersToArgs( const com::sun::star::util::URL& aURL, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) const
513 : : {
514 : : // Extract the parameter from the URL and put them into the property value sequence
515 : 0 : sal_Int32 nQueryIndex = aURL.Complete.indexOf( '?' );
516 [ # # ]: 0 : if ( nQueryIndex > 0 )
517 : : {
518 : 0 : rtl::OUString aParamString( aURL.Complete.copy( nQueryIndex+1 ));
519 : 0 : sal_Int32 nIndex = 0;
520 [ # # ]: 0 : do
521 : : {
522 : 0 : rtl::OUString aToken = aParamString.getToken( 0, '&', nIndex );
523 : :
524 : 0 : sal_Int32 nParmIndex = 0;
525 : 0 : rtl::OUString aParamType;
526 : 0 : rtl::OUString aParamName = aToken.getToken( 0, '=', nParmIndex );
527 [ # # ]: 0 : rtl::OUString aValue = (nParmIndex!=-1) ? aToken.getToken( 0, '=', nParmIndex ) : ::rtl::OUString();
528 : :
529 [ # # ]: 0 : if ( !aParamName.isEmpty() )
530 : : {
531 : 0 : nParmIndex = 0;
532 : 0 : aToken = aParamName;
533 [ # # ]: 0 : aParamName = (nParmIndex!=-1) ? aToken.getToken( 0, ':', nParmIndex ) : ::rtl::OUString();
534 [ # # ]: 0 : aParamType = (nParmIndex!=-1) ? aToken.getToken( 0, ':', nParmIndex ) : ::rtl::OUString();
535 : : }
536 : :
537 : 0 : sal_Int32 nLen = rArgs.getLength();
538 [ # # ]: 0 : rArgs.realloc( nLen+1 );
539 [ # # ]: 0 : rArgs[nLen].Name = aParamName;
540 : :
541 [ # # ]: 0 : if ( aParamType.isEmpty() )
542 : : {
543 : : // Default: LONG
544 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= aValue.toInt32();
545 : : }
546 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_BOOL], 4 ))
547 : : {
548 : : // sal_Bool support
549 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= aValue.toBoolean();
550 : : }
551 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_BYTE], 4 ))
552 : : {
553 : : // sal_uInt8 support
554 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= sal_Int8( aValue.toInt32() );
555 : : }
556 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_LONG], 4 ))
557 : : {
558 : : // LONG support
559 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= aValue.toInt32();
560 : : }
561 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_SHORT], 5 ))
562 : : {
563 : : // SHORT support
564 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= sal_Int8( aValue.toInt32() );
565 : : }
566 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_HYPER], 5 ))
567 : : {
568 : : // HYPER support
569 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= aValue.toInt64();
570 : : }
571 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_FLOAT], 5 ))
572 : : {
573 : : // FLOAT support
574 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= aValue.toFloat();
575 : : }
576 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_STRING], 6 ))
577 : : {
578 : : // STRING support
579 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= rtl::OUString( INetURLObject::decode( aValue, '%', INetURLObject::DECODE_WITH_CHARSET ));
[ # # ]
580 : : }
581 [ # # ]: 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_DOUBLE], 6))
582 : : {
583 : : // DOUBLE support
584 [ # # ][ # # ]: 0 : rArgs[nLen].Value <<= aValue.toDouble();
585 : 0 : }
586 : : }
587 : 0 : while ( nIndex >= 0 );
588 : : }
589 : 0 : }
590 : :
591 : 32305 : SfxMapUnit SfxDispatchController_Impl::GetCoreMetric( SfxItemPool& rPool, sal_uInt16 nSlotId )
592 : : {
593 : 32305 : sal_uInt16 nWhich = rPool.GetWhich( nSlotId );
594 : 32305 : return rPool.GetMetric( nWhich );
595 : : }
596 : :
597 : 0 : rtl::OUString SfxDispatchController_Impl::getSlaveCommand( const ::com::sun::star::util::URL& rURL )
598 : : {
599 : 0 : rtl::OUString aSlaveCommand;
600 : 0 : sal_Int32 nIndex = rURL.Path.indexOf( '.' );
601 [ # # ][ # # ]: 0 : if (( nIndex > 0 ) && ( nIndex < rURL.Path.getLength() ))
[ # # ]
602 : 0 : aSlaveCommand = rURL.Path.copy( nIndex+1 );
603 : 0 : return aSlaveCommand;
604 : : }
605 : :
606 : 62 : void SAL_CALL SfxDispatchController_Impl::dispatch( const ::com::sun::star::util::URL& aURL,
607 : : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs,
608 : : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& rListener ) throw( ::com::sun::star::uno::RuntimeException )
609 : : {
610 [ + - ]: 62 : SolarMutexGuard aGuard;
611 [ + - + - : 186 : if (
- + # # #
# ][ + - ]
612 : : pDispatch &&
613 : : (
614 : 124 : (aURL.Protocol.equalsAsciiL( ".uno:", 5 ) && aURL.Path == aDispatchURL.Path) ||
615 : 0 : (aURL.Protocol.equalsAsciiL( "slot:", 5 ) && aURL.Path.toInt32() == GetId())
616 : : )
617 : : )
618 : : {
619 [ - + ][ # # ]: 62 : if ( !pDispatcher && pBindings )
620 : 0 : pDispatcher = GetBindings().GetDispatcher_Impl();
621 : :
622 [ + - ]: 62 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lNewArgs;
623 : 62 : sal_Int32 nCount = aArgs.getLength();
624 : :
625 : : // Support for URL based arguments
626 [ + - ]: 62 : INetURLObject aURLObj( aURL.Complete );
627 [ + - ][ - + ]: 62 : if ( aURLObj.HasParam() )
628 [ # # ]: 0 : addParametersToArgs( aURL, lNewArgs );
629 : :
630 : : // Try to find call mode and frame name inside given arguments...
631 : 62 : SfxCallMode nCall = SFX_CALLMODE_STANDARD;
632 : 62 : sal_Int32 nMarkArg = -1;
633 : :
634 : : // Filter arguments which shouldn't be part of the sequence property value
635 : 62 : sal_Bool bTemp = sal_Bool();
636 : 62 : sal_uInt16 nModifier(0);
637 : 62 : sal_Bool bVBARequest = sal_False;
638 [ + - ]: 62 : std::vector< ::com::sun::star::beans::PropertyValue > aAddArgs;
639 [ + + ]: 84 : for( sal_Int32 n=0; n<nCount; n++ )
640 : : {
641 : 22 : const ::com::sun::star::beans::PropertyValue& rProp = aArgs[n];
642 [ + + ]: 22 : if( rProp.Name.equalsAsciiL("SynchronMode",12))
643 : : {
644 [ + - ]: 8 : if( rProp.Value >>=bTemp )
645 [ + - ]: 8 : nCall = bTemp ? SFX_CALLMODE_SYNCHRON : SFX_CALLMODE_ASYNCHRON;
646 : : }
647 [ - + ]: 14 : else if( rProp.Name.equalsAsciiL("Bookmark",8))
648 : : {
649 : 0 : nMarkArg = n;
650 [ # # ]: 0 : aAddArgs.push_back( aArgs[n] );
651 : : }
652 [ + + ]: 14 : else if( rProp.Name.equalsAsciiL("KeyModifier",11))
653 : 2 : rProp.Value >>= nModifier;
654 [ - + ]: 12 : else if( rProp.Name.equalsAsciiL("VBADialogResultRequest",22) )
655 : : {
656 : 0 : rProp.Value >>= bVBARequest;
657 : : }
658 : : else
659 [ + - ]: 12 : aAddArgs.push_back( aArgs[n] );
660 : : }
661 : :
662 : : // Add needed arguments to sequence property value
663 : 62 : sal_uInt32 nAddArgs = aAddArgs.size();
664 [ + + ]: 62 : if ( nAddArgs > 0 )
665 : : {
666 : 12 : sal_uInt32 nIndex( lNewArgs.getLength() );
667 : :
668 [ + - ]: 12 : lNewArgs.realloc( lNewArgs.getLength()+aAddArgs.size() );
669 [ + + ]: 24 : for ( sal_uInt32 i = 0; i < nAddArgs; i++ )
670 [ + - ]: 12 : lNewArgs[nIndex++] = aAddArgs[i];
671 : : }
672 : :
673 : : // Overwrite possible detected sychron argument, if real listener exists (currently no other way)
674 [ + + ]: 62 : if ( rListener.is() )
675 : 8 : nCall = SFX_CALLMODE_SYNCHRON;
676 : :
677 [ - + ][ # # ]: 62 : if( GetId() == SID_JUMPTOMARK && nMarkArg == - 1 )
[ - + ]
678 : : {
679 : : // we offer dispatches for SID_JUMPTOMARK if the URL points to a bookmark inside the document
680 : : // so we must retrieve this as an argument from the parsed URL
681 [ # # ]: 0 : lNewArgs.realloc( lNewArgs.getLength()+1 );
682 : 0 : nMarkArg = lNewArgs.getLength()-1;
683 [ # # ]: 0 : lNewArgs[nMarkArg].Name = ::rtl::OUString("Bookmark");
684 [ # # ][ # # ]: 0 : lNewArgs[nMarkArg].Value <<= aURL.Mark;
685 : : }
686 : :
687 [ + - ][ + - ]: 62 : css::uno::Reference< css::frame::XFrame > xFrameRef(xFrame.get(), css::uno::UNO_QUERY);
688 [ + - ][ + - ]: 62 : if (! xFrameRef.is() && pDispatcher)
[ + - ]
689 : : {
690 [ + - ]: 62 : SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
691 [ + - ]: 62 : if (pViewFrame)
692 [ + - ][ + - ]: 62 : xFrameRef = pViewFrame->GetFrame().GetFrameInterface();
[ + - ]
693 : : }
694 [ + - ][ + - ]: 62 : SfxAllItemSet aInternalSet( SFX_APP()->GetPool() );
695 [ + - ]: 62 : if (xFrameRef.is()) // an empty set is no problem ... but an empty frame reference can be a problem !
696 [ + - ][ + - ]: 62 : aInternalSet.Put( SfxUnoFrameItem( SID_FILLFRAME, xFrameRef ) );
[ + - ]
697 : :
698 : 62 : sal_Bool bSuccess = sal_False;
699 : 62 : const SfxPoolItem* pItem = NULL;
700 : 62 : SfxShell* pShell( 0 );
701 : : // #i102619# Retrieve metric from shell before execution - the shell could be destroyed after execution
702 : 62 : SfxMapUnit eMapUnit( SFX_MAPUNIT_100TH_MM );
703 [ + - ][ + - ]: 62 : if ( pDispatcher->GetBindings() )
704 : : {
705 [ + - ][ + - ]: 62 : if ( !pDispatcher->IsLocked( GetId() ) )
706 : : {
707 : 62 : const SfxSlot *pSlot = 0;
708 [ + - ]: 124 : if ( pDispatcher->GetShellAndSlot_Impl( GetId(), &pShell, &pSlot, sal_False,
709 [ + - ]: 62 : SFX_CALLMODE_MODAL==(nCall&SFX_CALLMODE_MODAL), sal_False ) )
710 : : {
711 [ - + ]: 62 : if ( bMasterSlave )
712 : : {
713 : : // Extract slave command and add argument to the args list. Master slot MUST
714 : : // have a argument that has the same name as the master slot and type is SfxStringItem.
715 : 0 : sal_Int32 nIndex = lNewArgs.getLength();
716 [ # # ]: 0 : lNewArgs.realloc( nIndex+1 );
717 [ # # ]: 0 : lNewArgs[nIndex].Name = rtl::OUString::createFromAscii( pSlot->pUnoName );
718 [ # # ][ # # ]: 0 : lNewArgs[nIndex].Value = makeAny( SfxDispatchController_Impl::getSlaveCommand( aDispatchURL ));
719 : : }
720 : :
721 [ + - ]: 62 : eMapUnit = GetCoreMetric( pShell->GetPool(), GetId() );
722 [ + - ][ + - ]: 62 : boost::scoped_ptr<SfxAllItemSet> xSet(new SfxAllItemSet(pShell->GetPool()));
723 [ + - ]: 62 : TransformParameters(GetId(), lNewArgs, *xSet, pSlot);
724 [ + + ]: 62 : if (xSet->Count())
725 : : {
726 : : // execute with arguments - call directly
727 [ + - ]: 12 : pItem = pDispatcher->Execute(GetId(), nCall, xSet.get(), &aInternalSet, nModifier);
728 : 12 : bSuccess = (pItem != NULL);
729 : : }
730 : : else
731 : : {
732 : : // Be sure to delete this before we send a dispatch
733 : : // request, which will destroy the current shell.
734 [ + - ]: 50 : xSet.reset();
735 : :
736 : : // execute using bindings, enables support for toggle/enum etc.
737 [ + - ]: 50 : SfxRequest aReq( GetId(), nCall, pShell->GetPool() );
738 [ + - ]: 50 : aReq.SetModifier( nModifier );
739 [ + - ]: 50 : aReq.SetInternalArgs_Impl(aInternalSet);
740 [ + - ][ + - ]: 50 : pDispatcher->GetBindings()->Execute_Impl( aReq, pSlot, pShell );
741 [ + - ]: 50 : pItem = aReq.GetReturnValue();
742 [ + - ][ + + ]: 50 : bSuccess = aReq.IsDone() || pItem != NULL;
[ - + ]
743 [ - + ]: 50 : if ( bVBARequest )
744 : : {
745 [ # # ][ # # ]: 0 : SFX_REQUEST_ARG( aReq, pDlgRet, SfxBoolItem, SID_DIALOG_RETURN, sal_False );
746 [ # # ]: 0 : if ( pDlgRet )
747 : : {
748 : 0 : bSuccess = pDlgRet->GetValue();
749 : : }
750 [ + - ]: 50 : }
751 [ + - ]: 62 : }
752 : : }
753 : : #ifdef DBG_UTIL
754 : : else
755 : : DBG_WARNING("MacroPlayer: Unknown slot dispatched!");
756 : : #endif
757 : : }
758 : : }
759 : : else
760 : : {
761 [ # # ][ # # ]: 0 : eMapUnit = GetCoreMetric( SFX_APP()->GetPool(), GetId() );
762 : : // AppDispatcher
763 [ # # ][ # # ]: 0 : SfxAllItemSet aSet( SFX_APP()->GetPool() );
764 [ # # ]: 0 : TransformParameters( GetId(), lNewArgs, aSet );
765 : :
766 [ # # ]: 0 : if ( aSet.Count() )
767 [ # # ]: 0 : pItem = pDispatcher->Execute( GetId(), nCall, &aSet, &aInternalSet, nModifier );
768 : : else
769 : : // SfxRequests take empty sets as argument sets, GetArgs() returning non-zero!
770 [ # # ]: 0 : pItem = pDispatcher->Execute( GetId(), nCall, 0, &aInternalSet, nModifier );
771 : :
772 : : // no bindings, no invalidate ( usually done in SfxDispatcher::Call_Impl()! )
773 [ # # ]: 0 : if ( SfxApplication::Get() )
774 : : {
775 [ # # ][ # # ]: 0 : SfxDispatcher* pAppDispat = SFX_APP()->GetAppDispatcher_Impl();
776 [ # # ]: 0 : if ( pAppDispat )
777 : : {
778 : 0 : const SfxPoolItem* pState=0;
779 [ # # ]: 0 : SfxItemState eState = pDispatcher->QueryState( GetId(), pState );
780 [ # # ]: 0 : StateChanged( GetId(), eState, pState );
781 : : }
782 : : }
783 : :
784 [ # # ]: 0 : bSuccess = (pItem != NULL);
785 : : }
786 : :
787 [ + + ]: 62 : if ( rListener.is() )
788 : : {
789 [ + - ]: 8 : ::com::sun::star::frame::DispatchResultEvent aEvent;
790 [ + + ]: 8 : if ( bSuccess )
791 : 2 : aEvent.State = com::sun::star::frame::DispatchResultState::SUCCESS;
792 : : else
793 : 6 : aEvent.State = com::sun::star::frame::DispatchResultState::FAILURE;
794 : :
795 [ + - ]: 8 : aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
796 [ + + ][ + - ]: 8 : if ( bSuccess && pItem && !pItem->ISA(SfxVoidItem) )
[ + - ][ + - ]
[ + - ][ + + ]
797 : : {
798 : 2 : sal_uInt16 nSubId( 0 );
799 [ - + ]: 2 : if ( eMapUnit == SFX_MAPUNIT_TWIP )
800 : 0 : nSubId |= CONVERT_TWIPS;
801 [ + - ]: 2 : pItem->QueryValue( aEvent.Result, (sal_uInt8)nSubId );
802 : : }
803 : :
804 [ + - ][ + - ]: 8 : rListener->dispatchFinished( aEvent );
[ + - ]
805 [ + - ][ + - ]: 62 : }
[ + - ]
806 [ + - ]: 62 : }
807 : 62 : }
808 : :
809 : 173371 : SfxDispatcher* SfxDispatchController_Impl::GetDispatcher()
810 : : {
811 [ - + ][ # # ]: 173371 : if ( !pDispatcher && pBindings )
812 : 0 : pDispatcher = GetBindings().GetDispatcher_Impl();
813 : 173371 : return pDispatcher;
814 : : }
815 : :
816 : 103069 : void SAL_CALL SfxDispatchController_Impl::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
817 : : {
818 [ + - ]: 103069 : SolarMutexGuard aGuard;
819 [ - + ]: 103069 : if ( !pDispatch )
820 : 103069 : return;
821 : :
822 : : // Use alternative QueryState call to have a valid UNO representation of the state.
823 : 103069 : ::com::sun::star::uno::Any aState;
824 [ # # ][ - + ]: 103069 : if ( !pDispatcher && pBindings )
825 : 0 : pDispatcher = GetBindings().GetDispatcher_Impl();
826 [ + - ]: 103069 : SfxItemState eState = pDispatcher->QueryState( GetId(), aState );
827 : :
828 [ - + ]: 103069 : if ( eState == SFX_ITEM_DONTCARE )
829 : : {
830 : : // Use special uno struct to transport don't care state
831 : 0 : ::com::sun::star::frame::status::ItemStatus aItemStatus;
832 : 0 : aItemStatus.State = ::com::sun::star::frame::status::ItemState::dont_care;
833 [ # # ]: 0 : aState = makeAny( aItemStatus );
834 : : }
835 : :
836 [ + - ]: 103069 : ::com::sun::star::frame::FeatureStateEvent aEvent;
837 : 103069 : aEvent.FeatureURL = aURL;
838 [ + - ]: 103069 : aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
839 : 103069 : aEvent.Requery = sal_False;
840 [ + + ]: 103069 : if ( bVisible )
841 : : {
842 : 103065 : aEvent.IsEnabled = eState != SFX_ITEM_DISABLED;
843 : 103065 : aEvent.State = aState;
844 : : }
845 : : else
846 : : {
847 : 4 : ::com::sun::star::frame::status::Visibility aVisibilityStatus;
848 : 4 : aVisibilityStatus.bVisible = sal_False;
849 : :
850 : : // MBA: we might decide to *not* disable "invisible" slots, but this would be
851 : : // a change that needs to adjust at least the testtool
852 : 4 : aEvent.IsEnabled = sal_False;
853 [ + - ]: 4 : aEvent.State = makeAny( aVisibilityStatus );
854 : : }
855 : :
856 [ + - ][ + - ]: 103069 : aListener->statusChanged( aEvent );
[ + - ][ + - ]
[ + - ]
857 : : }
858 : :
859 : 64836 : void SfxDispatchController_Impl::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState, SfxSlotServer* pSlotServ )
860 : : {
861 [ - + ]: 64836 : if ( !pDispatch )
862 : 64836 : return;
863 : :
864 : : // Bindings instance notifies controller about a state change, listeners must be notified also
865 : : // Don't cache visibility state changes as they are volatile. We need our real state to send it
866 : : // to our controllers after visibility is set to true.
867 : 64836 : sal_Bool bNotify = sal_True;
868 [ + + ][ + + ]: 64836 : if ( pState && !IsInvalidItem( pState ) )
[ + + ]
869 : : {
870 [ + + ]: 54136 : if ( !pState->ISA( SfxVisibilityItem ) )
871 : : {
872 [ + + ][ + + ]: 54134 : sal_Bool bBothAvailable = pLastState && !IsInvalidItem(pLastState);
873 [ + + ]: 54134 : if ( bBothAvailable )
874 [ + - ][ + + ]: 1045 : bNotify = pState->Type() != pLastState->Type() || *pState != *pLastState;
875 [ + + ][ + + ]: 54134 : if ( pLastState && !IsInvalidItem( pLastState ) )
[ + + ]
876 [ + - ]: 1045 : delete pLastState;
877 [ + - ]: 54134 : pLastState = !IsInvalidItem(pState) ? pState->Clone() : pState;
878 : 54134 : bVisible = sal_True;
879 : : }
880 : : else
881 : 2 : bVisible = ((SfxVisibilityItem *)pState)->GetValue();
882 : : }
883 : : else
884 : : {
885 [ + + ][ + + ]: 10700 : if ( pLastState && !IsInvalidItem( pLastState ) )
[ + + ]
886 [ + - ]: 75 : delete pLastState;
887 : 10700 : pLastState = pState;
888 : : }
889 : :
890 : 64836 : ::cppu::OInterfaceContainerHelper* pContnr = pDispatch->GetListeners().getContainer ( aDispatchURL.Complete );
891 [ + + ][ + + ]: 64836 : if ( bNotify && pContnr )
892 : : {
893 : 52854 : ::com::sun::star::uno::Any aState;
894 [ + - ][ + - ]: 52854 : if ( ( eState >= SFX_ITEM_AVAILABLE ) && pState && !IsInvalidItem( pState ) && !pState->ISA(SfxVoidItem) )
[ + - ][ + - ]
[ + - ][ + + ]
[ + + ]
895 : : {
896 : : // Retrieve metric from pool to have correct sub ID when calling QueryValue
897 : 32243 : sal_uInt16 nSubId( 0 );
898 : 32243 : SfxMapUnit eMapUnit( SFX_MAPUNIT_100TH_MM );
899 : :
900 : : // retrieve the core metric
901 : : // it's enough to check the objectshell, the only shell that does not use the pool of the document
902 : : // is SfxViewFrame, but it hasn't any metric parameters
903 : : // TODO/LATER: what about the FormShell? Does it use any metric data?! Perhaps it should use the Pool of the document!
904 [ + - ][ + - ]: 32243 : if ( pSlotServ && pDispatcher )
905 : : {
906 [ + - ]: 32243 : SfxShell* pShell = pDispatcher->GetShell( pSlotServ->GetShellLevel() );
907 : : DBG_ASSERT( pShell, "Can't get core metric without shell!" );
908 [ + - ]: 32243 : if ( pShell )
909 [ + - ]: 32243 : eMapUnit = GetCoreMetric( pShell->GetPool(), nSID );
910 : : }
911 : :
912 [ + + ]: 32243 : if ( eMapUnit == SFX_MAPUNIT_TWIP )
913 : 26958 : nSubId |= CONVERT_TWIPS;
914 : :
915 [ + - ]: 32243 : pState->QueryValue( aState, (sal_uInt8)nSubId );
916 : : }
917 [ + + ]: 20611 : else if ( eState == SFX_ITEM_DONTCARE )
918 : : {
919 : : // Use special uno struct to transport don't care state
920 : 20 : ::com::sun::star::frame::status::ItemStatus aItemStatus;
921 : 20 : aItemStatus.State = ::com::sun::star::frame::status::ItemState::dont_care;
922 [ + - ]: 20 : aState = makeAny( aItemStatus );
923 : : }
924 : :
925 [ + - ]: 52854 : ::com::sun::star::frame::FeatureStateEvent aEvent;
926 : 52854 : aEvent.FeatureURL = aDispatchURL;
927 [ + - ]: 52854 : aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
928 : 52854 : aEvent.IsEnabled = eState != SFX_ITEM_DISABLED;
929 : 52854 : aEvent.Requery = sal_False;
930 : 52854 : aEvent.State = aState;
931 : :
932 [ + - ]: 52854 : ::cppu::OInterfaceIteratorHelper aIt( *pContnr );
933 [ + + ]: 108033 : while( aIt.hasMoreElements() )
934 : : {
935 : : try
936 : : {
937 [ + - ][ + - ]: 55179 : ((::com::sun::star::frame::XStatusListener *)aIt.next())->statusChanged( aEvent );
938 : : }
939 [ # # # # ]: 0 : catch (const ::com::sun::star::uno::RuntimeException&)
940 : : {
941 [ # # ]: 0 : aIt.remove();
942 : : }
943 [ + - ][ + - ]: 52854 : }
944 : : }
945 : : }
946 : :
947 : 0 : void SfxDispatchController_Impl::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
948 : : {
949 : 0 : StateChanged( nSID, eState, pState, 0 );
950 : 0 : }
951 : :
952 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|