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 : #include "sal/config.h"
21 :
22 : #include <iomanip>
23 :
24 : #include <boost/unordered_map.hpp>
25 : #include <sal/log.hxx>
26 : #include <svl/itempool.hxx>
27 : #include <svl/itemiter.hxx>
28 : #include <svl/eitem.hxx>
29 : #include <svl/aeitem.hxx>
30 : #include <svl/intitem.hxx>
31 : #include <svl/stritem.hxx>
32 : #include <svl/visitem.hxx>
33 : #include <com/sun/star/util/URLTransformer.hpp>
34 : #include <com/sun/star/util/XURLTransformer.hpp>
35 : #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
36 : #include <com/sun/star/frame/XDispatch.hpp>
37 : #include <com/sun/star/frame/XDispatchProvider.hpp>
38 : #include <com/sun/star/frame/XStatusListener.hpp>
39 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
40 : #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
41 : #include <com/sun/star/frame/FeatureStateEvent.hpp>
42 : #include <com/sun/star/frame/DispatchDescriptor.hpp>
43 : #include <com/sun/star/frame/XController.hpp>
44 : #include <comphelper/processfactory.hxx>
45 : #include <svtools/itemdel.hxx>
46 :
47 : //Includes below due to nInReschedule
48 : #include "appdata.hxx"
49 : #include <sfx2/bindings.hxx>
50 : #include <sfx2/msg.hxx>
51 : #include "statcach.hxx"
52 : #include <sfx2/ctrlitem.hxx>
53 : #include <sfx2/app.hxx>
54 : #include <sfx2/dispatch.hxx>
55 : #include <sfx2/request.hxx>
56 : #include <sfx2/objface.hxx>
57 : #include "sfxtypes.hxx"
58 : #include "workwin.hxx"
59 : #include <sfx2/unoctitm.hxx>
60 : #include <sfx2/sfx.hrc>
61 : #include <sfx2/sfxuno.hxx>
62 : #include <sfx2/viewfrm.hxx>
63 : #include <sfx2/objsh.hxx>
64 : #include <sfx2/msgpool.hxx>
65 :
66 : #include <com/sun/star/frame/XModuleManager.hpp>
67 :
68 : #include <boost/scoped_ptr.hpp>
69 :
70 : using namespace ::com::sun::star;
71 : using namespace ::com::sun::star::uno;
72 : using namespace ::com::sun::star::util;
73 :
74 : DBG_NAME(SfxBindingsMsgPos)
75 : DBG_NAME(SfxBindingsUpdateServers)
76 : DBG_NAME(SfxBindingsCreateSet)
77 : DBG_NAME(SfxBindingsUpdateCtrl1)
78 : DBG_NAME(SfxBindingsUpdateCtrl2)
79 : DBG_NAME(SfxBindingsNextJob_Impl0)
80 : DBG_NAME(SfxBindingsNextJob_Impl)
81 : DBG_NAME(SfxBindingsUpdate_Impl)
82 : DBG_NAME(SfxBindingsInvalidateAll)
83 :
84 : //====================================================================
85 :
86 : static sal_uInt16 nTimeOut = 300;
87 :
88 : #define TIMEOUT_FIRST nTimeOut
89 : #define TIMEOUT_UPDATING 20
90 : #define TIMEOUT_IDLE 2500
91 :
92 : typedef boost::unordered_map< sal_uInt16, bool > InvalidateSlotMap;
93 :
94 : //====================================================================
95 :
96 : typedef std::vector<SfxStateCache*> SfxStateCacheArr_Impl;
97 :
98 : //====================================================================
99 :
100 0 : class SfxAsyncExec_Impl
101 : {
102 : ::com::sun::star::util::URL aCommand;
103 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
104 : Timer aTimer;
105 :
106 : public:
107 :
108 0 : SfxAsyncExec_Impl( const ::com::sun::star::util::URL& rCmd, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& rDisp )
109 : : aCommand( rCmd )
110 0 : , xDisp( rDisp )
111 : {
112 0 : aTimer.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl, TimerHdl) );
113 0 : aTimer.SetTimeout( 0 );
114 0 : aTimer.Start();
115 0 : }
116 :
117 : DECL_LINK( TimerHdl, Timer*);
118 : };
119 :
120 0 : IMPL_LINK(SfxAsyncExec_Impl, TimerHdl, Timer*, pTimer)
121 : {
122 : (void)pTimer; // unused
123 0 : aTimer.Stop();
124 :
125 0 : Sequence<beans::PropertyValue> aSeq;
126 0 : xDisp->dispatch( aCommand, aSeq );
127 :
128 0 : delete this;
129 0 : return 0L;
130 : }
131 :
132 2165 : class SfxBindings_Impl
133 : {
134 : public:
135 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchRecorder > xRecorder;
136 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv;
137 : SfxUnoControllerArr_Impl*
138 : pUnoCtrlArr;
139 : SfxWorkWindow* pWorkWin;
140 : SfxBindings* pSubBindings;
141 : SfxBindings* pSuperBindings;
142 : SfxStateCacheArr_Impl* pCaches; // One chache for each binding
143 : sal_uInt16 nCachedFunc1; // index for the last one called
144 : sal_uInt16 nCachedFunc2; // index for the second last called
145 : sal_uInt16 nMsgPos; // Message-Position relative the one to be updated
146 : SfxPopupAction ePopupAction; // Checked in DeleteFloatinWindow()
147 : sal_Bool bContextChanged;
148 : sal_Bool bMsgDirty; // Has a MessageServer been invalidated?
149 : sal_Bool bAllMsgDirty; // Has a MessageServer been invalidated?
150 : sal_Bool bAllDirty; // After InvalidateAll
151 : sal_Bool bCtrlReleased; // while EnterRegistrations
152 : AutoTimer aTimer; // for volatile Slots
153 : sal_Bool bInUpdate; // for Assertions
154 : sal_Bool bInNextJob; // for Assertions
155 : sal_Bool bFirstRound; // First round in Update
156 : sal_uInt16 nFirstShell; // Shell, the first round is prefered
157 : sal_uInt16 nOwnRegLevel; // Counts the real Locks, exept those of the Super Bindings
158 : InvalidateSlotMap m_aInvalidateSlots; // store slots which are invalidated while in update
159 : };
160 :
161 : //--------------------------------------------------------------------
162 :
163 : struct SfxFoundCache_Impl
164 : {
165 : sal_uInt16 nSlotId; // the Slot-Id
166 : sal_uInt16 nWhichId; // If available: Which-Id, else: nSlotId
167 : const SfxSlot* pSlot; // Pointer to <Master-Slot>
168 : SfxStateCache* pCache; // Pointer to StatusCache, if possible NULL
169 :
170 : SfxFoundCache_Impl():
171 : nSlotId(0),
172 : nWhichId(0),
173 : pSlot(0),
174 : pCache(0)
175 : {}
176 :
177 : SfxFoundCache_Impl(SfxFoundCache_Impl&r):
178 : nSlotId(r.nSlotId),
179 : nWhichId(r.nWhichId),
180 : pSlot(r.pSlot),
181 : pCache(r.pCache)
182 : {}
183 :
184 51976 : SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ):
185 : nSlotId(nS),
186 : nWhichId(nW),
187 : pSlot(pS),
188 51976 : pCache(pC)
189 51976 : {}
190 :
191 : int operator<( const SfxFoundCache_Impl &r ) const
192 : { return nWhichId < r.nWhichId; }
193 :
194 : int operator==( const SfxFoundCache_Impl &r ) const
195 : { return nWhichId== r.nWhichId; }
196 : };
197 :
198 : //--------------------------------------------------------------------------
199 :
200 15088 : class SfxFoundCacheArr_Impl : public std::vector<SfxFoundCache_Impl*>
201 : {
202 : public:
203 15088 : ~SfxFoundCacheArr_Impl()
204 15088 : {
205 66590 : for(const_iterator it = begin(); it != end(); ++it)
206 51502 : delete *it;
207 15088 : }
208 : };
209 :
210 : //==========================================================================
211 :
212 1086 : SfxBindings::SfxBindings()
213 1086 : : pImp(new SfxBindings_Impl),
214 : pDispatcher(0),
215 2172 : nRegLevel(1) // first becomes 0, when the Dispatcher is set
216 : {
217 1086 : pImp->nMsgPos = 0;
218 1086 : pImp->bAllMsgDirty = sal_True;
219 1086 : pImp->bContextChanged = sal_False;
220 1086 : pImp->bMsgDirty = sal_True;
221 1086 : pImp->bAllDirty = sal_True;
222 1086 : pImp->ePopupAction = SFX_POPUP_DELETE;
223 1086 : pImp->nCachedFunc1 = 0;
224 1086 : pImp->nCachedFunc2 = 0;
225 1086 : pImp->bCtrlReleased = sal_False;
226 1086 : pImp->bFirstRound = sal_False;
227 1086 : pImp->bInNextJob = sal_False;
228 1086 : pImp->bInUpdate = sal_False;
229 1086 : pImp->pSubBindings = NULL;
230 1086 : pImp->pSuperBindings = NULL;
231 1086 : pImp->pWorkWin = NULL;
232 1086 : pImp->pUnoCtrlArr = NULL;
233 1086 : pImp->nOwnRegLevel = nRegLevel;
234 :
235 : // all caches are valid (no pending invalidate-job)
236 : // create the list of caches
237 1086 : pImp->pCaches = new SfxStateCacheArr_Impl;
238 1086 : pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob_Impl) );
239 1086 : }
240 :
241 : //====================================================================
242 :
243 3233 : SfxBindings::~SfxBindings()
244 :
245 : /* [Description]
246 :
247 : Destructor of the SfxBindings class. The one, for each <SfxApplication>
248 : existing Instance is automatically destroyed by the <SfxApplication>
249 : after the execution of <SfxApplication::Exit()>.
250 :
251 : The still existing <SfxControllerItem> instances, which are registered
252 : by the SfxBindings instance, are automatically destroyed in the Destructor.
253 : These are usually the Floating-Toolboxen, Value-Sets
254 : etc. Arrays of SfxControllerItems may at this time no longer exist.
255 : */
256 :
257 : {
258 : // The SubBindings should not be locked!
259 1079 : pImp->pSubBindings = NULL;
260 :
261 1079 : ENTERREGISTRATIONS();
262 :
263 1079 : pImp->aTimer.Stop();
264 1079 : DeleteControllers_Impl();
265 :
266 : // Delete Caches
267 1079 : for(SfxStateCacheArr_Impl::const_iterator it = pImp->pCaches->begin(); it != pImp->pCaches->end(); ++it)
268 0 : delete *it;
269 :
270 1079 : DELETEZ( pImp->pWorkWin );
271 :
272 1079 : delete pImp->pCaches;
273 1079 : delete pImp;
274 2154 : }
275 :
276 : //--------------------------------------------------------------------
277 :
278 1079 : void SfxBindings::DeleteControllers_Impl()
279 : {
280 : // in the first round delete SfxPopupWindows
281 1079 : sal_uInt16 nCount = pImp->pCaches->size();
282 : sal_uInt16 nCache;
283 62245 : for ( nCache = 0; nCache < nCount; ++nCache )
284 : {
285 : // Remember were you are
286 61166 : SfxStateCache *pCache = (*pImp->pCaches)[nCache];
287 61166 : sal_uInt16 nSlotId = pCache->GetId();
288 :
289 : // Delete SfxPopupWindow
290 61166 : pCache->DeleteFloatingWindows();
291 :
292 : // Re-align, because the cache may have been reduced
293 61166 : sal_uInt16 nNewCount = pImp->pCaches->size();
294 61166 : if ( nNewCount < nCount )
295 : {
296 0 : nCache = GetSlotPos(nSlotId);
297 0 : if ( nCache >= nNewCount ||
298 0 : nSlotId != (*pImp->pCaches)[nCache]->GetId() )
299 0 : --nCache;
300 0 : nCount = nNewCount;
301 : }
302 : }
303 :
304 : // Delete all Caches
305 62245 : for ( nCache = pImp->pCaches->size(); nCache > 0; --nCache )
306 : {
307 : // Get Cache via ::com::sun::star::sdbcx::Index
308 61166 : SfxStateCache *pCache = (*pImp->pCaches)[ nCache-1 ];
309 :
310 : // unbind all controllers in the cache
311 : SfxControllerItem *pNext;
312 61166 : for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
313 : pCtrl; pCtrl = pNext )
314 : {
315 0 : pNext = pCtrl->GetItemLink();
316 0 : pCtrl->UnBind();
317 : }
318 :
319 61166 : if ( pCache->GetInternalController() )
320 55332 : pCache->GetInternalController()->UnBind();
321 :
322 : // Delete Cache
323 61166 : if( nCache-1 < (sal_uInt16) pImp->pCaches->size() )
324 61166 : delete (*pImp->pCaches)[nCache-1];
325 61166 : pImp->pCaches->erase(pImp->pCaches->begin()+ nCache - 1);
326 : }
327 :
328 1079 : if( pImp->pUnoCtrlArr )
329 : {
330 0 : sal_uInt16 nCtrlCount = pImp->pUnoCtrlArr->size();
331 0 : for ( sal_uInt16 n=nCtrlCount; n>0; n-- )
332 : {
333 0 : SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
334 0 : pCtrl->ReleaseBindings();
335 : }
336 :
337 : DBG_ASSERT( !pImp->pUnoCtrlArr->size(), "Do not remove UnoControllerItems!" );
338 0 : DELETEZ( pImp->pUnoCtrlArr );
339 : }
340 1079 : }
341 :
342 : //--------------------------------------------------------------------
343 :
344 2 : void SfxBindings::HidePopups( bool bHide )
345 : {
346 : // Hide SfxPopupWindows
347 2 : HidePopupCtrls_Impl( bHide );
348 2 : SfxBindings *pSub = pImp->pSubBindings;
349 4 : while ( pSub )
350 : {
351 0 : pImp->pSubBindings->HidePopupCtrls_Impl( bHide );
352 0 : pSub = pSub->pImp->pSubBindings;
353 : }
354 :
355 : // Hide SfxChildWindows
356 : DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" );
357 2 : if ( pImp->pWorkWin )
358 2 : pImp->pWorkWin->HidePopups_Impl( bHide, sal_True );
359 2 : }
360 :
361 2130 : void SfxBindings::HidePopupCtrls_Impl( bool bHide )
362 : {
363 2130 : if ( bHide )
364 : {
365 : // Hide SfxPopupWindows
366 1064 : pImp->ePopupAction = SFX_POPUP_HIDE;
367 : }
368 : else
369 : {
370 : // Show SfxPopupWindows
371 1066 : pImp->ePopupAction = SFX_POPUP_SHOW;
372 : }
373 :
374 86540 : for(SfxStateCacheArr_Impl::const_iterator it = pImp->pCaches->begin(); it != pImp->pCaches->end(); ++it)
375 84410 : (*it)->DeleteFloatingWindows();
376 2130 : pImp->ePopupAction = SFX_POPUP_DELETE;
377 2130 : }
378 :
379 : //--------------------------------------------------------------------
380 :
381 15088 : void SfxBindings::Update_Impl
382 : (
383 : SfxStateCache* pCache // The up to date SfxStatusCache
384 : )
385 : {
386 15088 : if( pCache->GetDispatch().is() && pCache->GetItemLink() )
387 : {
388 0 : pCache->SetCachedState(sal_True);
389 0 : if ( !pCache->GetInternalController() )
390 0 : return;
391 : }
392 :
393 15088 : if ( !pDispatcher )
394 0 : return;
395 : DBG_PROFSTART(SfxBindingsUpdate_Impl);
396 :
397 : // gather together all with the same status method which are dirty
398 15088 : SfxDispatcher &rDispat = *pDispatcher;
399 15088 : const SfxSlot *pRealSlot = 0;
400 15088 : const SfxSlotServer* pMsgServer = 0;
401 15088 : SfxFoundCacheArr_Impl aFound;
402 15088 : SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound );
403 15088 : sal_Bool bUpdated = sal_False;
404 15088 : if ( pSet )
405 : {
406 : // Query Status
407 14614 : if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) )
408 : {
409 : // Post Status
410 : const SfxInterface *pInterface =
411 14614 : rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface();
412 66116 : for ( sal_uInt16 nPos = 0; nPos < aFound.size(); ++nPos )
413 : {
414 51502 : const SfxFoundCache_Impl *pFound = aFound[nPos];
415 51502 : sal_uInt16 nWhich = pFound->nWhichId;
416 51502 : const SfxPoolItem *pItem = 0;
417 51502 : SfxItemState eState = pSet->GetItemState(nWhich, sal_True, &pItem);
418 51502 : if ( eState == SFX_ITEM_DEFAULT && SfxItemPool::IsWhich(nWhich) )
419 337 : pItem = &pSet->Get(nWhich);
420 51502 : UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState );
421 : }
422 14614 : bUpdated = sal_True;
423 : }
424 :
425 14614 : delete pSet;
426 : }
427 :
428 15088 : if ( !bUpdated && pCache )
429 : {
430 : // When pCache == NULL and no SlotServer
431 : // (for example due to locked Dispatcher! ),
432 : // obviously do not try to update
433 : SfxFoundCache_Impl aFoundCache(
434 474 : pCache->GetId(), 0,
435 948 : pRealSlot, pCache );
436 474 : UpdateControllers_Impl( 0, &aFoundCache, 0, SFX_ITEM_DISABLED);
437 : }
438 :
439 15088 : DBG_PROFSTOP(SfxBindingsUpdate_Impl);
440 : }
441 :
442 : //--------------------------------------------------------------------
443 :
444 1169 : void SfxBindings::InvalidateSlotsInMap_Impl()
445 : {
446 1169 : InvalidateSlotMap::const_iterator pIter = pImp->m_aInvalidateSlots.begin();
447 2349 : while ( pIter != pImp->m_aInvalidateSlots.end() )
448 : {
449 11 : Invalidate( pIter->first );
450 11 : ++pIter;
451 : }
452 1169 : pImp->m_aInvalidateSlots.clear();
453 1169 : }
454 :
455 : //--------------------------------------------------------------------
456 :
457 11 : void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( sal_uInt16 nId )
458 : {
459 11 : pImp->m_aInvalidateSlots[nId] = sal_True;
460 11 : }
461 :
462 : //--------------------------------------------------------------------
463 :
464 1198 : void SfxBindings::Update
465 : (
466 : sal_uInt16 nId // the bound and up-to-date Slot-Id
467 : )
468 : {
469 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
470 :
471 1198 : if ( pDispatcher )
472 1198 : pDispatcher->Flush();
473 :
474 1198 : if ( pImp->pSubBindings )
475 0 : pImp->pSubBindings->Update( nId );
476 :
477 1198 : SfxStateCache* pCache = GetStateCache( nId );
478 1198 : if ( pCache )
479 : {
480 1169 : pImp->bInUpdate = sal_True;
481 1169 : if ( pImp->bMsgDirty )
482 : {
483 212 : UpdateSlotServer_Impl();
484 212 : pCache = GetStateCache( nId );
485 : }
486 :
487 1169 : if (pCache)
488 : {
489 1169 : sal_Bool bInternalUpdate = sal_True;
490 1169 : if( pCache->GetDispatch().is() && pCache->GetItemLink() )
491 : {
492 0 : pCache->SetCachedState(sal_True);
493 0 : bInternalUpdate = ( pCache->GetInternalController() != 0 );
494 : }
495 :
496 1169 : if ( bInternalUpdate )
497 : {
498 : // Query Status
499 1169 : const SfxSlotServer* pMsgServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
500 1398 : if ( !pCache->IsControllerDirty() &&
501 229 : ( !pMsgServer ||
502 229 : !pMsgServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) )
503 : {
504 229 : pImp->bInUpdate = sal_False;
505 229 : InvalidateSlotsInMap_Impl();
506 229 : return;
507 : }
508 940 : if (!pMsgServer)
509 : {
510 354 : pCache->SetState(SFX_ITEM_DISABLED, 0);
511 354 : pImp->bInUpdate = sal_False;
512 354 : InvalidateSlotsInMap_Impl();
513 354 : return;
514 : }
515 :
516 586 : Update_Impl(pCache);
517 : }
518 :
519 586 : pImp->bAllDirty = sal_False;
520 : }
521 :
522 586 : pImp->bInUpdate = sal_False;
523 586 : InvalidateSlotsInMap_Impl();
524 : }
525 : }
526 :
527 : //--------------------------------------------------------------------
528 :
529 0 : void SfxBindings::Update()
530 : {
531 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
532 :
533 0 : if ( pImp->pSubBindings )
534 0 : pImp->pSubBindings->Update();
535 :
536 0 : if ( pDispatcher )
537 : {
538 0 : if ( nRegLevel )
539 0 : return;
540 :
541 0 : pImp->bInUpdate = sal_True;
542 0 : pDispatcher->Flush();
543 0 : pDispatcher->Update_Impl();
544 0 : while ( !NextJob_Impl(0) )
545 : ; // loop
546 0 : pImp->bInUpdate = sal_False;
547 0 : InvalidateSlotsInMap_Impl();
548 : }
549 : }
550 :
551 : //--------------------------------------------------------------------
552 :
553 0 : void SfxBindings::SetState
554 : (
555 : const SfxItemSet& rSet // status values to be set
556 : )
557 : {
558 : // when locked then only invalidate
559 0 : if ( nRegLevel )
560 : {
561 0 : SfxItemIter aIter(rSet);
562 0 : for ( const SfxPoolItem *pItem = aIter.FirstItem();
563 : pItem;
564 : pItem = aIter.NextItem() )
565 0 : Invalidate( pItem->Which() );
566 : }
567 : else
568 : {
569 : // Status may be accepted only if all slot-pointers are set
570 0 : if ( pImp->bMsgDirty )
571 0 : UpdateSlotServer_Impl();
572 :
573 : // Iterate over the itemset, update if the slot bound
574 : //! Bug: Use WhichIter and possibly send VoidItems up
575 0 : SfxItemIter aIter(rSet);
576 0 : for ( const SfxPoolItem *pItem = aIter.FirstItem();
577 : pItem;
578 : pItem = aIter.NextItem() )
579 : {
580 : SfxStateCache* pCache =
581 0 : GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) );
582 0 : if ( pCache )
583 : {
584 : // Update status
585 0 : if ( !pCache->IsControllerDirty() )
586 0 : pCache->Invalidate(sal_False);
587 0 : pCache->SetState( SFX_ITEM_AVAILABLE, pItem );
588 :
589 : //! Not implemented: Updates from EnumSlots via master slots
590 : }
591 0 : }
592 : }
593 0 : }
594 :
595 : //--------------------------------------------------------------------
596 :
597 79 : void SfxBindings::SetState
598 : (
599 : const SfxPoolItem& rItem // Status value to be set
600 : )
601 : {
602 79 : if ( nRegLevel )
603 : {
604 1 : Invalidate( rItem.Which() );
605 : }
606 : else
607 : {
608 : // Status may be accepted only if all slot-pointers are set
609 78 : if ( pImp->bMsgDirty )
610 28 : UpdateSlotServer_Impl();
611 :
612 : //update if the slot bound
613 : DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
614 : "cannot set items with which-id" );
615 78 : SfxStateCache* pCache = GetStateCache( rItem.Which() );
616 78 : if ( pCache )
617 : {
618 : // Update Status
619 52 : if ( !pCache->IsControllerDirty() )
620 13 : pCache->Invalidate(sal_False);
621 52 : pCache->SetState( SFX_ITEM_AVAILABLE, &rItem );
622 :
623 : //! Not implemented: Updates from EnumSlots via master slots
624 : }
625 : }
626 79 : }
627 :
628 :
629 : //--------------------------------------------------------------------
630 :
631 0 : SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId )
632 : {
633 0 : SfxStateCache* pCache = GetStateCache( nId );
634 0 : if ( !pCache && pImp->pSubBindings )
635 0 : return pImp->pSubBindings->GetAnyStateCache_Impl( nId );
636 0 : return pCache;
637 : }
638 :
639 230014 : SfxStateCache* SfxBindings::GetStateCache
640 : (
641 : sal_uInt16 nId /* Slot-Id, which SfxStatusCache is to be found */
642 : )
643 : {
644 230014 : return GetStateCache(nId, 0);
645 : }
646 :
647 519142 : SfxStateCache* SfxBindings::GetStateCache
648 : (
649 : sal_uInt16 nId, /* Slot-Id, which SfxStatusCache is to be found */
650 : sal_uInt16* pPos /* NULL for instance the position from which the
651 : bindings are to be searched binary. Returns the
652 : position back for where the nId was found,
653 : or where it was inserted. */
654 : )
655 : {
656 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
657 : // is the specified function bound?
658 519142 : const sal_uInt16 nStart = ( pPos ? *pPos : 0 );
659 519142 : const sal_uInt16 nPos = GetSlotPos( nId, nStart );
660 :
661 1024600 : if ( nPos < pImp->pCaches->size() &&
662 505458 : (*pImp->pCaches)[nPos]->GetId() == nId )
663 : {
664 205500 : if ( pPos )
665 42185 : *pPos = nPos;
666 205500 : return (*pImp->pCaches)[nPos];
667 : }
668 313642 : return 0;
669 : }
670 :
671 : //--------------------------------------------------------------------
672 :
673 26248 : void SfxBindings::InvalidateAll
674 : (
675 : sal_Bool bWithMsg /* sal_True Mark Slot Server as invalid
676 : sal_False Slot Server remains valid */
677 : )
678 : {
679 : DBG_PROFSTART(SfxBindingsInvalidateAll);
680 : DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
681 :
682 26248 : if ( pImp->pSubBindings )
683 15 : pImp->pSubBindings->InvalidateAll( bWithMsg );
684 :
685 : // everything is already set dirty or downing => nothing to do
686 76591 : if ( !pDispatcher ||
687 50917 : ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) ||
688 1690 : SFX_APP()->IsDowning() )
689 : {
690 : DBG_PROFSTOP(SfxBindingsInvalidateAll);
691 50806 : return;
692 : }
693 :
694 1690 : pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg;
695 1690 : pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg;
696 1690 : pImp->bAllDirty = sal_True;
697 :
698 154776 : for ( sal_uInt16 n = 0; n < pImp->pCaches->size(); ++n )
699 153086 : (*pImp->pCaches)[n]->Invalidate(bWithMsg);
700 :
701 1690 : pImp->nMsgPos = 0;
702 1690 : if ( !nRegLevel )
703 : {
704 707 : pImp->aTimer.Stop();
705 707 : pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
706 707 : pImp->aTimer.Start();
707 : }
708 :
709 : DBG_PROFSTOP(SfxBindingsInvalidateAll);
710 : }
711 :
712 : //--------------------------------------------------------------------
713 :
714 5740 : void SfxBindings::Invalidate
715 : (
716 : const sal_uInt16* pIds /* numerically sorted NULL-terminated array of
717 : slot IDs (individual, not as a couple!) */
718 : )
719 : {
720 : DBG_PROFSTART(SfxBindingsInvalidateAll);
721 :
722 5740 : if ( pImp->bInUpdate )
723 : {
724 0 : sal_Int32 i = 0;
725 0 : while ( pIds[i] != 0 )
726 0 : AddSlotToInvalidateSlotsMap_Impl( pIds[i++] );
727 :
728 0 : if ( pImp->pSubBindings )
729 0 : pImp->pSubBindings->Invalidate( pIds );
730 0 : return;
731 : }
732 :
733 5740 : if ( pImp->pSubBindings )
734 0 : pImp->pSubBindings->Invalidate( pIds );
735 :
736 : // everything is already set dirty or downing => nothing to do
737 5740 : if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
738 5616 : return;
739 :
740 : // Search binary in always smaller areas
741 3322 : for ( sal_uInt16 n = GetSlotPos(*pIds);
742 1661 : *pIds && n < pImp->pCaches->size();
743 1537 : n = GetSlotPos(*pIds, n) )
744 : {
745 : // If SID is ever bound, then invalidate the cache
746 1661 : SfxStateCache *pCache = (*pImp->pCaches)[n];
747 1661 : if ( pCache->GetId() == *pIds )
748 1608 : pCache->Invalidate(sal_False);
749 :
750 : // Next SID
751 1661 : if ( !*++pIds )
752 124 : break;
753 : DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" );
754 : }
755 :
756 : // if not enticed to start update timer
757 124 : pImp->nMsgPos = 0;
758 124 : if ( !nRegLevel )
759 : {
760 123 : pImp->aTimer.Stop();
761 123 : pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
762 123 : pImp->aTimer.Start();
763 : }
764 :
765 : DBG_PROFSTOP(SfxBindingsInvalidateAll);
766 : }
767 :
768 : //--------------------------------------------------------------------
769 :
770 390 : void SfxBindings::InvalidateShell
771 : (
772 : const SfxShell& rSh, /* <SfxShell>, which Slot-Ids should be
773 : invalidated */
774 : sal_Bool bDeep /* sal_True
775 : also inherited slot IDs of SfxShell are invalidert
776 :
777 : sal_False
778 : the inherited and not overloaded Slot-Ids were
779 : invalidiert */
780 : // for now always bDeep
781 : )
782 : {
783 : DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
784 :
785 390 : if ( pImp->pSubBindings )
786 0 : pImp->pSubBindings->InvalidateShell( rSh, bDeep );
787 :
788 390 : if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
789 279 : return;
790 :
791 : DBG_PROFSTART(SfxBindingsInvalidateAll);
792 :
793 : // flush now already, it is done in GetShellLevel (rsh) anyway,
794 : // important so that is set correctly: pimp-> ball(Msg)Dirty
795 111 : pDispatcher->Flush();
796 :
797 333 : if ( !pDispatcher ||
798 222 : ( pImp->bAllDirty && pImp->bAllMsgDirty ) ||
799 111 : SFX_APP()->IsDowning() )
800 : {
801 : // if the next one is anyway, then all the servers are collected
802 0 : return;
803 : }
804 :
805 : // Find Level
806 111 : sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh);
807 111 : if ( nLevel != USHRT_MAX )
808 : {
809 10303 : for ( sal_uInt16 n = 0; n < pImp->pCaches->size(); ++n )
810 : {
811 10192 : SfxStateCache *pCache = (*pImp->pCaches)[n];
812 : const SfxSlotServer *pMsgServer =
813 10192 : pCache->GetSlotServer(*pDispatcher, pImp->xProv);
814 10192 : if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel )
815 8008 : pCache->Invalidate(sal_False);
816 : }
817 111 : pImp->nMsgPos = 0;
818 111 : if ( !nRegLevel )
819 : {
820 111 : pImp->aTimer.Stop();
821 111 : pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
822 111 : pImp->aTimer.Start();
823 111 : pImp->bFirstRound = sal_True;
824 111 : pImp->nFirstShell = nLevel;
825 : }
826 : }
827 :
828 : DBG_PROFSTOP(SfxBindingsInvalidateAll);
829 : }
830 :
831 : //--------------------------------------------------------------------
832 :
833 174412 : void SfxBindings::Invalidate
834 : (
835 : sal_uInt16 nId // Status value to be set
836 : )
837 : {
838 174412 : if ( pImp->bInUpdate )
839 : {
840 11 : AddSlotToInvalidateSlotsMap_Impl( nId );
841 11 : if ( pImp->pSubBindings )
842 0 : pImp->pSubBindings->Invalidate( nId );
843 11 : return;
844 : }
845 :
846 174401 : if ( pImp->pSubBindings )
847 56 : pImp->pSubBindings->Invalidate( nId );
848 :
849 174401 : if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
850 148805 : return;
851 :
852 25596 : SfxStateCache* pCache = GetStateCache(nId);
853 25596 : if ( pCache )
854 : {
855 13472 : pCache->Invalidate(sal_False);
856 13472 : pImp->nMsgPos = std::min(GetSlotPos(nId), pImp->nMsgPos);
857 13472 : if ( !nRegLevel )
858 : {
859 13324 : pImp->aTimer.Stop();
860 13324 : pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
861 13324 : pImp->aTimer.Start();
862 : }
863 : }
864 : }
865 :
866 : //--------------------------------------------------------------------
867 :
868 2294 : void SfxBindings::Invalidate
869 : (
870 : sal_uInt16 nId, // Status value to be set
871 : sal_Bool bWithItem, // Clear StateCache?
872 : sal_Bool bWithMsg // Get new SlotServer?
873 : )
874 : {
875 : DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
876 :
877 2294 : if ( pImp->pSubBindings )
878 0 : pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
879 :
880 2294 : if ( SFX_APP()->IsDowning() )
881 0 : return;
882 :
883 2294 : SfxStateCache* pCache = GetStateCache(nId);
884 2294 : if ( pCache )
885 : {
886 610 : if ( bWithItem )
887 610 : pCache->ClearCache();
888 610 : pCache->Invalidate(bWithMsg);
889 :
890 610 : if ( !pDispatcher || pImp->bAllDirty )
891 0 : return;
892 :
893 610 : pImp->nMsgPos = std::min(GetSlotPos(nId), pImp->nMsgPos);
894 610 : if ( !nRegLevel )
895 : {
896 10 : pImp->aTimer.Stop();
897 10 : pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
898 10 : pImp->aTimer.Start();
899 : }
900 : }
901 : }
902 :
903 : //--------------------------------------------------------------------
904 :
905 0 : sal_Bool SfxBindings::IsBound( sal_uInt16 nSlotId, sal_uInt16 nStartSearchAt )
906 : {
907 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
908 0 : return GetStateCache(nSlotId, &nStartSearchAt ) != 0;
909 : }
910 :
911 : //--------------------------------------------------------------------
912 :
913 711895 : sal_uInt16 SfxBindings::GetSlotPos( sal_uInt16 nId, sal_uInt16 nStartSearchAt )
914 : {
915 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
916 : DBG_PROFSTART(SfxBindingsMsgPos);
917 :
918 : // answer immediately if a function-seek comes repeated
919 1355562 : if ( pImp->nCachedFunc1 < pImp->pCaches->size() &&
920 643667 : (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId )
921 : {
922 : DBG_PROFSTOP(SfxBindingsMsgPos);
923 90992 : return pImp->nCachedFunc1;
924 : }
925 1176154 : if ( pImp->nCachedFunc2 < pImp->pCaches->size() &&
926 555251 : (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId )
927 : {
928 : // swap the caches
929 9913 : sal_uInt16 nTemp = pImp->nCachedFunc1;
930 9913 : pImp->nCachedFunc1 = pImp->nCachedFunc2;
931 9913 : pImp->nCachedFunc2 = nTemp;
932 : DBG_PROFSTOP(SfxBindingsMsgPos);
933 9913 : return pImp->nCachedFunc1;
934 : }
935 :
936 : // binary search, if not found, seek to target-position
937 610990 : if ( pImp->pCaches->size() <= nStartSearchAt )
938 : {
939 : DBG_PROFSTOP(SfxBindingsMsgPos);
940 3324 : return 0;
941 : }
942 607666 : if ( (sal_uInt16) pImp->pCaches->size() == (nStartSearchAt+1) )
943 : {
944 : DBG_PROFSTOP(SfxBindingsMsgPos);
945 5103 : return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1;
946 : }
947 602563 : sal_uInt16 nLow = nStartSearchAt;
948 602563 : sal_uInt16 nMid = 0;
949 602563 : sal_uInt16 nHigh = 0;
950 602563 : sal_Bool bFound = sal_False;
951 602563 : nHigh = pImp->pCaches->size() - 1;
952 4459213 : while ( !bFound && nLow <= nHigh )
953 : {
954 3260707 : nMid = (nLow + nHigh) >> 1;
955 : DBG_ASSERT( nMid < pImp->pCaches->size(), "bsearch is buggy" );
956 3260707 : int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() );
957 3260707 : if ( nDiff < 0)
958 1359963 : { if ( nMid == 0 )
959 6620 : break;
960 1353343 : nHigh = nMid - 1;
961 : }
962 1900744 : else if ( nDiff > 0 )
963 1677281 : { nLow = nMid + 1;
964 1677281 : if ( nLow == 0 )
965 0 : break;
966 : }
967 : else
968 223463 : bFound = sal_True;
969 : }
970 602563 : sal_uInt16 nPos = bFound ? nMid : nLow;
971 : DBG_ASSERT( nPos <= pImp->pCaches->size(), "" );
972 : DBG_ASSERT( nPos == pImp->pCaches->size() ||
973 : nId <= (*pImp->pCaches)[nPos]->GetId(), "" );
974 : DBG_ASSERT( nPos == nStartSearchAt ||
975 : nId > (*pImp->pCaches)[nPos-1]->GetId(), "" );
976 : DBG_ASSERT( ( (nPos+1) >= (sal_uInt16) pImp->pCaches->size() ) ||
977 : nId < (*pImp->pCaches)[nPos+1]->GetId(), "" );
978 602563 : pImp->nCachedFunc2 = pImp->nCachedFunc1;
979 602563 : pImp->nCachedFunc1 = nPos;
980 : DBG_PROFSTOP(SfxBindingsMsgPos);
981 602563 : return nPos;
982 : }
983 : //--------------------------------------------------------------------
984 55332 : void SfxBindings::RegisterInternal_Impl( SfxControllerItem& rItem )
985 : {
986 55332 : Register_Impl( rItem, sal_True );
987 :
988 55332 : }
989 :
990 33175 : void SfxBindings::Register( SfxControllerItem& rItem )
991 : {
992 33175 : Register_Impl( rItem, sal_False );
993 33175 : }
994 :
995 88507 : void SfxBindings::Register_Impl( SfxControllerItem& rItem, sal_Bool bInternal )
996 : {
997 : // DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
998 : DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" );
999 :
1000 : // insert new cache if it does not already exist
1001 88507 : sal_uInt16 nId = rItem.GetId();
1002 88507 : sal_uInt16 nPos = GetSlotPos(nId);
1003 166172 : if ( nPos >= pImp->pCaches->size() ||
1004 77665 : (*pImp->pCaches)[nPos]->GetId() != nId )
1005 : {
1006 73195 : SfxStateCache* pCache = new SfxStateCache(nId);
1007 73195 : pImp->pCaches->insert( pImp->pCaches->begin() + nPos, pCache );
1008 : DBG_ASSERT( nPos == 0 ||
1009 : (*pImp->pCaches)[nPos]->GetId() >
1010 : (*pImp->pCaches)[nPos-1]->GetId(), "" );
1011 : DBG_ASSERT( (nPos == pImp->pCaches->size()-1) ||
1012 : (*pImp->pCaches)[nPos]->GetId() <
1013 : (*pImp->pCaches)[nPos+1]->GetId(), "" );
1014 73195 : pImp->bMsgDirty = sal_True;
1015 : }
1016 :
1017 : // enqueue the new binding
1018 88507 : if ( bInternal )
1019 : {
1020 55332 : (*pImp->pCaches)[nPos]->SetInternalController( &rItem );
1021 : }
1022 : else
1023 : {
1024 33175 : SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem);
1025 33175 : rItem.ChangeItemLink(pOldItem);
1026 : }
1027 88507 : }
1028 :
1029 : //--------------------------------------------------------------------
1030 :
1031 88503 : void SfxBindings::Release( SfxControllerItem& rItem )
1032 : {
1033 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1034 : DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" );
1035 88503 : ENTERREGISTRATIONS();
1036 :
1037 : // find the bound function
1038 88503 : sal_uInt16 nId = rItem.GetId();
1039 88503 : sal_uInt16 nPos = GetSlotPos(nId);
1040 88503 : SfxStateCache* pCache = (*pImp->pCaches)[nPos];
1041 88503 : if ( pCache->GetId() == nId )
1042 : {
1043 88503 : if ( pCache->GetInternalController() == &rItem )
1044 : {
1045 55332 : pCache->ReleaseInternalController();
1046 : }
1047 : else
1048 : {
1049 : // is this the first binding in the list?
1050 33171 : SfxControllerItem* pItem = pCache->GetItemLink();
1051 33171 : if ( pItem == &rItem )
1052 28922 : pCache->ChangeItemLink( rItem.GetItemLink() );
1053 : else
1054 : {
1055 : // search the binding in the list
1056 8498 : while ( pItem && pItem->GetItemLink() != &rItem )
1057 0 : pItem = pItem->GetItemLink();
1058 :
1059 : // unlink it if it was found
1060 4249 : if ( pItem )
1061 4249 : pItem->ChangeItemLink( rItem.GetItemLink() );
1062 : }
1063 : }
1064 :
1065 : // was this the last controller?
1066 88503 : if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
1067 : {
1068 73191 : pImp->bCtrlReleased = sal_True;
1069 : }
1070 : }
1071 :
1072 88503 : LEAVEREGISTRATIONS();
1073 88503 : }
1074 :
1075 : //--------------------------------------------------------------------
1076 0 : const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi,
1077 : const SfxPoolItem **ppInternalArgs )
1078 : {
1079 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1080 :
1081 0 : if( !nId || !pDispatcher )
1082 0 : return NULL;
1083 :
1084 0 : return Execute_Impl( nId, ppItems, nModi, SFX_CALLMODE_SYNCHRON, ppInternalArgs );
1085 : }
1086 :
1087 0 : sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
1088 : const SfxPoolItem **ppInternalArgs )
1089 : {
1090 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1091 :
1092 0 : if( !nId || !pDispatcher )
1093 0 : return sal_False;
1094 :
1095 0 : const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs );
1096 0 : return ( pRet != 0 );
1097 : }
1098 :
1099 0 : const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
1100 : const SfxPoolItem **ppInternalArgs, sal_Bool bGlobalOnly )
1101 : {
1102 0 : SfxStateCache *pCache = GetStateCache( nId );
1103 0 : if ( !pCache )
1104 : {
1105 0 : SfxBindings *pBind = pImp->pSubBindings;
1106 0 : while ( pBind )
1107 : {
1108 0 : if ( pBind->GetStateCache( nId ) )
1109 0 : return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly );
1110 0 : pBind = pBind->pImp->pSubBindings;
1111 : };
1112 : }
1113 :
1114 0 : SfxDispatcher &rDispatcher = *pDispatcher;
1115 0 : rDispatcher.Flush();
1116 0 : rDispatcher.GetFrame(); // -Wall is this required???
1117 :
1118 : // get SlotServer (Slot+ShellLevel) and Shell from cache
1119 0 : ::boost::scoped_ptr<SfxStateCache> xCache;
1120 0 : if ( !pCache )
1121 : {
1122 : // Execution of non cached slots (Accelerators don't use Controllers)
1123 : // slot is uncached, use SlotCache to handle external dispatch providers
1124 0 : xCache.reset(new SfxStateCache(nId));
1125 0 : pCache = xCache.get();
1126 0 : pCache->GetSlotServer( rDispatcher, pImp->xProv );
1127 : }
1128 :
1129 0 : if ( pCache && pCache->GetDispatch().is() )
1130 : {
1131 : DBG_ASSERT( !ppInternalArgs, "Internal args get lost when dispatched!" );
1132 :
1133 0 : SfxItemPool &rPool = GetDispatcher()->GetFrame()->GetObjectShell()->GetPool();
1134 0 : SfxRequest aReq( nId, nCallMode, rPool );
1135 0 : aReq.SetModifier( nModi );
1136 0 : if( ppItems )
1137 0 : while( *ppItems )
1138 0 : aReq.AppendItem( **ppItems++ );
1139 :
1140 : // cache binds to an external dispatch provider
1141 0 : pCache->Dispatch( aReq.GetArgs(), nCallMode == SFX_CALLMODE_SYNCHRON );
1142 0 : SfxPoolItem *pVoid = new SfxVoidItem( nId );
1143 0 : DeleteItemOnIdle( pVoid );
1144 0 : return pVoid;
1145 : }
1146 :
1147 : // slot is handled internally by SfxDispatcher
1148 0 : if ( pImp->bMsgDirty )
1149 0 : UpdateSlotServer_Impl();
1150 :
1151 0 : SfxShell *pShell=0;
1152 0 : const SfxSlot *pSlot=0;
1153 :
1154 : // if slot was uncached, we should have created a cache in this method!
1155 : DBG_ASSERT( pCache, "This code needs a cache!");
1156 0 : const SfxSlotServer* pServer = pCache ? pCache->GetSlotServer( rDispatcher, pImp->xProv ) : 0;
1157 0 : if ( !pServer )
1158 : {
1159 0 : return NULL;
1160 : }
1161 : else
1162 : {
1163 0 : pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
1164 0 : pSlot = pServer->GetSlot();
1165 : }
1166 :
1167 0 : if ( bGlobalOnly )
1168 0 : if ( !pShell->ISA(SfxModule) && !pShell->ISA(SfxApplication) && !pShell->ISA(SfxViewFrame) )
1169 0 : return NULL;
1170 :
1171 0 : SfxItemPool &rPool = pShell->GetPool();
1172 0 : SfxRequest aReq( nId, nCallMode, rPool );
1173 0 : aReq.SetModifier( nModi );
1174 0 : if( ppItems )
1175 0 : while( *ppItems )
1176 0 : aReq.AppendItem( **ppItems++ );
1177 0 : if ( ppInternalArgs )
1178 : {
1179 0 : SfxAllItemSet aSet( rPool );
1180 0 : for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
1181 0 : aSet.Put( **pArg );
1182 0 : aReq.SetInternalArgs_Impl( aSet );
1183 : }
1184 :
1185 0 : Execute_Impl( aReq, pSlot, pShell );
1186 :
1187 0 : const SfxPoolItem* pRet = aReq.GetReturnValue();
1188 0 : if ( !pRet )
1189 : {
1190 0 : SfxPoolItem *pVoid = new SfxVoidItem( nId );
1191 0 : DeleteItemOnIdle( pVoid );
1192 0 : pRet = pVoid;
1193 : }
1194 :
1195 0 : return pRet;
1196 : }
1197 :
1198 26 : void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell )
1199 : {
1200 26 : SfxItemPool &rPool = pShell->GetPool();
1201 :
1202 26 : if ( SFX_KIND_ENUM == pSlot->GetKind() )
1203 : {
1204 : // for Enum-Slots, the Master has to be excecuted with the value
1205 : // of the enums
1206 0 : const SfxSlot *pRealSlot = pShell->GetInterface()->GetRealSlot(pSlot);
1207 0 : const sal_uInt16 nSlotId = pRealSlot->GetSlotId();
1208 0 : aReq.SetSlot( nSlotId );
1209 0 : aReq.AppendItem( SfxAllEnumItem( rPool.GetWhich(nSlotId), pSlot->GetValue() ) );
1210 0 : pDispatcher->_Execute( *pShell, *pRealSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1211 : }
1212 26 : else if ( SFX_KIND_ATTR == pSlot->GetKind() )
1213 : {
1214 : // Which value has to be mapped for Attribute slots
1215 26 : const sal_uInt16 nSlotId = pSlot->GetSlotId();
1216 26 : aReq.SetSlot( nSlotId );
1217 26 : if ( pSlot->IsMode(SFX_SLOT_TOGGLE) )
1218 : {
1219 : // The value is attached to a toggleable attribute (Bools)
1220 10 : sal_uInt16 nWhich = pSlot->GetWhich(rPool);
1221 10 : SfxItemSet aSet(rPool, nWhich, nWhich);
1222 10 : SfxStateFunc aFunc = pSlot->GetStateFnc();
1223 10 : pShell->CallState( aFunc, aSet );
1224 : const SfxPoolItem *pOldItem;
1225 10 : SfxItemState eState = aSet.GetItemState(nWhich, sal_True, &pOldItem);
1226 10 : if ( eState == SFX_ITEM_DISABLED )
1227 26 : return;
1228 :
1229 10 : if ( SFX_ITEM_AVAILABLE == eState && SfxItemPool::IsWhich(nWhich) )
1230 0 : pOldItem = &aSet.Get(nWhich);
1231 :
1232 20 : if ( SFX_ITEM_SET == eState ||
1233 0 : ( SFX_ITEM_AVAILABLE == eState &&
1234 0 : SfxItemPool::IsWhich(nWhich) &&
1235 : pOldItem ) )
1236 : {
1237 10 : if ( pOldItem->ISA(SfxBoolItem) )
1238 : {
1239 : // we can toggle Bools
1240 10 : sal_Bool bOldValue = ((const SfxBoolItem *)pOldItem)->GetValue();
1241 10 : SfxBoolItem *pNewItem = (SfxBoolItem*) (pOldItem->Clone());
1242 10 : pNewItem->SetValue( !bOldValue );
1243 10 : aReq.AppendItem( *pNewItem );
1244 10 : delete pNewItem;
1245 : }
1246 0 : else if ( pOldItem->ISA(SfxEnumItemInterface) &&
1247 0 : ((SfxEnumItemInterface *)pOldItem)->HasBoolValue())
1248 : {
1249 : // and Enums with Bool-Interface
1250 : SfxEnumItemInterface *pNewItem =
1251 0 : (SfxEnumItemInterface*) (pOldItem->Clone());
1252 0 : pNewItem->SetBoolValue(!((SfxEnumItemInterface *)pOldItem)->GetBoolValue());
1253 0 : aReq.AppendItem( *pNewItem );
1254 0 : delete pNewItem;
1255 : }
1256 : else {
1257 : OSL_FAIL( "Toggle only for Enums and Bools allowed" );
1258 : }
1259 : }
1260 0 : else if ( SFX_ITEM_DONTCARE == eState )
1261 : {
1262 : // Create one Status-Item for each Factory
1263 0 : SfxPoolItem *pNewItem = pSlot->GetType()->CreateItem();
1264 : DBG_ASSERT( pNewItem, "Toggle to slot without ItemFactory" );
1265 0 : pNewItem->SetWhich( nWhich );
1266 :
1267 0 : if ( pNewItem->ISA(SfxBoolItem) )
1268 : {
1269 : // we can toggle Bools
1270 0 : ((SfxBoolItem*)pNewItem)->SetValue( sal_True );
1271 0 : aReq.AppendItem( *pNewItem );
1272 : }
1273 0 : else if ( pNewItem->ISA(SfxEnumItemInterface) &&
1274 0 : ((SfxEnumItemInterface *)pNewItem)->HasBoolValue())
1275 : {
1276 : // and Enums with Bool-Interface
1277 0 : ((SfxEnumItemInterface*)pNewItem)->SetBoolValue(sal_True);
1278 0 : aReq.AppendItem( *pNewItem );
1279 : }
1280 : else {
1281 : OSL_FAIL( "Toggle only for Enums and Bools allowed" );
1282 : }
1283 0 : delete pNewItem;
1284 : }
1285 : else {
1286 : OSL_FAIL( "suspicious Toggle-Slot" );
1287 10 : }
1288 : }
1289 :
1290 26 : pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1291 : }
1292 : else
1293 0 : pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1294 : }
1295 :
1296 : //--------------------------------------------------------------------
1297 :
1298 1235 : void SfxBindings::UpdateSlotServer_Impl()
1299 : {
1300 : DBG_PROFSTART(SfxBindingsUpdateServers);
1301 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1302 :
1303 : // synchronize
1304 1235 : pDispatcher->Flush();
1305 :
1306 1235 : if ( pImp->bAllMsgDirty )
1307 : {
1308 688 : if ( !nRegLevel )
1309 : {
1310 : ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
1311 628 : ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1312 628 : pImp->bContextChanged = sal_False;
1313 : }
1314 : else
1315 60 : pImp->bContextChanged = sal_True;
1316 : }
1317 :
1318 82744 : for (size_t i = 0, nCount = pImp->pCaches->size(); i < nCount; ++i)
1319 : {
1320 81509 : SfxStateCache *pCache = (*pImp->pCaches)[i];
1321 : //GetSlotServer can modify pImp->pCaches
1322 81509 : pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1323 : }
1324 1235 : pImp->bMsgDirty = pImp->bAllMsgDirty = sal_False;
1325 :
1326 1235 : Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) );
1327 :
1328 : DBG_PROFSTOP(SfxBindingsUpdateServers);
1329 1235 : }
1330 :
1331 : //--------------------------------------------------------------------
1332 :
1333 15088 : SfxItemSet* SfxBindings::CreateSet_Impl
1334 : (
1335 : SfxStateCache*& pCache, // in: Status-Cache from nId
1336 : const SfxSlot*& pRealSlot, // out: RealSlot to nId
1337 : const SfxSlotServer** pMsgServer, // out: Slot-Server to nId
1338 : SfxFoundCacheArr_Impl& rFound // out: List of Caches for Siblings
1339 : )
1340 : {
1341 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1342 :
1343 : DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl with dirty MessageServer" );
1344 :
1345 15088 : const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1346 15088 : if(!pMsgSvr || !pDispatcher)
1347 474 : return 0;
1348 :
1349 : DBG_PROFSTART(SfxBindingsCreateSet);
1350 14614 : pRealSlot = 0;
1351 14614 : *pMsgServer = pMsgSvr;
1352 :
1353 14614 : sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
1354 14614 : SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
1355 14614 : if ( !pShell ) // rare GPF when browsing through update from Inet-Notify
1356 0 : return 0;
1357 :
1358 14614 : SfxItemPool &rPool = pShell->GetPool();
1359 :
1360 : // get the status method, which is served by the pCache
1361 14614 : SfxStateFunc pFnc = 0;
1362 14614 : const SfxInterface *pInterface = pShell->GetInterface();
1363 14614 : if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() )
1364 : {
1365 0 : pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot());
1366 0 : pCache = GetStateCache( pRealSlot->GetSlotId() );
1367 : }
1368 : else
1369 14614 : pRealSlot = pMsgSvr->GetSlot();
1370 :
1371 : // Note: pCache can be NULL!
1372 :
1373 14614 : pFnc = pRealSlot->GetStateFnc();
1374 :
1375 : // the RealSlot is always on
1376 : SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
1377 14614 : pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache );
1378 14614 : rFound.push_back( pFound );
1379 :
1380 14614 : sal_uInt16 nSlot = pRealSlot->GetSlotId();
1381 14614 : if ( !(nSlot >= SID_VERB_START && nSlot <= SID_VERB_END) )
1382 : {
1383 14614 : pInterface = pInterface->GetRealInterfaceForSlot( pRealSlot );
1384 : DBG_ASSERT (pInterface,"Slot in the given shell is not found");
1385 : }
1386 :
1387 : // Search through the bindings for slots served by the same function. This , // will only affect slots which are present in the found interface.
1388 :
1389 : // The position of the Statecaches in StateCache-Array
1390 14614 : sal_uInt16 nCachePos = pImp->nMsgPos;
1391 14614 : const SfxSlot *pSibling = pRealSlot->GetNextSlot();
1392 :
1393 : // the Slots ODF a interfaces ar linked in a circle
1394 318356 : while ( pSibling > pRealSlot )
1395 : {
1396 289128 : SfxStateFunc pSiblingFnc=0;
1397 : SfxStateCache *pSiblingCache =
1398 289128 : GetStateCache( pSibling->GetSlotId(), &nCachePos );
1399 :
1400 : // Is the slot cached ?
1401 289128 : if ( pSiblingCache )
1402 : {
1403 42185 : const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv);
1404 42185 : if ( pServ && pServ->GetShellLevel() == nShellLevel )
1405 38245 : pSiblingFnc = pServ->GetSlot()->GetStateFnc();
1406 : }
1407 :
1408 : // Does the slot have to be updated at all?
1409 289128 : bool bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
1410 :
1411 : // It is not enough to ask for the same shell!!
1412 289128 : bool bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
1413 :
1414 : // If the slot is a non-dirty master slot, then maybe one of his slaves
1415 : // is dirty? Then the master slot is still inserted.
1416 289128 : if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() )
1417 : {
1418 : // Also check slave slots for Binding
1419 0 : const SfxSlot* pFirstSlave = pSibling->GetLinkedSlot();
1420 0 : for ( const SfxSlot *pSlaveSlot = pFirstSlave;
1421 0 : !bInsert;
1422 : pSlaveSlot = pSlaveSlot->GetNextSlot())
1423 : {
1424 : // the slaves points to its master
1425 : DBG_ASSERT(pSlaveSlot->GetLinkedSlot() == pSibling,
1426 : "Wrong Master/Slave relationship!");
1427 :
1428 0 : sal_uInt16 nCurMsgPos = pImp->nMsgPos;
1429 : const SfxStateCache *pSlaveCache =
1430 0 : GetStateCache( pSlaveSlot->GetSlotId(), &nCurMsgPos );
1431 :
1432 : // Is the slave slot chached and dirty ?
1433 0 : bInsert = pSlaveCache && pSlaveCache->IsControllerDirty();
1434 :
1435 : // Slaves are chained together in a circle
1436 0 : if (pSlaveSlot->GetNextSlot() == pFirstSlave)
1437 0 : break;
1438 : }
1439 : }
1440 :
1441 289128 : if ( bInsert && bSameMethod )
1442 : {
1443 : SfxFoundCache_Impl *pFoundCache = new SfxFoundCache_Impl(
1444 73776 : pSibling->GetSlotId(), pSibling->GetWhich(rPool),
1445 73776 : pSibling, pSiblingCache );
1446 :
1447 36888 : rFound.push_back( pFoundCache );
1448 : }
1449 :
1450 289128 : pSibling = pSibling->GetNextSlot();
1451 : }
1452 :
1453 : // Create a Set from the ranges
1454 14614 : sal_uInt16 *pRanges = new sal_uInt16[rFound.size() * 2 + 1];
1455 14614 : int j = 0;
1456 14614 : sal_uInt16 i = 0;
1457 68191 : while ( i < rFound.size() )
1458 : {
1459 38963 : pRanges[j++] = rFound[i]->nWhichId;
1460 : // consecutive numbers
1461 51502 : for ( ; i < rFound.size()-1; ++i )
1462 36888 : if ( rFound[i]->nWhichId+1 != rFound[i+1]->nWhichId )
1463 24349 : break;
1464 38963 : pRanges[j++] = rFound[i++]->nWhichId;
1465 : }
1466 14614 : pRanges[j] = 0; // terminating NULL
1467 14614 : SfxItemSet *pSet = new SfxItemSet(rPool, pRanges);
1468 14614 : delete [] pRanges;
1469 : DBG_PROFSTOP(SfxBindingsCreateSet);
1470 14614 : return pSet;
1471 : }
1472 :
1473 : //--------------------------------------------------------------------
1474 :
1475 51976 : void SfxBindings::UpdateControllers_Impl
1476 : (
1477 : const SfxInterface* pIF, // Id of the current serving Interface
1478 : const SfxFoundCache_Impl* pFound, // Cache, Slot, Which etc.
1479 : const SfxPoolItem* pItem, // item to send to controller
1480 : SfxItemState eState // state of item
1481 : )
1482 : {
1483 : DBG_ASSERT( !pFound->pSlot || SFX_KIND_ENUM != pFound->pSlot->GetKind(),
1484 : "direct update of enum slot isn't allowed" );
1485 : DBG_PROFSTART(SfxBindingsUpdateCtrl1);
1486 :
1487 51976 : SfxStateCache* pCache = pFound->pCache;
1488 51976 : const SfxSlot* pSlot = pFound->pSlot;
1489 : DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" );
1490 :
1491 : // bound until now, the Controller to update the Slot.
1492 51976 : if ( pCache && pCache->IsControllerDirty() )
1493 : {
1494 51976 : if ( SFX_ITEM_DONTCARE == eState )
1495 : {
1496 : // ambiguous
1497 10 : pCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
1498 : }
1499 64935 : else if ( SFX_ITEM_DEFAULT == eState &&
1500 12969 : pFound->nWhichId > SFX_WHICH_MAX )
1501 : {
1502 : // no Status or Default but without Pool
1503 12632 : SfxVoidItem aVoid(0);
1504 12632 : pCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
1505 : }
1506 39334 : else if ( SFX_ITEM_DISABLED == eState )
1507 7322 : pCache->SetState(SFX_ITEM_DISABLED, 0);
1508 : else
1509 32012 : pCache->SetState(SFX_ITEM_AVAILABLE, pItem);
1510 : }
1511 :
1512 : DBG_PROFSTOP(SfxBindingsUpdateCtrl1);
1513 :
1514 : // Update the slots for so far available and bound Controllers for
1515 : // Slave-Slots (Enum-value)
1516 : DBG_PROFSTART(SfxBindingsUpdateCtrl2);
1517 : DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem ||
1518 : pItem->ISA(SfxEnumItemInterface),
1519 : "master slot with non-enum-type found" );
1520 51976 : const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0;
1521 51976 : if ( pIF && pFirstSlave)
1522 : {
1523 : // Items cast on EnumItem
1524 : const SfxEnumItemInterface *pEnumItem =
1525 260 : PTR_CAST(SfxEnumItemInterface,pItem);
1526 260 : if ( eState == SFX_ITEM_AVAILABLE && !pEnumItem )
1527 0 : eState = SFX_ITEM_DONTCARE;
1528 : else
1529 260 : eState = SfxControllerItem::GetItemState( pEnumItem );
1530 :
1531 : // Iterate over all Slaves-Slots
1532 3900 : for ( const SfxSlot *pSlave = pFirstSlave; pSlave; pSlave = pSlave->GetNextSlot() )
1533 : {
1534 : DBG_ASSERT(pSlave, "Wrong SlaveSlot binding!");
1535 : DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed");
1536 : DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"Wrong MasterSlot!");
1537 :
1538 : // Binding exist for function ?
1539 3900 : SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() );
1540 3900 : if ( pEnumCache )
1541 : {
1542 0 : pEnumCache->Invalidate(sal_False);
1543 :
1544 : // HACK(CONTROL/SELECT Kram) ???
1545 0 : if ( eState == SFX_ITEM_DONTCARE && pFound->nWhichId == 10144 )
1546 : {
1547 0 : SfxVoidItem aVoid(0);
1548 0 : pEnumCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
1549 :
1550 0 : if (pSlave->GetNextSlot() == pFirstSlave)
1551 0 : break;
1552 :
1553 0 : continue;
1554 : }
1555 :
1556 0 : if ( SFX_ITEM_DISABLED == eState || !pEnumItem->IsEnabled( pSlave->GetSlotId()) )
1557 : {
1558 : // disabled
1559 0 : pEnumCache->SetState(SFX_ITEM_DISABLED, 0);
1560 : }
1561 0 : else if ( SFX_ITEM_AVAILABLE == eState )
1562 : {
1563 : // Determine enum value
1564 0 : sal_uInt16 nValue = pEnumItem->GetEnumValue();
1565 0 : SfxBoolItem aBool( pFound->nWhichId, pSlave->GetValue() == nValue );
1566 0 : pEnumCache->SetState(SFX_ITEM_AVAILABLE, &aBool);
1567 : }
1568 : else
1569 : {
1570 : // ambiguous
1571 0 : pEnumCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
1572 : }
1573 : }
1574 :
1575 3900 : if (pSlave->GetNextSlot() == pFirstSlave)
1576 260 : break;
1577 : }
1578 : }
1579 :
1580 : DBG_PROFSTOP(SfxBindingsUpdateCtrl2);
1581 51976 : }
1582 :
1583 :
1584 : //--------------------------------------------------------------------
1585 :
1586 5232 : IMPL_LINK( SfxBindings, NextJob_Impl, Timer *, pTimer )
1587 : {
1588 : #ifdef DBG_UTIL
1589 : // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT
1590 : // or another MS library try to get them here
1591 : try
1592 : {
1593 : #endif
1594 2616 : const unsigned MAX_INPUT_DELAY = 200;
1595 :
1596 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1597 :
1598 : DBG_PROFSTART(SfxBindingsNextJob_Impl0);
1599 :
1600 2616 : if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY && pTimer )
1601 : {
1602 0 : pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
1603 0 : return sal_True;
1604 : }
1605 :
1606 2616 : SfxApplication *pSfxApp = SFX_APP();
1607 :
1608 2616 : if( pDispatcher )
1609 2616 : pDispatcher->Update_Impl();
1610 :
1611 : // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
1612 2616 : SfxViewFrame* pFrame = pDispatcher->GetFrame();
1613 2616 : if ( (pFrame && !pFrame->GetObjectShell()->AcceptStateUpdate()) || pSfxApp->IsDowning() || pImp->pCaches->empty() )
1614 : {
1615 : DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1616 0 : return sal_True;
1617 : }
1618 2616 : if ( !pDispatcher || !pDispatcher->IsFlushed() )
1619 : {
1620 : DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1621 0 : return sal_True;
1622 : }
1623 :
1624 : // if possible Update all server / happens in its own time slice
1625 2616 : if ( pImp->bMsgDirty )
1626 : {
1627 995 : UpdateSlotServer_Impl();
1628 : DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1629 995 : return sal_False;
1630 : }
1631 :
1632 : DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1633 : DBG_PROFSTART(SfxBindingsNextJob_Impl);
1634 1621 : pImp->bAllDirty = sal_False;
1635 1621 : pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
1636 :
1637 : // at least 10 loops and further if more jobs are available but no input
1638 1621 : bool bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule;
1639 1621 : sal_uInt16 nLoops = 10;
1640 1621 : pImp->bInNextJob = sal_True;
1641 1621 : const sal_uInt16 nCount = pImp->pCaches->size();
1642 3597 : while ( pImp->nMsgPos < nCount )
1643 : {
1644 : // iterate through the bound functions
1645 1621 : sal_Bool bJobDone = sal_False;
1646 47067 : while ( !bJobDone )
1647 : {
1648 45091 : SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos];
1649 : DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
1650 45091 : sal_Bool bWasDirty = pCache->IsControllerDirty();
1651 45091 : if ( bWasDirty )
1652 : {
1653 14502 : Update_Impl( pCache );
1654 : DBG_ASSERT( nCount == pImp->pCaches->size(),
1655 : "Reschedule in StateChanged => buff" );
1656 : }
1657 :
1658 : // skip to next function binding
1659 45091 : ++pImp->nMsgPos;
1660 :
1661 : // keep job if it is not completed, but any input is available
1662 45091 : bJobDone = pImp->nMsgPos >= nCount;
1663 45091 : if ( bJobDone && pImp->bFirstRound )
1664 : {
1665 :
1666 : // Update of the preferred shell has been done, now may
1667 : // also the others shells be updated
1668 20 : bJobDone = sal_False;
1669 20 : pImp->bFirstRound = sal_False;
1670 20 : pImp->nMsgPos = 0;
1671 : }
1672 :
1673 45091 : if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
1674 : {
1675 : DBG_PROFSTOP(SfxBindingsNextJob_Impl);
1676 1266 : pImp->bInNextJob = sal_False;
1677 1266 : return sal_False;
1678 : }
1679 : }
1680 : }
1681 :
1682 355 : pImp->nMsgPos = 0;
1683 :
1684 : // check for volatile slots
1685 355 : bool bVolatileSlotsPresent = false;
1686 33659 : for ( sal_uInt16 n = 0; n < nCount; ++n )
1687 : {
1688 33304 : SfxStateCache* pCache = (*pImp->pCaches)[n];
1689 33304 : const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1690 33304 : if ( pSlotServer && pSlotServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) )
1691 : {
1692 0 : pCache->Invalidate(sal_False);
1693 0 : bVolatileSlotsPresent = true;
1694 : }
1695 : }
1696 :
1697 355 : if (bVolatileSlotsPresent)
1698 0 : pImp->aTimer.SetTimeout(TIMEOUT_IDLE);
1699 : else
1700 355 : pImp->aTimer.Stop();
1701 :
1702 : // Update round is finished
1703 355 : pImp->bInNextJob = sal_False;
1704 355 : Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE));
1705 : DBG_PROFSTOP(SfxBindingsNextJob_Impl);
1706 355 : return sal_True;
1707 : #ifdef DBG_UTIL
1708 : }
1709 : catch (...)
1710 : {
1711 : OSL_FAIL("C++ exception caught!");
1712 : pImp->bInNextJob = sal_False;
1713 : }
1714 :
1715 : return sal_False;
1716 : #endif
1717 : }
1718 :
1719 : //--------------------------------------------------------------------
1720 :
1721 168365 : sal_uInt16 SfxBindings::EnterRegistrations(const char *pFile, int nLine)
1722 : {
1723 : SAL_INFO(
1724 : "sfx2.control",
1725 : std::setw(std::min(nRegLevel, sal_uInt16(8))) << ' ' << "this = " << this
1726 : << " Level = " << nRegLevel << " SfxBindings::EnterRegistrations "
1727 : << (pFile
1728 : ? SAL_STREAM("File: " << pFile << " Line: " << nLine) : ""));
1729 :
1730 : // When bindings are locked, also lock sub bindings.
1731 168365 : if ( pImp->pSubBindings )
1732 : {
1733 0 : pImp->pSubBindings->ENTERREGISTRATIONS();
1734 :
1735 : // These EnterRegistrations are not "real" for the SubBindings
1736 0 : pImp->pSubBindings->pImp->nOwnRegLevel--;
1737 :
1738 : // Synchronize Bindings
1739 0 : pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel + 1;
1740 : }
1741 :
1742 168365 : pImp->nOwnRegLevel++;
1743 :
1744 : // check if this is the outer most level
1745 168365 : if ( ++nRegLevel == 1 )
1746 : {
1747 : // stop background-processing
1748 53258 : pImp->aTimer.Stop();
1749 :
1750 : // flush the cache
1751 53258 : pImp->nCachedFunc1 = 0;
1752 53258 : pImp->nCachedFunc2 = 0;
1753 :
1754 : // Mark if the all of the Caches have dissapered.
1755 53258 : pImp->bCtrlReleased = sal_False;
1756 : }
1757 :
1758 168365 : return nRegLevel;
1759 : }
1760 : //--------------------------------------------------------------------
1761 :
1762 166218 : void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel, const char *pFile, int nLine )
1763 : {
1764 : (void)nLevel; // unused variable
1765 : DBG_ASSERT( nRegLevel, "Leave without Enter" );
1766 : DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" );
1767 :
1768 : // Only when the SubBindings are still locked by the Superbindings,
1769 : // remove this lock (i.e. if there are more locks than "real" ones)
1770 166218 : if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel )
1771 : {
1772 : // Synchronize Bindings
1773 0 : pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel;
1774 :
1775 : // This LeaveRegistrations is not "real" for SubBindings
1776 0 : pImp->pSubBindings->pImp->nOwnRegLevel++;
1777 0 : pImp->pSubBindings->LEAVEREGISTRATIONS();
1778 : }
1779 :
1780 166218 : pImp->nOwnRegLevel--;
1781 :
1782 : // check if this is the outer most level
1783 166218 : if ( --nRegLevel == 0 && !SFX_APP()->IsDowning() )
1784 : {
1785 53265 : if ( pImp->bContextChanged )
1786 : {
1787 60 : pImp->bContextChanged = sal_False;
1788 : }
1789 :
1790 53265 : SfxViewFrame* pFrame = pDispatcher->GetFrame();
1791 :
1792 : // If possible remove unused Caches, for example prepare PlugInInfo
1793 53265 : if ( pImp->bCtrlReleased )
1794 : {
1795 18028 : for ( sal_uInt16 nCache = pImp->pCaches->size(); nCache > 0; --nCache )
1796 : {
1797 : // Get Cache via ::com::sun::star::sdbcx::Index
1798 17170 : SfxStateCache *pCache = (*pImp->pCaches)[nCache-1];
1799 :
1800 : // No interested Controller present
1801 17170 : if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
1802 : {
1803 : // Remove Cache. Safety: first remove and then delete
1804 12025 : pImp->pCaches->erase(pImp->pCaches->begin() + nCache - 1);
1805 12025 : delete pCache;
1806 : }
1807 : }
1808 : }
1809 :
1810 : // restart background-processing
1811 53265 : pImp->nMsgPos = 0;
1812 53265 : if ( !pFrame || !pFrame->GetObjectShell() )
1813 167300 : return;
1814 52183 : if ( pImp->pCaches && !pImp->pCaches->empty() )
1815 : {
1816 48509 : pImp->aTimer.Stop();
1817 48509 : pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
1818 48509 : pImp->aTimer.Start();
1819 : }
1820 : }
1821 :
1822 : SAL_INFO(
1823 : "sfx2.control",
1824 : std::setw(std::min(nRegLevel, sal_uInt16(8))) << ' ' << "this = " << this
1825 : << " Level = " << nRegLevel << " SfxBindings::LeaveRegistrations "
1826 : << (pFile
1827 : ? SAL_STREAM("File: " << pFile << " Line: " << nLine) : ""));
1828 : }
1829 :
1830 : //--------------------------------------------------------------------
1831 :
1832 0 : const SfxSlot* SfxBindings::GetSlot(sal_uInt16 nSlotId)
1833 : {
1834 : DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1835 :
1836 : // synchronizing
1837 0 : pDispatcher->Flush();
1838 0 : if ( pImp->bMsgDirty )
1839 0 : UpdateSlotServer_Impl();
1840 :
1841 : // get the cache for the specified function; return if not bound
1842 0 : SfxStateCache* pCache = GetStateCache(nSlotId);
1843 0 : return pCache && pCache->GetSlotServer(*pDispatcher, pImp->xProv)?
1844 0 : pCache->GetSlotServer(*pDispatcher, pImp->xProv)->GetSlot(): 0;
1845 : }
1846 :
1847 : //--------------------------------------------------------------------
1848 :
1849 3230 : void SfxBindings::SetDispatcher( SfxDispatcher *pDisp )
1850 : {
1851 3230 : SfxDispatcher *pOldDispat = pDispatcher;
1852 3230 : if ( pDisp != pDispatcher )
1853 : {
1854 2165 : if ( pOldDispat )
1855 : {
1856 1079 : SfxBindings* pBind = pOldDispat->GetBindings();
1857 3237 : while ( pBind )
1858 : {
1859 1079 : if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp )
1860 4 : pBind->SetSubBindings_Impl( NULL );
1861 1079 : pBind = pBind->pImp->pSubBindings;
1862 : }
1863 : }
1864 :
1865 2165 : pDispatcher = pDisp;
1866 :
1867 2165 : ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv;
1868 2165 : if ( pDisp )
1869 2172 : xProv = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider >
1870 2172 : ( pDisp->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1871 :
1872 2165 : SetDispatchProvider_Impl( xProv );
1873 2165 : InvalidateAll( sal_True );
1874 2165 : InvalidateUnoControllers_Impl();
1875 :
1876 2165 : if ( pDispatcher && !pOldDispat )
1877 : {
1878 1086 : if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
1879 : {
1880 : OSL_FAIL( "SubBindings already set before activating!" );
1881 0 : pImp->pSubBindings->ENTERREGISTRATIONS();
1882 : }
1883 1086 : LEAVEREGISTRATIONS();
1884 : }
1885 1079 : else if( !pDispatcher )
1886 : {
1887 1079 : ENTERREGISTRATIONS();
1888 1079 : if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
1889 : {
1890 : OSL_FAIL( "SubBindings still set even when deactivating!" );
1891 0 : pImp->pSubBindings->LEAVEREGISTRATIONS();
1892 : }
1893 : }
1894 :
1895 2165 : Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
1896 :
1897 2165 : if ( pDisp )
1898 : {
1899 1086 : SfxBindings* pBind = pDisp->GetBindings();
1900 2172 : while ( pBind && pBind != this )
1901 : {
1902 4 : if ( !pBind->pImp->pSubBindings )
1903 : {
1904 4 : pBind->SetSubBindings_Impl( this );
1905 4 : break;
1906 : }
1907 :
1908 0 : pBind = pBind->pImp->pSubBindings;
1909 : }
1910 2165 : }
1911 : }
1912 3230 : }
1913 :
1914 : //--------------------------------------------------------------------
1915 :
1916 0 : void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId )
1917 : {
1918 0 : GetStateCache(nSlotId)->ClearCache();
1919 0 : }
1920 :
1921 : //--------------------------------------------------------------------
1922 0 : void SfxBindings::StartUpdate_Impl( sal_Bool bComplete )
1923 : {
1924 0 : if ( pImp->pSubBindings )
1925 0 : pImp->pSubBindings->StartUpdate_Impl( bComplete );
1926 :
1927 0 : if ( !bComplete )
1928 : // Update may be interrupted
1929 0 : NextJob_Impl(&pImp->aTimer);
1930 : else
1931 : // Update all slots in a row
1932 0 : NextJob_Impl(0);
1933 0 : }
1934 :
1935 : //-------------------------------------------------------------------------
1936 :
1937 0 : SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, SfxPoolItem* &rpState )
1938 : {
1939 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
1940 0 : SfxStateCache *pCache = GetStateCache( nSlot );
1941 0 : if ( pCache )
1942 0 : xDisp = pCache->GetDispatch();
1943 0 : if ( xDisp.is() || !pCache )
1944 : {
1945 0 : const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pDispatcher->GetFrame() ).GetSlot( nSlot );
1946 0 : if ( !pSlot || !pSlot->pUnoName )
1947 0 : return SFX_ITEM_DISABLED;
1948 :
1949 0 : ::com::sun::star::util::URL aURL;
1950 0 : OUString aCmd( ".uno:" );
1951 0 : aURL.Protocol = aCmd;
1952 0 : aURL.Path = OUString::createFromAscii(pSlot->GetUnoName());
1953 0 : aCmd += aURL.Path;
1954 0 : aURL.Complete = aCmd;
1955 0 : aURL.Main = aCmd;
1956 :
1957 0 : if ( !xDisp.is() )
1958 0 : xDisp = pImp->xProv->queryDispatch( aURL, OUString(), 0 );
1959 :
1960 0 : if ( xDisp.is() )
1961 : {
1962 0 : ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
1963 0 : SfxOfficeDispatch* pDisp = NULL;
1964 0 : if ( xTunnel.is() )
1965 : {
1966 0 : sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
1967 0 : pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation ));
1968 : }
1969 :
1970 0 : if ( !pDisp )
1971 : {
1972 0 : sal_Bool bDeleteCache = sal_False;
1973 0 : if ( !pCache )
1974 : {
1975 0 : pCache = new SfxStateCache( nSlot );
1976 0 : pCache->GetSlotServer( *GetDispatcher_Impl(), pImp->xProv );
1977 0 : bDeleteCache = sal_True;
1978 : }
1979 :
1980 0 : SfxItemState eState = SFX_ITEM_SET;
1981 0 : SfxPoolItem *pItem=NULL;
1982 0 : BindDispatch_Impl *pBind = new BindDispatch_Impl( xDisp, aURL, pCache, pSlot );
1983 0 : pBind->acquire();
1984 0 : xDisp->addStatusListener( pBind, aURL );
1985 0 : if ( !pBind->GetStatus().IsEnabled )
1986 : {
1987 0 : eState = SFX_ITEM_DISABLED;
1988 : }
1989 : else
1990 : {
1991 0 : ::com::sun::star::uno::Any aAny = pBind->GetStatus().State;
1992 0 : ::com::sun::star::uno::Type pType = aAny.getValueType();
1993 :
1994 0 : if ( pType == ::getBooleanCppuType() )
1995 : {
1996 0 : sal_Bool bTemp = false;
1997 0 : aAny >>= bTemp ;
1998 0 : pItem = new SfxBoolItem( nSlot, bTemp );
1999 : }
2000 0 : else if ( pType == ::getCppuType((const sal_uInt16*)0) )
2001 : {
2002 0 : sal_uInt16 nTemp = 0;
2003 0 : aAny >>= nTemp ;
2004 0 : pItem = new SfxUInt16Item( nSlot, nTemp );
2005 : }
2006 0 : else if ( pType == ::getCppuType((const sal_uInt32*)0) )
2007 : {
2008 0 : sal_uInt32 nTemp = 0;
2009 0 : aAny >>= nTemp ;
2010 0 : pItem = new SfxUInt32Item( nSlot, nTemp );
2011 : }
2012 0 : else if ( pType == ::getCppuType((const OUString*)0) )
2013 : {
2014 0 : OUString sTemp ;
2015 0 : aAny >>= sTemp ;
2016 0 : pItem = new SfxStringItem( nSlot, sTemp );
2017 : }
2018 : else
2019 0 : pItem = new SfxVoidItem( nSlot );
2020 : }
2021 :
2022 0 : xDisp->removeStatusListener( pBind, aURL );
2023 0 : pBind->Release();
2024 0 : rpState = pItem;
2025 0 : if ( bDeleteCache )
2026 0 : DELETEZ( pCache );
2027 0 : return eState;
2028 0 : }
2029 0 : }
2030 : }
2031 :
2032 : // Then test at the dispatcher to check if the returned items from
2033 : // there are always DELETE_ON_IDLE, a copy of it has to be made in
2034 : // order to allow for transition of ownership.
2035 0 : const SfxPoolItem *pItem = NULL;
2036 0 : SfxItemState eState = pDispatcher->QueryState( nSlot, pItem );
2037 0 : if ( eState == SFX_ITEM_SET )
2038 : {
2039 : DBG_ASSERT( pItem, "SFX_ITEM_SET but no item!" );
2040 0 : if ( pItem )
2041 0 : rpState = pItem->Clone();
2042 : }
2043 0 : else if ( eState == SFX_ITEM_AVAILABLE && pItem )
2044 : {
2045 0 : rpState = pItem->Clone();
2046 : }
2047 :
2048 0 : return eState;
2049 : }
2050 :
2051 8 : void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub )
2052 : {
2053 8 : if ( pImp->pSubBindings )
2054 : {
2055 4 : pImp->pSubBindings->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () );
2056 4 : pImp->pSubBindings->pImp->pSuperBindings = NULL;
2057 : }
2058 :
2059 8 : pImp->pSubBindings = pSub;
2060 :
2061 8 : if ( pSub )
2062 : {
2063 4 : pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
2064 4 : pSub->pImp->pSuperBindings = this;
2065 : }
2066 8 : }
2067 :
2068 3211 : SfxBindings* SfxBindings::GetSubBindings_Impl( sal_Bool bTop ) const
2069 : {
2070 3211 : SfxBindings *pRet = pImp->pSubBindings;
2071 3211 : if ( bTop )
2072 : {
2073 0 : while ( pRet->pImp->pSubBindings )
2074 0 : pRet = pRet->pImp->pSubBindings;
2075 : }
2076 :
2077 3211 : return pRet;
2078 : }
2079 :
2080 1082 : void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork )
2081 : {
2082 1082 : pImp->pWorkWin = pWork;
2083 1082 : }
2084 :
2085 5560 : SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const
2086 : {
2087 5560 : return pImp->pWorkWin;
2088 : }
2089 :
2090 0 : void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl )
2091 : {
2092 0 : if ( !pImp->pUnoCtrlArr )
2093 0 : pImp->pUnoCtrlArr = new SfxUnoControllerArr_Impl;
2094 0 : pImp->pUnoCtrlArr->push_back( pControl );
2095 0 : }
2096 :
2097 0 : void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl )
2098 : {
2099 0 : if ( pImp->pUnoCtrlArr )
2100 : {
2101 : SfxUnoControllerArr_Impl::iterator it = std::find(
2102 0 : pImp->pUnoCtrlArr->begin(), pImp->pUnoCtrlArr->end(), pControl );
2103 0 : if ( it != pImp->pUnoCtrlArr->end() )
2104 : {
2105 0 : pImp->pUnoCtrlArr->erase( it );
2106 0 : return;
2107 : }
2108 : }
2109 :
2110 0 : if ( pImp->pSubBindings )
2111 0 : pImp->pSubBindings->ReleaseUnoController_Impl( pControl );
2112 : }
2113 :
2114 4330 : void SfxBindings::InvalidateUnoControllers_Impl()
2115 : {
2116 4330 : if ( pImp->pUnoCtrlArr )
2117 : {
2118 0 : sal_uInt16 nCount = pImp->pUnoCtrlArr->size();
2119 0 : for ( sal_uInt16 n=nCount; n>0; n-- )
2120 : {
2121 0 : SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
2122 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > xRef( (::cppu::OWeakObject*)pCtrl, ::com::sun::star::uno::UNO_QUERY );
2123 0 : pCtrl->ReleaseDispatch();
2124 0 : pCtrl->GetNewDispatch();
2125 0 : }
2126 : }
2127 :
2128 4330 : if ( pImp->pSubBindings )
2129 0 : pImp->pSubBindings->InvalidateUnoControllers_Impl();
2130 4330 : }
2131 :
2132 10077 : sal_Bool SfxBindings::IsInUpdate() const
2133 : {
2134 10077 : sal_Bool bInUpdate = pImp->bInUpdate;
2135 10077 : if ( !bInUpdate && pImp->pSubBindings )
2136 0 : bInUpdate = pImp->pSubBindings->IsInUpdate();
2137 10077 : return bInUpdate;
2138 : }
2139 :
2140 264 : void SfxBindings::SetVisibleState( sal_uInt16 nId, sal_Bool bShow )
2141 : {
2142 264 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
2143 264 : SfxStateCache *pCache = GetStateCache( nId );
2144 264 : if ( pCache )
2145 0 : pCache->SetVisibleState( bShow );
2146 264 : }
2147 :
2148 4403 : void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
2149 : {
2150 4403 : if ( rFrame.is() || !pDispatcher )
2151 1065 : SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) );
2152 : else
2153 : SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > (
2154 3338 : pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ) );
2155 4403 : }
2156 :
2157 2896 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxBindings::GetActiveFrame() const
2158 : {
2159 2896 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( pImp->xProv, ::com::sun::star::uno::UNO_QUERY );
2160 2896 : if ( xFrame.is() || !pDispatcher )
2161 2895 : return xFrame;
2162 : else
2163 1 : return pDispatcher->GetFrame()->GetFrame().GetFrameInterface();
2164 : }
2165 :
2166 6576 : void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv )
2167 : {
2168 6576 : sal_Bool bInvalidate = ( rProv != pImp->xProv );
2169 6576 : if ( bInvalidate )
2170 : {
2171 2165 : pImp->xProv = rProv;
2172 2165 : InvalidateAll( sal_True );
2173 2165 : InvalidateUnoControllers_Impl();
2174 : }
2175 :
2176 6576 : if ( pImp->pSubBindings )
2177 0 : pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
2178 6576 : }
2179 :
2180 0 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & SfxBindings::GetDispatchProvider_Impl() const
2181 : {
2182 0 : return pImp->xProv;
2183 : }
2184 :
2185 0 : SystemWindow* SfxBindings::GetSystemWindow() const
2186 : {
2187 0 : SfxViewFrame *pFrame = pDispatcher->GetFrame();
2188 0 : while ( pFrame->GetParentViewFrame_Impl() )
2189 0 : pFrame = pFrame->GetParentViewFrame_Impl();
2190 0 : SfxViewFrame* pTop = pFrame->GetTopViewFrame();
2191 0 : return pTop->GetFrame().GetTopWindow_Impl();
2192 : }
2193 :
2194 0 : sal_Bool SfxBindings::ExecuteCommand_Impl( const String& rCommand )
2195 : {
2196 0 : ::com::sun::star::util::URL aURL;
2197 0 : aURL.Complete = rCommand;
2198 0 : Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2199 0 : xTrans->parseStrict( aURL );
2200 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp = pImp->xProv->queryDispatch( aURL, OUString(), 0 );
2201 0 : if ( xDisp.is() )
2202 : {
2203 0 : new SfxAsyncExec_Impl( aURL, xDisp );
2204 0 : return sal_True;
2205 : }
2206 :
2207 0 : return sal_False;
2208 : }
2209 :
2210 0 : com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxBindings::GetRecorder() const
2211 : {
2212 0 : return pImp->xRecorder;
2213 : }
2214 :
2215 1075 : void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder >& rRecorder )
2216 : {
2217 1075 : pImp->xRecorder = rRecorder;
2218 1075 : }
2219 :
2220 0 : void SfxBindings::ContextChanged_Impl()
2221 : {
2222 0 : if ( !pImp->bInUpdate && ( !pImp->bContextChanged || !pImp->bAllMsgDirty ) )
2223 : {
2224 0 : InvalidateAll( sal_True );
2225 : }
2226 0 : }
2227 :
2228 147637 : uno::Reference < frame::XDispatch > SfxBindings::GetDispatch( const SfxSlot* pSlot, const util::URL& aURL, sal_Bool bMasterCommand )
2229 : {
2230 147637 : uno::Reference < frame::XDispatch > xRet;
2231 147637 : SfxStateCache* pCache = GetStateCache( pSlot->nSlotId );
2232 147637 : if ( pCache && !bMasterCommand )
2233 99274 : xRet = pCache->GetInternalDispatch();
2234 147637 : if ( !xRet.is() )
2235 : {
2236 : // dispatches for slaves are unbound, they don't have a state
2237 : SfxOfficeDispatch* pDispatch = bMasterCommand ?
2238 104 : new SfxOfficeDispatch( pDispatcher, pSlot, aURL ) :
2239 55540 : new SfxOfficeDispatch( *this, pDispatcher, pSlot, aURL );
2240 :
2241 55436 : pDispatch->SetMasterUnoCommand( bMasterCommand );
2242 55436 : xRet = uno::Reference < frame::XDispatch >( pDispatch );
2243 55436 : if ( !pCache )
2244 48259 : pCache = GetStateCache( pSlot->nSlotId );
2245 :
2246 : DBG_ASSERT( pCache, "No cache for OfficeDispatch!" );
2247 55436 : if ( pCache && !bMasterCommand )
2248 55332 : pCache->SetInternalDispatch( xRet );
2249 : }
2250 :
2251 147637 : return xRet;
2252 408 : }
2253 :
2254 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|