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