1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sal/config.h"
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>
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>
66 #include <com/sun/star/frame/XModuleManager.hpp>
68 #include <boost/scoped_ptr.hpp>
70 using namespace ::com::sun::star
;
71 using namespace ::com::sun::star::uno
;
72 using namespace ::com::sun::star::util
;
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
)
84 //====================================================================
86 static sal_uInt16 nTimeOut
= 300;
88 #define TIMEOUT_FIRST nTimeOut
89 #define TIMEOUT_UPDATING 20
90 #define TIMEOUT_IDLE 2500
92 typedef boost::unordered_map
< sal_uInt16
, bool > InvalidateSlotMap
;
94 //====================================================================
96 typedef std::vector
<SfxStateCache
*> SfxStateCacheArr_Impl
;
98 //====================================================================
100 class SfxAsyncExec_Impl
102 ::com::sun::star::util::URL aCommand
;
103 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
108 SfxAsyncExec_Impl( const ::com::sun::star::util::URL
& rCmd
, const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
>& rDisp
)
112 aTimer
.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl
, TimerHdl
) );
113 aTimer
.SetTimeout( 0 );
117 DECL_LINK( TimerHdl
, Timer
*);
120 IMPL_LINK(SfxAsyncExec_Impl
, TimerHdl
, Timer
*, pTimer
)
122 (void)pTimer
; // unused
125 Sequence
<beans::PropertyValue
> aSeq
;
126 xDisp
->dispatch( aCommand
, aSeq
);
132 class SfxBindings_Impl
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
*
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
161 //--------------------------------------------------------------------
163 struct SfxFoundCache_Impl
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
170 SfxFoundCache_Impl():
177 SfxFoundCache_Impl(SfxFoundCache_Impl
&r
):
179 nWhichId(r
.nWhichId
),
184 SfxFoundCache_Impl(sal_uInt16 nS
, sal_uInt16 nW
, const SfxSlot
*pS
, SfxStateCache
*pC
):
191 int operator<( const SfxFoundCache_Impl
&r
) const
192 { return nWhichId
< r
.nWhichId
; }
194 int operator==( const SfxFoundCache_Impl
&r
) const
195 { return nWhichId
== r
.nWhichId
; }
198 //--------------------------------------------------------------------------
200 class SfxFoundCacheArr_Impl
: public std::vector
<SfxFoundCache_Impl
*>
203 ~SfxFoundCacheArr_Impl()
205 for(const_iterator it
= begin(); it
!= end(); ++it
)
210 //==========================================================================
212 SfxBindings::SfxBindings()
213 : pImp(new SfxBindings_Impl
),
215 nRegLevel(1) // first becomes 0, when the Dispatcher is set
218 pImp
->bAllMsgDirty
= sal_True
;
219 pImp
->bContextChanged
= sal_False
;
220 pImp
->bMsgDirty
= sal_True
;
221 pImp
->bAllDirty
= sal_True
;
222 pImp
->ePopupAction
= SFX_POPUP_DELETE
;
223 pImp
->nCachedFunc1
= 0;
224 pImp
->nCachedFunc2
= 0;
225 pImp
->bCtrlReleased
= sal_False
;
226 pImp
->bFirstRound
= sal_False
;
227 pImp
->bInNextJob
= sal_False
;
228 pImp
->bInUpdate
= sal_False
;
229 pImp
->pSubBindings
= NULL
;
230 pImp
->pSuperBindings
= NULL
;
231 pImp
->pWorkWin
= NULL
;
232 pImp
->pUnoCtrlArr
= NULL
;
233 pImp
->nOwnRegLevel
= nRegLevel
;
235 // all caches are valid (no pending invalidate-job)
236 // create the list of caches
237 pImp
->pCaches
= new SfxStateCacheArr_Impl
;
238 pImp
->aTimer
.SetTimeoutHdl( LINK(this, SfxBindings
, NextJob_Impl
) );
241 //====================================================================
243 SfxBindings::~SfxBindings()
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()>.
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.
258 // The SubBindings should not be locked!
259 pImp
->pSubBindings
= NULL
;
261 ENTERREGISTRATIONS();
264 DeleteControllers_Impl();
267 for(SfxStateCacheArr_Impl::const_iterator it
= pImp
->pCaches
->begin(); it
!= pImp
->pCaches
->end(); ++it
)
270 DELETEZ( pImp
->pWorkWin
);
272 delete pImp
->pCaches
;
276 //--------------------------------------------------------------------
278 void SfxBindings::DeleteControllers_Impl()
280 // in the first round delete SfxPopupWindows
281 sal_uInt16 nCount
= pImp
->pCaches
->size();
283 for ( nCache
= 0; nCache
< nCount
; ++nCache
)
285 // Remember were you are
286 SfxStateCache
*pCache
= (*pImp
->pCaches
)[nCache
];
287 sal_uInt16 nSlotId
= pCache
->GetId();
289 // Delete SfxPopupWindow
290 pCache
->DeleteFloatingWindows();
292 // Re-align, because the cache may have been reduced
293 sal_uInt16 nNewCount
= pImp
->pCaches
->size();
294 if ( nNewCount
< nCount
)
296 nCache
= GetSlotPos(nSlotId
);
297 if ( nCache
>= nNewCount
||
298 nSlotId
!= (*pImp
->pCaches
)[nCache
]->GetId() )
305 for ( nCache
= pImp
->pCaches
->size(); nCache
> 0; --nCache
)
307 // Get Cache via ::com::sun::star::sdbcx::Index
308 SfxStateCache
*pCache
= (*pImp
->pCaches
)[ nCache
-1 ];
310 // unbind all controllers in the cache
311 SfxControllerItem
*pNext
;
312 for ( SfxControllerItem
*pCtrl
= pCache
->GetItemLink();
313 pCtrl
; pCtrl
= pNext
)
315 pNext
= pCtrl
->GetItemLink();
319 if ( pCache
->GetInternalController() )
320 pCache
->GetInternalController()->UnBind();
323 if( nCache
-1 < (sal_uInt16
) pImp
->pCaches
->size() )
324 delete (*pImp
->pCaches
)[nCache
-1];
325 pImp
->pCaches
->erase(pImp
->pCaches
->begin()+ nCache
- 1);
328 if( pImp
->pUnoCtrlArr
)
330 sal_uInt16 nCtrlCount
= pImp
->pUnoCtrlArr
->size();
331 for ( sal_uInt16 n
=nCtrlCount
; n
>0; n
-- )
333 SfxUnoControllerItem
*pCtrl
= (*pImp
->pUnoCtrlArr
)[n
-1];
334 pCtrl
->ReleaseBindings();
337 DBG_ASSERT( !pImp
->pUnoCtrlArr
->size(), "Do not remove UnoControllerItems!" );
338 DELETEZ( pImp
->pUnoCtrlArr
);
342 //--------------------------------------------------------------------
344 void SfxBindings::HidePopups( bool bHide
)
346 // Hide SfxPopupWindows
347 HidePopupCtrls_Impl( bHide
);
348 SfxBindings
*pSub
= pImp
->pSubBindings
;
351 pImp
->pSubBindings
->HidePopupCtrls_Impl( bHide
);
352 pSub
= pSub
->pImp
->pSubBindings
;
355 // Hide SfxChildWindows
356 DBG_ASSERT( pDispatcher
, "HidePopups not allowed without dispatcher" );
357 if ( pImp
->pWorkWin
)
358 pImp
->pWorkWin
->HidePopups_Impl( bHide
, sal_True
);
361 void SfxBindings::HidePopupCtrls_Impl( bool bHide
)
365 // Hide SfxPopupWindows
366 pImp
->ePopupAction
= SFX_POPUP_HIDE
;
370 // Show SfxPopupWindows
371 pImp
->ePopupAction
= SFX_POPUP_SHOW
;
374 for(SfxStateCacheArr_Impl::const_iterator it
= pImp
->pCaches
->begin(); it
!= pImp
->pCaches
->end(); ++it
)
375 (*it
)->DeleteFloatingWindows();
376 pImp
->ePopupAction
= SFX_POPUP_DELETE
;
379 //--------------------------------------------------------------------
381 void SfxBindings::Update_Impl
383 SfxStateCache
* pCache
// The up to date SfxStatusCache
386 if( pCache
->GetDispatch().is() && pCache
->GetItemLink() )
388 pCache
->SetCachedState(sal_True
);
389 if ( !pCache
->GetInternalController() )
395 DBG_PROFSTART(SfxBindingsUpdate_Impl
);
397 // gather together all with the same status method which are dirty
398 SfxDispatcher
&rDispat
= *pDispatcher
;
399 const SfxSlot
*pRealSlot
= 0;
400 const SfxSlotServer
* pMsgServer
= 0;
401 SfxFoundCacheArr_Impl aFound
;
402 SfxItemSet
*pSet
= CreateSet_Impl( pCache
, pRealSlot
, &pMsgServer
, aFound
);
403 sal_Bool bUpdated
= sal_False
;
407 if ( rDispat
._FillState( *pMsgServer
, *pSet
, pRealSlot
) )
410 const SfxInterface
*pInterface
=
411 rDispat
.GetShell(pMsgServer
->GetShellLevel())->GetInterface();
412 for ( sal_uInt16 nPos
= 0; nPos
< aFound
.size(); ++nPos
)
414 const SfxFoundCache_Impl
*pFound
= aFound
[nPos
];
415 sal_uInt16 nWhich
= pFound
->nWhichId
;
416 const SfxPoolItem
*pItem
= 0;
417 SfxItemState eState
= pSet
->GetItemState(nWhich
, sal_True
, &pItem
);
418 if ( eState
== SFX_ITEM_DEFAULT
&& SfxItemPool::IsWhich(nWhich
) )
419 pItem
= &pSet
->Get(nWhich
);
420 UpdateControllers_Impl( pInterface
, aFound
[nPos
], pItem
, eState
);
428 if ( !bUpdated
&& pCache
)
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(
436 UpdateControllers_Impl( 0, &aFoundCache
, 0, SFX_ITEM_DISABLED
);
439 DBG_PROFSTOP(SfxBindingsUpdate_Impl
);
442 //--------------------------------------------------------------------
444 void SfxBindings::InvalidateSlotsInMap_Impl()
446 InvalidateSlotMap::const_iterator pIter
= pImp
->m_aInvalidateSlots
.begin();
447 while ( pIter
!= pImp
->m_aInvalidateSlots
.end() )
449 Invalidate( pIter
->first
);
452 pImp
->m_aInvalidateSlots
.clear();
455 //--------------------------------------------------------------------
457 void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( sal_uInt16 nId
)
459 pImp
->m_aInvalidateSlots
[nId
] = sal_True
;
462 //--------------------------------------------------------------------
464 void SfxBindings::Update
466 sal_uInt16 nId
// the bound and up-to-date Slot-Id
469 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
472 pDispatcher
->Flush();
474 if ( pImp
->pSubBindings
)
475 pImp
->pSubBindings
->Update( nId
);
477 SfxStateCache
* pCache
= GetStateCache( nId
);
480 pImp
->bInUpdate
= sal_True
;
481 if ( pImp
->bMsgDirty
)
483 UpdateSlotServer_Impl();
484 pCache
= GetStateCache( nId
);
489 sal_Bool bInternalUpdate
= sal_True
;
490 if( pCache
->GetDispatch().is() && pCache
->GetItemLink() )
492 pCache
->SetCachedState(sal_True
);
493 bInternalUpdate
= ( pCache
->GetInternalController() != 0 );
496 if ( bInternalUpdate
)
499 const SfxSlotServer
* pMsgServer
= pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
500 if ( !pCache
->IsControllerDirty() &&
502 !pMsgServer
->GetSlot()->IsMode(SFX_SLOT_VOLATILE
) ) )
504 pImp
->bInUpdate
= sal_False
;
505 InvalidateSlotsInMap_Impl();
510 pCache
->SetState(SFX_ITEM_DISABLED
, 0);
511 pImp
->bInUpdate
= sal_False
;
512 InvalidateSlotsInMap_Impl();
519 pImp
->bAllDirty
= sal_False
;
522 pImp
->bInUpdate
= sal_False
;
523 InvalidateSlotsInMap_Impl();
527 //--------------------------------------------------------------------
529 void SfxBindings::Update()
531 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
533 if ( pImp
->pSubBindings
)
534 pImp
->pSubBindings
->Update();
541 pImp
->bInUpdate
= sal_True
;
542 pDispatcher
->Flush();
543 pDispatcher
->Update_Impl();
544 while ( !NextJob_Impl(0) )
546 pImp
->bInUpdate
= sal_False
;
547 InvalidateSlotsInMap_Impl();
551 //--------------------------------------------------------------------
553 void SfxBindings::SetState
555 const SfxItemSet
& rSet
// status values to be set
558 // when locked then only invalidate
561 SfxItemIter
aIter(rSet
);
562 for ( const SfxPoolItem
*pItem
= aIter
.FirstItem();
564 pItem
= aIter
.NextItem() )
565 Invalidate( pItem
->Which() );
569 // Status may be accepted only if all slot-pointers are set
570 if ( pImp
->bMsgDirty
)
571 UpdateSlotServer_Impl();
573 // Iterate over the itemset, update if the slot bound
574 //! Bug: Use WhichIter and possibly send VoidItems up
575 SfxItemIter
aIter(rSet
);
576 for ( const SfxPoolItem
*pItem
= aIter
.FirstItem();
578 pItem
= aIter
.NextItem() )
580 SfxStateCache
* pCache
=
581 GetStateCache( rSet
.GetPool()->GetSlotId(pItem
->Which()) );
585 if ( !pCache
->IsControllerDirty() )
586 pCache
->Invalidate(sal_False
);
587 pCache
->SetState( SFX_ITEM_AVAILABLE
, pItem
);
589 //! Not implemented: Updates from EnumSlots via master slots
595 //--------------------------------------------------------------------
597 void SfxBindings::SetState
599 const SfxPoolItem
& rItem
// Status value to be set
604 Invalidate( rItem
.Which() );
608 // Status may be accepted only if all slot-pointers are set
609 if ( pImp
->bMsgDirty
)
610 UpdateSlotServer_Impl();
612 //update if the slot bound
613 DBG_ASSERT( SfxItemPool::IsSlot( rItem
.Which() ),
614 "cannot set items with which-id" );
615 SfxStateCache
* pCache
= GetStateCache( rItem
.Which() );
619 if ( !pCache
->IsControllerDirty() )
620 pCache
->Invalidate(sal_False
);
621 pCache
->SetState( SFX_ITEM_AVAILABLE
, &rItem
);
623 //! Not implemented: Updates from EnumSlots via master slots
629 //--------------------------------------------------------------------
631 SfxStateCache
* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId
)
633 SfxStateCache
* pCache
= GetStateCache( nId
);
634 if ( !pCache
&& pImp
->pSubBindings
)
635 return pImp
->pSubBindings
->GetAnyStateCache_Impl( nId
);
639 SfxStateCache
* SfxBindings::GetStateCache
641 sal_uInt16 nId
/* Slot-Id, which SfxStatusCache is to be found */
644 return GetStateCache(nId
, 0);
647 SfxStateCache
* SfxBindings::GetStateCache
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. */
656 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
657 // is the specified function bound?
658 const sal_uInt16 nStart
= ( pPos
? *pPos
: 0 );
659 const sal_uInt16 nPos
= GetSlotPos( nId
, nStart
);
661 if ( nPos
< pImp
->pCaches
->size() &&
662 (*pImp
->pCaches
)[nPos
]->GetId() == nId
)
666 return (*pImp
->pCaches
)[nPos
];
671 //--------------------------------------------------------------------
673 void SfxBindings::InvalidateAll
675 sal_Bool bWithMsg
/* sal_True Mark Slot Server as invalid
676 sal_False Slot Server remains valid */
679 DBG_PROFSTART(SfxBindingsInvalidateAll
);
680 DBG_ASSERT( !pImp
->bInUpdate
, "SfxBindings::Invalidate while in update" );
682 if ( pImp
->pSubBindings
)
683 pImp
->pSubBindings
->InvalidateAll( bWithMsg
);
685 // everything is already set dirty or downing => nothing to do
687 ( pImp
->bAllDirty
&& ( !bWithMsg
|| pImp
->bAllMsgDirty
) ) ||
688 SFX_APP()->IsDowning() )
690 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
694 pImp
->bAllMsgDirty
= pImp
->bAllMsgDirty
|| bWithMsg
;
695 pImp
->bMsgDirty
= pImp
->bMsgDirty
|| pImp
->bAllMsgDirty
|| bWithMsg
;
696 pImp
->bAllDirty
= sal_True
;
698 for ( sal_uInt16 n
= 0; n
< pImp
->pCaches
->size(); ++n
)
699 (*pImp
->pCaches
)[n
]->Invalidate(bWithMsg
);
705 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
706 pImp
->aTimer
.Start();
709 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
712 //--------------------------------------------------------------------
714 void SfxBindings::Invalidate
716 const sal_uInt16
* pIds
/* numerically sorted NULL-terminated array of
717 slot IDs (individual, not as a couple!) */
720 DBG_PROFSTART(SfxBindingsInvalidateAll
);
722 if ( pImp
->bInUpdate
)
725 while ( pIds
[i
] != 0 )
726 AddSlotToInvalidateSlotsMap_Impl( pIds
[i
++] );
728 if ( pImp
->pSubBindings
)
729 pImp
->pSubBindings
->Invalidate( pIds
);
733 if ( pImp
->pSubBindings
)
734 pImp
->pSubBindings
->Invalidate( pIds
);
736 // everything is already set dirty or downing => nothing to do
737 if ( !pDispatcher
|| pImp
->bAllDirty
|| SFX_APP()->IsDowning() )
740 // Search binary in always smaller areas
741 for ( sal_uInt16 n
= GetSlotPos(*pIds
);
742 *pIds
&& n
< pImp
->pCaches
->size();
743 n
= GetSlotPos(*pIds
, n
) )
745 // If SID is ever bound, then invalidate the cache
746 SfxStateCache
*pCache
= (*pImp
->pCaches
)[n
];
747 if ( pCache
->GetId() == *pIds
)
748 pCache
->Invalidate(sal_False
);
753 DBG_ASSERT( *pIds
> *(pIds
-1), "pIds unsorted" );
756 // if not enticed to start update timer
761 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
762 pImp
->aTimer
.Start();
765 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
768 //--------------------------------------------------------------------
770 void SfxBindings::InvalidateShell
772 const SfxShell
& rSh
, /* <SfxShell>, which Slot-Ids should be
774 sal_Bool bDeep
/* sal_True
775 also inherited slot IDs of SfxShell are invalidert
778 the inherited and not overloaded Slot-Ids were
780 // for now always bDeep
783 DBG_ASSERT( !pImp
->bInUpdate
, "SfxBindings::Invalidate while in update" );
785 if ( pImp
->pSubBindings
)
786 pImp
->pSubBindings
->InvalidateShell( rSh
, bDeep
);
788 if ( !pDispatcher
|| pImp
->bAllDirty
|| SFX_APP()->IsDowning() )
791 DBG_PROFSTART(SfxBindingsInvalidateAll
);
793 // flush now already, it is done in GetShellLevel (rsh) anyway,
794 // important so that is set correctly: pimp-> ball(Msg)Dirty
795 pDispatcher
->Flush();
798 ( pImp
->bAllDirty
&& pImp
->bAllMsgDirty
) ||
799 SFX_APP()->IsDowning() )
801 // if the next one is anyway, then all the servers are collected
806 sal_uInt16 nLevel
= pDispatcher
->GetShellLevel(rSh
);
807 if ( nLevel
!= USHRT_MAX
)
809 for ( sal_uInt16 n
= 0; n
< pImp
->pCaches
->size(); ++n
)
811 SfxStateCache
*pCache
= (*pImp
->pCaches
)[n
];
812 const SfxSlotServer
*pMsgServer
=
813 pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
814 if ( pMsgServer
&& pMsgServer
->GetShellLevel() == nLevel
)
815 pCache
->Invalidate(sal_False
);
821 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
822 pImp
->aTimer
.Start();
823 pImp
->bFirstRound
= sal_True
;
824 pImp
->nFirstShell
= nLevel
;
828 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
831 //--------------------------------------------------------------------
833 void SfxBindings::Invalidate
835 sal_uInt16 nId
// Status value to be set
838 if ( pImp
->bInUpdate
)
840 AddSlotToInvalidateSlotsMap_Impl( nId
);
841 if ( pImp
->pSubBindings
)
842 pImp
->pSubBindings
->Invalidate( nId
);
846 if ( pImp
->pSubBindings
)
847 pImp
->pSubBindings
->Invalidate( nId
);
849 if ( !pDispatcher
|| pImp
->bAllDirty
|| SFX_APP()->IsDowning() )
852 SfxStateCache
* pCache
= GetStateCache(nId
);
855 pCache
->Invalidate(sal_False
);
856 pImp
->nMsgPos
= std::min(GetSlotPos(nId
), pImp
->nMsgPos
);
860 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
861 pImp
->aTimer
.Start();
866 //--------------------------------------------------------------------
868 void SfxBindings::Invalidate
870 sal_uInt16 nId
, // Status value to be set
871 sal_Bool bWithItem
, // Clear StateCache?
872 sal_Bool bWithMsg
// Get new SlotServer?
875 DBG_ASSERT( !pImp
->bInUpdate
, "SfxBindings::Invalidate while in update" );
877 if ( pImp
->pSubBindings
)
878 pImp
->pSubBindings
->Invalidate( nId
, bWithItem
, bWithMsg
);
880 if ( SFX_APP()->IsDowning() )
883 SfxStateCache
* pCache
= GetStateCache(nId
);
887 pCache
->ClearCache();
888 pCache
->Invalidate(bWithMsg
);
890 if ( !pDispatcher
|| pImp
->bAllDirty
)
893 pImp
->nMsgPos
= std::min(GetSlotPos(nId
), pImp
->nMsgPos
);
897 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
898 pImp
->aTimer
.Start();
903 //--------------------------------------------------------------------
905 sal_Bool
SfxBindings::IsBound( sal_uInt16 nSlotId
, sal_uInt16 nStartSearchAt
)
907 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
908 return GetStateCache(nSlotId
, &nStartSearchAt
) != 0;
911 //--------------------------------------------------------------------
913 sal_uInt16
SfxBindings::GetSlotPos( sal_uInt16 nId
, sal_uInt16 nStartSearchAt
)
915 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
916 DBG_PROFSTART(SfxBindingsMsgPos
);
918 // answer immediately if a function-seek comes repeated
919 if ( pImp
->nCachedFunc1
< pImp
->pCaches
->size() &&
920 (*pImp
->pCaches
)[pImp
->nCachedFunc1
]->GetId() == nId
)
922 DBG_PROFSTOP(SfxBindingsMsgPos
);
923 return pImp
->nCachedFunc1
;
925 if ( pImp
->nCachedFunc2
< pImp
->pCaches
->size() &&
926 (*pImp
->pCaches
)[pImp
->nCachedFunc2
]->GetId() == nId
)
929 sal_uInt16 nTemp
= pImp
->nCachedFunc1
;
930 pImp
->nCachedFunc1
= pImp
->nCachedFunc2
;
931 pImp
->nCachedFunc2
= nTemp
;
932 DBG_PROFSTOP(SfxBindingsMsgPos
);
933 return pImp
->nCachedFunc1
;
936 // binary search, if not found, seek to target-position
937 if ( pImp
->pCaches
->size() <= nStartSearchAt
)
939 DBG_PROFSTOP(SfxBindingsMsgPos
);
942 if ( (sal_uInt16
) pImp
->pCaches
->size() == (nStartSearchAt
+1) )
944 DBG_PROFSTOP(SfxBindingsMsgPos
);
945 return (*pImp
->pCaches
)[nStartSearchAt
]->GetId() >= nId
? 0 : 1;
947 sal_uInt16 nLow
= nStartSearchAt
;
949 sal_uInt16 nHigh
= 0;
950 sal_Bool bFound
= sal_False
;
951 nHigh
= pImp
->pCaches
->size() - 1;
952 while ( !bFound
&& nLow
<= nHigh
)
954 nMid
= (nLow
+ nHigh
) >> 1;
955 DBG_ASSERT( nMid
< pImp
->pCaches
->size(), "bsearch is buggy" );
956 int nDiff
= (int) nId
- (int) ( ((*pImp
->pCaches
)[nMid
])->GetId() );
962 else if ( nDiff
> 0 )
970 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 pImp
->nCachedFunc2
= pImp
->nCachedFunc1
;
979 pImp
->nCachedFunc1
= nPos
;
980 DBG_PROFSTOP(SfxBindingsMsgPos
);
983 //--------------------------------------------------------------------
984 void SfxBindings::RegisterInternal_Impl( SfxControllerItem
& rItem
)
986 Register_Impl( rItem
, sal_True
);
990 void SfxBindings::Register( SfxControllerItem
& rItem
)
992 Register_Impl( rItem
, sal_False
);
995 void SfxBindings::Register_Impl( SfxControllerItem
& rItem
, sal_Bool bInternal
)
997 // DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
998 DBG_ASSERT( !pImp
->bInNextJob
, "SfxBindings::Register while status-updating" );
1000 // insert new cache if it does not already exist
1001 sal_uInt16 nId
= rItem
.GetId();
1002 sal_uInt16 nPos
= GetSlotPos(nId
);
1003 if ( nPos
>= pImp
->pCaches
->size() ||
1004 (*pImp
->pCaches
)[nPos
]->GetId() != nId
)
1006 SfxStateCache
* pCache
= new SfxStateCache(nId
);
1007 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 pImp
->bMsgDirty
= sal_True
;
1017 // enqueue the new binding
1020 (*pImp
->pCaches
)[nPos
]->SetInternalController( &rItem
);
1024 SfxControllerItem
*pOldItem
= (*pImp
->pCaches
)[nPos
]->ChangeItemLink(&rItem
);
1025 rItem
.ChangeItemLink(pOldItem
);
1029 //--------------------------------------------------------------------
1031 void SfxBindings::Release( SfxControllerItem
& rItem
)
1033 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1034 DBG_ASSERT( !pImp
->bInNextJob
, "SfxBindings::Release while status-updating" );
1035 ENTERREGISTRATIONS();
1037 // find the bound function
1038 sal_uInt16 nId
= rItem
.GetId();
1039 sal_uInt16 nPos
= GetSlotPos(nId
);
1040 SfxStateCache
* pCache
= (*pImp
->pCaches
)[nPos
];
1041 if ( pCache
->GetId() == nId
)
1043 if ( pCache
->GetInternalController() == &rItem
)
1045 pCache
->ReleaseInternalController();
1049 // is this the first binding in the list?
1050 SfxControllerItem
* pItem
= pCache
->GetItemLink();
1051 if ( pItem
== &rItem
)
1052 pCache
->ChangeItemLink( rItem
.GetItemLink() );
1055 // search the binding in the list
1056 while ( pItem
&& pItem
->GetItemLink() != &rItem
)
1057 pItem
= pItem
->GetItemLink();
1059 // unlink it if it was found
1061 pItem
->ChangeItemLink( rItem
.GetItemLink() );
1065 // was this the last controller?
1066 if ( pCache
->GetItemLink() == 0 && !pCache
->GetInternalController() )
1068 pImp
->bCtrlReleased
= sal_True
;
1072 LEAVEREGISTRATIONS();
1075 //--------------------------------------------------------------------
1076 const SfxPoolItem
* SfxBindings::ExecuteSynchron( sal_uInt16 nId
, const SfxPoolItem
** ppItems
, sal_uInt16 nModi
,
1077 const SfxPoolItem
**ppInternalArgs
)
1079 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1081 if( !nId
|| !pDispatcher
)
1084 return Execute_Impl( nId
, ppItems
, nModi
, SFX_CALLMODE_SYNCHRON
, ppInternalArgs
);
1087 sal_Bool
SfxBindings::Execute( sal_uInt16 nId
, const SfxPoolItem
** ppItems
, sal_uInt16 nModi
, SfxCallMode nCallMode
,
1088 const SfxPoolItem
**ppInternalArgs
)
1090 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1092 if( !nId
|| !pDispatcher
)
1095 const SfxPoolItem
* pRet
= Execute_Impl( nId
, ppItems
, nModi
, nCallMode
, ppInternalArgs
);
1096 return ( pRet
!= 0 );
1099 const SfxPoolItem
* SfxBindings::Execute_Impl( sal_uInt16 nId
, const SfxPoolItem
** ppItems
, sal_uInt16 nModi
, SfxCallMode nCallMode
,
1100 const SfxPoolItem
**ppInternalArgs
, sal_Bool bGlobalOnly
)
1102 SfxStateCache
*pCache
= GetStateCache( nId
);
1105 SfxBindings
*pBind
= pImp
->pSubBindings
;
1108 if ( pBind
->GetStateCache( nId
) )
1109 return pBind
->Execute_Impl( nId
, ppItems
, nModi
, nCallMode
, ppInternalArgs
, bGlobalOnly
);
1110 pBind
= pBind
->pImp
->pSubBindings
;
1114 SfxDispatcher
&rDispatcher
= *pDispatcher
;
1115 rDispatcher
.Flush();
1116 rDispatcher
.GetFrame(); // -Wall is this required???
1118 // get SlotServer (Slot+ShellLevel) and Shell from cache
1119 ::boost::scoped_ptr
<SfxStateCache
> xCache
;
1122 // Execution of non cached slots (Accelerators don't use Controllers)
1123 // slot is uncached, use SlotCache to handle external dispatch providers
1124 xCache
.reset(new SfxStateCache(nId
));
1125 pCache
= xCache
.get();
1126 pCache
->GetSlotServer( rDispatcher
, pImp
->xProv
);
1129 if ( pCache
&& pCache
->GetDispatch().is() )
1131 DBG_ASSERT( !ppInternalArgs
, "Internal args get lost when dispatched!" );
1133 SfxItemPool
&rPool
= GetDispatcher()->GetFrame()->GetObjectShell()->GetPool();
1134 SfxRequest
aReq( nId
, nCallMode
, rPool
);
1135 aReq
.SetModifier( nModi
);
1138 aReq
.AppendItem( **ppItems
++ );
1140 // cache binds to an external dispatch provider
1141 pCache
->Dispatch( aReq
.GetArgs(), nCallMode
== SFX_CALLMODE_SYNCHRON
);
1142 SfxPoolItem
*pVoid
= new SfxVoidItem( nId
);
1143 DeleteItemOnIdle( pVoid
);
1147 // slot is handled internally by SfxDispatcher
1148 if ( pImp
->bMsgDirty
)
1149 UpdateSlotServer_Impl();
1152 const SfxSlot
*pSlot
=0;
1154 // if slot was uncached, we should have created a cache in this method!
1155 DBG_ASSERT( pCache
, "This code needs a cache!");
1156 const SfxSlotServer
* pServer
= pCache
? pCache
->GetSlotServer( rDispatcher
, pImp
->xProv
) : 0;
1163 pShell
= rDispatcher
.GetShell( pServer
->GetShellLevel() );
1164 pSlot
= pServer
->GetSlot();
1168 if ( !pShell
->ISA(SfxModule
) && !pShell
->ISA(SfxApplication
) && !pShell
->ISA(SfxViewFrame
) )
1171 SfxItemPool
&rPool
= pShell
->GetPool();
1172 SfxRequest
aReq( nId
, nCallMode
, rPool
);
1173 aReq
.SetModifier( nModi
);
1176 aReq
.AppendItem( **ppItems
++ );
1177 if ( ppInternalArgs
)
1179 SfxAllItemSet
aSet( rPool
);
1180 for ( const SfxPoolItem
**pArg
= ppInternalArgs
; *pArg
; ++pArg
)
1182 aReq
.SetInternalArgs_Impl( aSet
);
1185 Execute_Impl( aReq
, pSlot
, pShell
);
1187 const SfxPoolItem
* pRet
= aReq
.GetReturnValue();
1190 SfxPoolItem
*pVoid
= new SfxVoidItem( nId
);
1191 DeleteItemOnIdle( pVoid
);
1198 void SfxBindings::Execute_Impl( SfxRequest
& aReq
, const SfxSlot
* pSlot
, SfxShell
* pShell
)
1200 SfxItemPool
&rPool
= pShell
->GetPool();
1202 if ( SFX_KIND_ENUM
== pSlot
->GetKind() )
1204 // for Enum-Slots, the Master has to be excecuted with the value
1206 const SfxSlot
*pRealSlot
= pShell
->GetInterface()->GetRealSlot(pSlot
);
1207 const sal_uInt16 nSlotId
= pRealSlot
->GetSlotId();
1208 aReq
.SetSlot( nSlotId
);
1209 aReq
.AppendItem( SfxAllEnumItem( rPool
.GetWhich(nSlotId
), pSlot
->GetValue() ) );
1210 pDispatcher
->_Execute( *pShell
, *pRealSlot
, aReq
, aReq
.GetCallMode() | SFX_CALLMODE_RECORD
);
1212 else if ( SFX_KIND_ATTR
== pSlot
->GetKind() )
1214 // Which value has to be mapped for Attribute slots
1215 const sal_uInt16 nSlotId
= pSlot
->GetSlotId();
1216 aReq
.SetSlot( nSlotId
);
1217 if ( pSlot
->IsMode(SFX_SLOT_TOGGLE
) )
1219 // The value is attached to a toggleable attribute (Bools)
1220 sal_uInt16 nWhich
= pSlot
->GetWhich(rPool
);
1221 SfxItemSet
aSet(rPool
, nWhich
, nWhich
);
1222 SfxStateFunc aFunc
= pSlot
->GetStateFnc();
1223 pShell
->CallState( aFunc
, aSet
);
1224 const SfxPoolItem
*pOldItem
;
1225 SfxItemState eState
= aSet
.GetItemState(nWhich
, sal_True
, &pOldItem
);
1226 if ( eState
== SFX_ITEM_DISABLED
)
1229 if ( SFX_ITEM_AVAILABLE
== eState
&& SfxItemPool::IsWhich(nWhich
) )
1230 pOldItem
= &aSet
.Get(nWhich
);
1232 if ( SFX_ITEM_SET
== eState
||
1233 ( SFX_ITEM_AVAILABLE
== eState
&&
1234 SfxItemPool::IsWhich(nWhich
) &&
1237 if ( pOldItem
->ISA(SfxBoolItem
) )
1239 // we can toggle Bools
1240 sal_Bool bOldValue
= ((const SfxBoolItem
*)pOldItem
)->GetValue();
1241 SfxBoolItem
*pNewItem
= (SfxBoolItem
*) (pOldItem
->Clone());
1242 pNewItem
->SetValue( !bOldValue
);
1243 aReq
.AppendItem( *pNewItem
);
1246 else if ( pOldItem
->ISA(SfxEnumItemInterface
) &&
1247 ((SfxEnumItemInterface
*)pOldItem
)->HasBoolValue())
1249 // and Enums with Bool-Interface
1250 SfxEnumItemInterface
*pNewItem
=
1251 (SfxEnumItemInterface
*) (pOldItem
->Clone());
1252 pNewItem
->SetBoolValue(!((SfxEnumItemInterface
*)pOldItem
)->GetBoolValue());
1253 aReq
.AppendItem( *pNewItem
);
1257 OSL_FAIL( "Toggle only for Enums and Bools allowed" );
1260 else if ( SFX_ITEM_DONTCARE
== eState
)
1262 // Create one Status-Item for each Factory
1263 SfxPoolItem
*pNewItem
= pSlot
->GetType()->CreateItem();
1264 DBG_ASSERT( pNewItem
, "Toggle to slot without ItemFactory" );
1265 pNewItem
->SetWhich( nWhich
);
1267 if ( pNewItem
->ISA(SfxBoolItem
) )
1269 // we can toggle Bools
1270 ((SfxBoolItem
*)pNewItem
)->SetValue( sal_True
);
1271 aReq
.AppendItem( *pNewItem
);
1273 else if ( pNewItem
->ISA(SfxEnumItemInterface
) &&
1274 ((SfxEnumItemInterface
*)pNewItem
)->HasBoolValue())
1276 // and Enums with Bool-Interface
1277 ((SfxEnumItemInterface
*)pNewItem
)->SetBoolValue(sal_True
);
1278 aReq
.AppendItem( *pNewItem
);
1281 OSL_FAIL( "Toggle only for Enums and Bools allowed" );
1286 OSL_FAIL( "suspicious Toggle-Slot" );
1290 pDispatcher
->_Execute( *pShell
, *pSlot
, aReq
, aReq
.GetCallMode() | SFX_CALLMODE_RECORD
);
1293 pDispatcher
->_Execute( *pShell
, *pSlot
, aReq
, aReq
.GetCallMode() | SFX_CALLMODE_RECORD
);
1296 //--------------------------------------------------------------------
1298 void SfxBindings::UpdateSlotServer_Impl()
1300 DBG_PROFSTART(SfxBindingsUpdateServers
);
1301 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1304 pDispatcher
->Flush();
1306 if ( pImp
->bAllMsgDirty
)
1310 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> xFrame
1311 ( pDispatcher
->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY
);
1312 pImp
->bContextChanged
= sal_False
;
1315 pImp
->bContextChanged
= sal_True
;
1318 for (size_t i
= 0, nCount
= pImp
->pCaches
->size(); i
< nCount
; ++i
)
1320 SfxStateCache
*pCache
= (*pImp
->pCaches
)[i
];
1321 //GetSlotServer can modify pImp->pCaches
1322 pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1324 pImp
->bMsgDirty
= pImp
->bAllMsgDirty
= sal_False
;
1326 Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED
) );
1328 DBG_PROFSTOP(SfxBindingsUpdateServers
);
1331 //--------------------------------------------------------------------
1333 SfxItemSet
* SfxBindings::CreateSet_Impl
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
1341 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1343 DBG_ASSERT( !pImp
->bMsgDirty
, "CreateSet_Impl with dirty MessageServer" );
1345 const SfxSlotServer
* pMsgSvr
= pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1346 if(!pMsgSvr
|| !pDispatcher
)
1349 DBG_PROFSTART(SfxBindingsCreateSet
);
1351 *pMsgServer
= pMsgSvr
;
1353 sal_uInt16 nShellLevel
= pMsgSvr
->GetShellLevel();
1354 SfxShell
*pShell
= pDispatcher
->GetShell( nShellLevel
);
1355 if ( !pShell
) // rare GPF when browsing through update from Inet-Notify
1358 SfxItemPool
&rPool
= pShell
->GetPool();
1360 // get the status method, which is served by the pCache
1361 SfxStateFunc pFnc
= 0;
1362 const SfxInterface
*pInterface
= pShell
->GetInterface();
1363 if ( SFX_KIND_ENUM
== pMsgSvr
->GetSlot()->GetKind() )
1365 pRealSlot
= pInterface
->GetRealSlot(pMsgSvr
->GetSlot());
1366 pCache
= GetStateCache( pRealSlot
->GetSlotId() );
1369 pRealSlot
= pMsgSvr
->GetSlot();
1371 // Note: pCache can be NULL!
1373 pFnc
= pRealSlot
->GetStateFnc();
1375 // the RealSlot is always on
1376 SfxFoundCache_Impl
*pFound
= new SfxFoundCache_Impl(
1377 pRealSlot
->GetSlotId(), pRealSlot
->GetWhich(rPool
), pRealSlot
, pCache
);
1378 rFound
.push_back( pFound
);
1380 sal_uInt16 nSlot
= pRealSlot
->GetSlotId();
1381 if ( !(nSlot
>= SID_VERB_START
&& nSlot
<= SID_VERB_END
) )
1383 pInterface
= pInterface
->GetRealInterfaceForSlot( pRealSlot
);
1384 DBG_ASSERT (pInterface
,"Slot in the given shell is not found");
1387 // Search through the bindings for slots served by the same function. This , // will only affect slots which are present in the found interface.
1389 // The position of the Statecaches in StateCache-Array
1390 sal_uInt16 nCachePos
= pImp
->nMsgPos
;
1391 const SfxSlot
*pSibling
= pRealSlot
->GetNextSlot();
1393 // the Slots ODF a interfaces ar linked in a circle
1394 while ( pSibling
> pRealSlot
)
1396 SfxStateFunc pSiblingFnc
=0;
1397 SfxStateCache
*pSiblingCache
=
1398 GetStateCache( pSibling
->GetSlotId(), &nCachePos
);
1400 // Is the slot cached ?
1401 if ( pSiblingCache
)
1403 const SfxSlotServer
*pServ
= pSiblingCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1404 if ( pServ
&& pServ
->GetShellLevel() == nShellLevel
)
1405 pSiblingFnc
= pServ
->GetSlot()->GetStateFnc();
1408 // Does the slot have to be updated at all?
1409 bool bInsert
= pSiblingCache
&& pSiblingCache
->IsControllerDirty();
1411 // It is not enough to ask for the same shell!!
1412 bool bSameMethod
= pSiblingCache
&& pFnc
== pSiblingFnc
;
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 if ( !bInsert
&& bSameMethod
&& pSibling
->GetLinkedSlot() )
1418 // Also check slave slots for Binding
1419 const SfxSlot
* pFirstSlave
= pSibling
->GetLinkedSlot();
1420 for ( const SfxSlot
*pSlaveSlot
= pFirstSlave
;
1422 pSlaveSlot
= pSlaveSlot
->GetNextSlot())
1424 // the slaves points to its master
1425 DBG_ASSERT(pSlaveSlot
->GetLinkedSlot() == pSibling
,
1426 "Wrong Master/Slave relationship!");
1428 sal_uInt16 nCurMsgPos
= pImp
->nMsgPos
;
1429 const SfxStateCache
*pSlaveCache
=
1430 GetStateCache( pSlaveSlot
->GetSlotId(), &nCurMsgPos
);
1432 // Is the slave slot chached and dirty ?
1433 bInsert
= pSlaveCache
&& pSlaveCache
->IsControllerDirty();
1435 // Slaves are chained together in a circle
1436 if (pSlaveSlot
->GetNextSlot() == pFirstSlave
)
1441 if ( bInsert
&& bSameMethod
)
1443 SfxFoundCache_Impl
*pFoundCache
= new SfxFoundCache_Impl(
1444 pSibling
->GetSlotId(), pSibling
->GetWhich(rPool
),
1445 pSibling
, pSiblingCache
);
1447 rFound
.push_back( pFoundCache
);
1450 pSibling
= pSibling
->GetNextSlot();
1453 // Create a Set from the ranges
1454 sal_uInt16
*pRanges
= new sal_uInt16
[rFound
.size() * 2 + 1];
1457 while ( i
< rFound
.size() )
1459 pRanges
[j
++] = rFound
[i
]->nWhichId
;
1460 // consecutive numbers
1461 for ( ; i
< rFound
.size()-1; ++i
)
1462 if ( rFound
[i
]->nWhichId
+1 != rFound
[i
+1]->nWhichId
)
1464 pRanges
[j
++] = rFound
[i
++]->nWhichId
;
1466 pRanges
[j
] = 0; // terminating NULL
1467 SfxItemSet
*pSet
= new SfxItemSet(rPool
, pRanges
);
1469 DBG_PROFSTOP(SfxBindingsCreateSet
);
1473 //--------------------------------------------------------------------
1475 void SfxBindings::UpdateControllers_Impl
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
1483 DBG_ASSERT( !pFound
->pSlot
|| SFX_KIND_ENUM
!= pFound
->pSlot
->GetKind(),
1484 "direct update of enum slot isn't allowed" );
1485 DBG_PROFSTART(SfxBindingsUpdateCtrl1
);
1487 SfxStateCache
* pCache
= pFound
->pCache
;
1488 const SfxSlot
* pSlot
= pFound
->pSlot
;
1489 DBG_ASSERT( !pCache
|| !pSlot
|| pCache
->GetId() == pSlot
->GetSlotId(), "SID mismatch" );
1491 // bound until now, the Controller to update the Slot.
1492 if ( pCache
&& pCache
->IsControllerDirty() )
1494 if ( SFX_ITEM_DONTCARE
== eState
)
1497 pCache
->SetState( SFX_ITEM_DONTCARE
, (SfxPoolItem
*)-1 );
1499 else if ( SFX_ITEM_DEFAULT
== eState
&&
1500 pFound
->nWhichId
> SFX_WHICH_MAX
)
1502 // no Status or Default but without Pool
1503 SfxVoidItem
aVoid(0);
1504 pCache
->SetState( SFX_ITEM_UNKNOWN
, &aVoid
);
1506 else if ( SFX_ITEM_DISABLED
== eState
)
1507 pCache
->SetState(SFX_ITEM_DISABLED
, 0);
1509 pCache
->SetState(SFX_ITEM_AVAILABLE
, pItem
);
1512 DBG_PROFSTOP(SfxBindingsUpdateCtrl1
);
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 const SfxSlot
*pFirstSlave
= pSlot
? pSlot
->GetLinkedSlot() : 0;
1521 if ( pIF
&& pFirstSlave
)
1523 // Items cast on EnumItem
1524 const SfxEnumItemInterface
*pEnumItem
=
1525 PTR_CAST(SfxEnumItemInterface
,pItem
);
1526 if ( eState
== SFX_ITEM_AVAILABLE
&& !pEnumItem
)
1527 eState
= SFX_ITEM_DONTCARE
;
1529 eState
= SfxControllerItem::GetItemState( pEnumItem
);
1531 // Iterate over all Slaves-Slots
1532 for ( const SfxSlot
*pSlave
= pFirstSlave
; pSlave
; pSlave
= pSlave
->GetNextSlot() )
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!");
1538 // Binding exist for function ?
1539 SfxStateCache
*pEnumCache
= GetStateCache( pSlave
->GetSlotId() );
1542 pEnumCache
->Invalidate(sal_False
);
1544 // HACK(CONTROL/SELECT Kram) ???
1545 if ( eState
== SFX_ITEM_DONTCARE
&& pFound
->nWhichId
== 10144 )
1547 SfxVoidItem
aVoid(0);
1548 pEnumCache
->SetState( SFX_ITEM_UNKNOWN
, &aVoid
);
1550 if (pSlave
->GetNextSlot() == pFirstSlave
)
1556 if ( SFX_ITEM_DISABLED
== eState
|| !pEnumItem
->IsEnabled( pSlave
->GetSlotId()) )
1559 pEnumCache
->SetState(SFX_ITEM_DISABLED
, 0);
1561 else if ( SFX_ITEM_AVAILABLE
== eState
)
1563 // Determine enum value
1564 sal_uInt16 nValue
= pEnumItem
->GetEnumValue();
1565 SfxBoolItem
aBool( pFound
->nWhichId
, pSlave
->GetValue() == nValue
);
1566 pEnumCache
->SetState(SFX_ITEM_AVAILABLE
, &aBool
);
1571 pEnumCache
->SetState( SFX_ITEM_DONTCARE
, (SfxPoolItem
*)-1 );
1575 if (pSlave
->GetNextSlot() == pFirstSlave
)
1580 DBG_PROFSTOP(SfxBindingsUpdateCtrl2
);
1584 //--------------------------------------------------------------------
1586 IMPL_LINK( SfxBindings
, NextJob_Impl
, Timer
*, pTimer
)
1589 // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT
1590 // or another MS library try to get them here
1594 const unsigned MAX_INPUT_DELAY
= 200;
1596 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1598 DBG_PROFSTART(SfxBindingsNextJob_Impl0
);
1600 if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY
&& pTimer
)
1602 pImp
->aTimer
.SetTimeout(TIMEOUT_UPDATING
);
1606 SfxApplication
*pSfxApp
= SFX_APP();
1609 pDispatcher
->Update_Impl();
1611 // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
1612 SfxViewFrame
* pFrame
= pDispatcher
->GetFrame();
1613 if ( (pFrame
&& !pFrame
->GetObjectShell()->AcceptStateUpdate()) || pSfxApp
->IsDowning() || pImp
->pCaches
->empty() )
1615 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1618 if ( !pDispatcher
|| !pDispatcher
->IsFlushed() )
1620 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1624 // if possible Update all server / happens in its own time slice
1625 if ( pImp
->bMsgDirty
)
1627 UpdateSlotServer_Impl();
1628 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1632 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1633 DBG_PROFSTART(SfxBindingsNextJob_Impl
);
1634 pImp
->bAllDirty
= sal_False
;
1635 pImp
->aTimer
.SetTimeout(TIMEOUT_UPDATING
);
1637 // at least 10 loops and further if more jobs are available but no input
1638 bool bPreEmptive
= pTimer
&& !pSfxApp
->Get_Impl()->nInReschedule
;
1639 sal_uInt16 nLoops
= 10;
1640 pImp
->bInNextJob
= sal_True
;
1641 const sal_uInt16 nCount
= pImp
->pCaches
->size();
1642 while ( pImp
->nMsgPos
< nCount
)
1644 // iterate through the bound functions
1645 sal_Bool bJobDone
= sal_False
;
1648 SfxStateCache
* pCache
= (*pImp
->pCaches
)[pImp
->nMsgPos
];
1649 DBG_ASSERT( pCache
, "invalid SfxStateCache-position in job queue" );
1650 sal_Bool bWasDirty
= pCache
->IsControllerDirty();
1653 Update_Impl( pCache
);
1654 DBG_ASSERT( nCount
== pImp
->pCaches
->size(),
1655 "Reschedule in StateChanged => buff" );
1658 // skip to next function binding
1661 // keep job if it is not completed, but any input is available
1662 bJobDone
= pImp
->nMsgPos
>= nCount
;
1663 if ( bJobDone
&& pImp
->bFirstRound
)
1666 // Update of the preferred shell has been done, now may
1667 // also the others shells be updated
1668 bJobDone
= sal_False
;
1669 pImp
->bFirstRound
= sal_False
;
1673 if ( bWasDirty
&& !bJobDone
&& bPreEmptive
&& (--nLoops
== 0) )
1675 DBG_PROFSTOP(SfxBindingsNextJob_Impl
);
1676 pImp
->bInNextJob
= sal_False
;
1684 // check for volatile slots
1685 bool bVolatileSlotsPresent
= false;
1686 for ( sal_uInt16 n
= 0; n
< nCount
; ++n
)
1688 SfxStateCache
* pCache
= (*pImp
->pCaches
)[n
];
1689 const SfxSlotServer
*pSlotServer
= pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1690 if ( pSlotServer
&& pSlotServer
->GetSlot()->IsMode(SFX_SLOT_VOLATILE
) )
1692 pCache
->Invalidate(sal_False
);
1693 bVolatileSlotsPresent
= true;
1697 if (bVolatileSlotsPresent
)
1698 pImp
->aTimer
.SetTimeout(TIMEOUT_IDLE
);
1700 pImp
->aTimer
.Stop();
1702 // Update round is finished
1703 pImp
->bInNextJob
= sal_False
;
1704 Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE
));
1705 DBG_PROFSTOP(SfxBindingsNextJob_Impl
);
1711 OSL_FAIL("C++ exception caught!");
1712 pImp
->bInNextJob
= sal_False
;
1719 //--------------------------------------------------------------------
1721 sal_uInt16
SfxBindings::EnterRegistrations(const char *pFile
, int nLine
)
1725 std::setw(std::min(nRegLevel
, sal_uInt16(8))) << ' ' << "this = " << this
1726 << " Level = " << nRegLevel
<< " SfxBindings::EnterRegistrations "
1728 ? SAL_STREAM("File: " << pFile
<< " Line: " << nLine
) : ""));
1730 // When bindings are locked, also lock sub bindings.
1731 if ( pImp
->pSubBindings
)
1733 pImp
->pSubBindings
->ENTERREGISTRATIONS();
1735 // These EnterRegistrations are not "real" for the SubBindings
1736 pImp
->pSubBindings
->pImp
->nOwnRegLevel
--;
1738 // Synchronize Bindings
1739 pImp
->pSubBindings
->nRegLevel
= nRegLevel
+ pImp
->pSubBindings
->pImp
->nOwnRegLevel
+ 1;
1742 pImp
->nOwnRegLevel
++;
1744 // check if this is the outer most level
1745 if ( ++nRegLevel
== 1 )
1747 // stop background-processing
1748 pImp
->aTimer
.Stop();
1751 pImp
->nCachedFunc1
= 0;
1752 pImp
->nCachedFunc2
= 0;
1754 // Mark if the all of the Caches have dissapered.
1755 pImp
->bCtrlReleased
= sal_False
;
1760 //--------------------------------------------------------------------
1762 void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel
, const char *pFile
, int nLine
)
1764 (void)nLevel
; // unused variable
1765 DBG_ASSERT( nRegLevel
, "Leave without Enter" );
1766 DBG_ASSERT( nLevel
== USHRT_MAX
|| nLevel
== nRegLevel
, "wrong Leave" );
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 if ( pImp
->pSubBindings
&& pImp
->pSubBindings
->nRegLevel
> pImp
->pSubBindings
->pImp
->nOwnRegLevel
)
1772 // Synchronize Bindings
1773 pImp
->pSubBindings
->nRegLevel
= nRegLevel
+ pImp
->pSubBindings
->pImp
->nOwnRegLevel
;
1775 // This LeaveRegistrations is not "real" for SubBindings
1776 pImp
->pSubBindings
->pImp
->nOwnRegLevel
++;
1777 pImp
->pSubBindings
->LEAVEREGISTRATIONS();
1780 pImp
->nOwnRegLevel
--;
1782 // check if this is the outer most level
1783 if ( --nRegLevel
== 0 && !SFX_APP()->IsDowning() )
1785 if ( pImp
->bContextChanged
)
1787 pImp
->bContextChanged
= sal_False
;
1790 SfxViewFrame
* pFrame
= pDispatcher
->GetFrame();
1792 // If possible remove unused Caches, for example prepare PlugInInfo
1793 if ( pImp
->bCtrlReleased
)
1795 for ( sal_uInt16 nCache
= pImp
->pCaches
->size(); nCache
> 0; --nCache
)
1797 // Get Cache via ::com::sun::star::sdbcx::Index
1798 SfxStateCache
*pCache
= (*pImp
->pCaches
)[nCache
-1];
1800 // No interested Controller present
1801 if ( pCache
->GetItemLink() == 0 && !pCache
->GetInternalController() )
1803 // Remove Cache. Safety: first remove and then delete
1804 pImp
->pCaches
->erase(pImp
->pCaches
->begin() + nCache
- 1);
1810 // restart background-processing
1812 if ( !pFrame
|| !pFrame
->GetObjectShell() )
1814 if ( pImp
->pCaches
&& !pImp
->pCaches
->empty() )
1816 pImp
->aTimer
.Stop();
1817 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
1818 pImp
->aTimer
.Start();
1824 std::setw(std::min(nRegLevel
, sal_uInt16(8))) << ' ' << "this = " << this
1825 << " Level = " << nRegLevel
<< " SfxBindings::LeaveRegistrations "
1827 ? SAL_STREAM("File: " << pFile
<< " Line: " << nLine
) : ""));
1830 //--------------------------------------------------------------------
1832 const SfxSlot
* SfxBindings::GetSlot(sal_uInt16 nSlotId
)
1834 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1837 pDispatcher
->Flush();
1838 if ( pImp
->bMsgDirty
)
1839 UpdateSlotServer_Impl();
1841 // get the cache for the specified function; return if not bound
1842 SfxStateCache
* pCache
= GetStateCache(nSlotId
);
1843 return pCache
&& pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
)?
1844 pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
)->GetSlot(): 0;
1847 //--------------------------------------------------------------------
1849 void SfxBindings::SetDispatcher( SfxDispatcher
*pDisp
)
1851 SfxDispatcher
*pOldDispat
= pDispatcher
;
1852 if ( pDisp
!= pDispatcher
)
1856 SfxBindings
* pBind
= pOldDispat
->GetBindings();
1859 if ( pBind
->pImp
->pSubBindings
== this && pBind
->pDispatcher
!= pDisp
)
1860 pBind
->SetSubBindings_Impl( NULL
);
1861 pBind
= pBind
->pImp
->pSubBindings
;
1865 pDispatcher
= pDisp
;
1867 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> xProv
;
1869 xProv
= ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
>
1870 ( pDisp
->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY
);
1872 SetDispatchProvider_Impl( xProv
);
1873 InvalidateAll( sal_True
);
1874 InvalidateUnoControllers_Impl();
1876 if ( pDispatcher
&& !pOldDispat
)
1878 if ( pImp
->pSubBindings
&& pImp
->pSubBindings
->pDispatcher
!= pOldDispat
)
1880 OSL_FAIL( "SubBindings already set before activating!" );
1881 pImp
->pSubBindings
->ENTERREGISTRATIONS();
1883 LEAVEREGISTRATIONS();
1885 else if( !pDispatcher
)
1887 ENTERREGISTRATIONS();
1888 if ( pImp
->pSubBindings
&& pImp
->pSubBindings
->pDispatcher
!= pOldDispat
)
1890 OSL_FAIL( "SubBindings still set even when deactivating!" );
1891 pImp
->pSubBindings
->LEAVEREGISTRATIONS();
1895 Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED
) );
1899 SfxBindings
* pBind
= pDisp
->GetBindings();
1900 while ( pBind
&& pBind
!= this )
1902 if ( !pBind
->pImp
->pSubBindings
)
1904 pBind
->SetSubBindings_Impl( this );
1908 pBind
= pBind
->pImp
->pSubBindings
;
1914 //--------------------------------------------------------------------
1916 void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId
)
1918 GetStateCache(nSlotId
)->ClearCache();
1921 //--------------------------------------------------------------------
1922 void SfxBindings::StartUpdate_Impl( sal_Bool bComplete
)
1924 if ( pImp
->pSubBindings
)
1925 pImp
->pSubBindings
->StartUpdate_Impl( bComplete
);
1928 // Update may be interrupted
1929 NextJob_Impl(&pImp
->aTimer
);
1931 // Update all slots in a row
1935 //-------------------------------------------------------------------------
1937 SfxItemState
SfxBindings::QueryState( sal_uInt16 nSlot
, SfxPoolItem
* &rpState
)
1939 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
1940 SfxStateCache
*pCache
= GetStateCache( nSlot
);
1942 xDisp
= pCache
->GetDispatch();
1943 if ( xDisp
.is() || !pCache
)
1945 const SfxSlot
* pSlot
= SfxSlotPool::GetSlotPool( pDispatcher
->GetFrame() ).GetSlot( nSlot
);
1946 if ( !pSlot
|| !pSlot
->pUnoName
)
1947 return SFX_ITEM_DISABLED
;
1949 ::com::sun::star::util::URL aURL
;
1950 OUString
aCmd( ".uno:" );
1951 aURL
.Protocol
= aCmd
;
1952 aURL
.Path
= OUString::createFromAscii(pSlot
->GetUnoName());
1954 aURL
.Complete
= aCmd
;
1958 xDisp
= pImp
->xProv
->queryDispatch( aURL
, OUString(), 0 );
1962 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XUnoTunnel
> xTunnel( xDisp
, ::com::sun::star::uno::UNO_QUERY
);
1963 SfxOfficeDispatch
* pDisp
= NULL
;
1966 sal_Int64 nImplementation
= xTunnel
->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
1967 pDisp
= reinterpret_cast< SfxOfficeDispatch
* >( sal::static_int_cast
< sal_IntPtr
>( nImplementation
));
1972 sal_Bool bDeleteCache
= sal_False
;
1975 pCache
= new SfxStateCache( nSlot
);
1976 pCache
->GetSlotServer( *GetDispatcher_Impl(), pImp
->xProv
);
1977 bDeleteCache
= sal_True
;
1980 SfxItemState eState
= SFX_ITEM_SET
;
1981 SfxPoolItem
*pItem
=NULL
;
1982 BindDispatch_Impl
*pBind
= new BindDispatch_Impl( xDisp
, aURL
, pCache
, pSlot
);
1984 xDisp
->addStatusListener( pBind
, aURL
);
1985 if ( !pBind
->GetStatus().IsEnabled
)
1987 eState
= SFX_ITEM_DISABLED
;
1991 ::com::sun::star::uno::Any aAny
= pBind
->GetStatus().State
;
1992 ::com::sun::star::uno::Type pType
= aAny
.getValueType();
1994 if ( pType
== ::getBooleanCppuType() )
1996 sal_Bool bTemp
= false;
1998 pItem
= new SfxBoolItem( nSlot
, bTemp
);
2000 else if ( pType
== ::getCppuType((const sal_uInt16
*)0) )
2002 sal_uInt16 nTemp
= 0;
2004 pItem
= new SfxUInt16Item( nSlot
, nTemp
);
2006 else if ( pType
== ::getCppuType((const sal_uInt32
*)0) )
2008 sal_uInt32 nTemp
= 0;
2010 pItem
= new SfxUInt32Item( nSlot
, nTemp
);
2012 else if ( pType
== ::getCppuType((const OUString
*)0) )
2016 pItem
= new SfxStringItem( nSlot
, sTemp
);
2019 pItem
= new SfxVoidItem( nSlot
);
2022 xDisp
->removeStatusListener( pBind
, aURL
);
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 const SfxPoolItem
*pItem
= NULL
;
2036 SfxItemState eState
= pDispatcher
->QueryState( nSlot
, pItem
);
2037 if ( eState
== SFX_ITEM_SET
)
2039 DBG_ASSERT( pItem
, "SFX_ITEM_SET but no item!" );
2041 rpState
= pItem
->Clone();
2043 else if ( eState
== SFX_ITEM_AVAILABLE
&& pItem
)
2045 rpState
= pItem
->Clone();
2051 void SfxBindings::SetSubBindings_Impl( SfxBindings
*pSub
)
2053 if ( pImp
->pSubBindings
)
2055 pImp
->pSubBindings
->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> () );
2056 pImp
->pSubBindings
->pImp
->pSuperBindings
= NULL
;
2059 pImp
->pSubBindings
= pSub
;
2063 pImp
->pSubBindings
->SetDispatchProvider_Impl( pImp
->xProv
);
2064 pSub
->pImp
->pSuperBindings
= this;
2068 SfxBindings
* SfxBindings::GetSubBindings_Impl( sal_Bool bTop
) const
2070 SfxBindings
*pRet
= pImp
->pSubBindings
;
2073 while ( pRet
->pImp
->pSubBindings
)
2074 pRet
= pRet
->pImp
->pSubBindings
;
2080 void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow
* pWork
)
2082 pImp
->pWorkWin
= pWork
;
2085 SfxWorkWindow
* SfxBindings::GetWorkWindow_Impl() const
2087 return pImp
->pWorkWin
;
2090 void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem
* pControl
)
2092 if ( !pImp
->pUnoCtrlArr
)
2093 pImp
->pUnoCtrlArr
= new SfxUnoControllerArr_Impl
;
2094 pImp
->pUnoCtrlArr
->push_back( pControl
);
2097 void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem
* pControl
)
2099 if ( pImp
->pUnoCtrlArr
)
2101 SfxUnoControllerArr_Impl::iterator it
= std::find(
2102 pImp
->pUnoCtrlArr
->begin(), pImp
->pUnoCtrlArr
->end(), pControl
);
2103 if ( it
!= pImp
->pUnoCtrlArr
->end() )
2105 pImp
->pUnoCtrlArr
->erase( it
);
2110 if ( pImp
->pSubBindings
)
2111 pImp
->pSubBindings
->ReleaseUnoController_Impl( pControl
);
2114 void SfxBindings::InvalidateUnoControllers_Impl()
2116 if ( pImp
->pUnoCtrlArr
)
2118 sal_uInt16 nCount
= pImp
->pUnoCtrlArr
->size();
2119 for ( sal_uInt16 n
=nCount
; n
>0; n
-- )
2121 SfxUnoControllerItem
*pCtrl
= (*pImp
->pUnoCtrlArr
)[n
-1];
2122 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XStatusListener
> xRef( (::cppu::OWeakObject
*)pCtrl
, ::com::sun::star::uno::UNO_QUERY
);
2123 pCtrl
->ReleaseDispatch();
2124 pCtrl
->GetNewDispatch();
2128 if ( pImp
->pSubBindings
)
2129 pImp
->pSubBindings
->InvalidateUnoControllers_Impl();
2132 sal_Bool
SfxBindings::IsInUpdate() const
2134 sal_Bool bInUpdate
= pImp
->bInUpdate
;
2135 if ( !bInUpdate
&& pImp
->pSubBindings
)
2136 bInUpdate
= pImp
->pSubBindings
->IsInUpdate();
2140 void SfxBindings::SetVisibleState( sal_uInt16 nId
, sal_Bool bShow
)
2142 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
2143 SfxStateCache
*pCache
= GetStateCache( nId
);
2145 pCache
->SetVisibleState( bShow
);
2148 void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> & rFrame
)
2150 if ( rFrame
.is() || !pDispatcher
)
2151 SetDispatchProvider_Impl( ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> ( rFrame
, ::com::sun::star::uno::UNO_QUERY
) );
2153 SetDispatchProvider_Impl( ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> (
2154 pDispatcher
->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY
) );
2157 const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> SfxBindings::GetActiveFrame() const
2159 const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> xFrame( pImp
->xProv
, ::com::sun::star::uno::UNO_QUERY
);
2160 if ( xFrame
.is() || !pDispatcher
)
2163 return pDispatcher
->GetFrame()->GetFrame().GetFrameInterface();
2166 void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> & rProv
)
2168 sal_Bool bInvalidate
= ( rProv
!= pImp
->xProv
);
2171 pImp
->xProv
= rProv
;
2172 InvalidateAll( sal_True
);
2173 InvalidateUnoControllers_Impl();
2176 if ( pImp
->pSubBindings
)
2177 pImp
->pSubBindings
->SetDispatchProvider_Impl( pImp
->xProv
);
2180 const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> & SfxBindings::GetDispatchProvider_Impl() const
2185 SystemWindow
* SfxBindings::GetSystemWindow() const
2187 SfxViewFrame
*pFrame
= pDispatcher
->GetFrame();
2188 while ( pFrame
->GetParentViewFrame_Impl() )
2189 pFrame
= pFrame
->GetParentViewFrame_Impl();
2190 SfxViewFrame
* pTop
= pFrame
->GetTopViewFrame();
2191 return pTop
->GetFrame().GetTopWindow_Impl();
2194 sal_Bool
SfxBindings::ExecuteCommand_Impl( const String
& rCommand
)
2196 ::com::sun::star::util::URL aURL
;
2197 aURL
.Complete
= rCommand
;
2198 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2199 xTrans
->parseStrict( aURL
);
2200 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
= pImp
->xProv
->queryDispatch( aURL
, OUString(), 0 );
2203 new SfxAsyncExec_Impl( aURL
, xDisp
);
2210 com::sun::star::uno::Reference
< com::sun::star::frame::XDispatchRecorder
> SfxBindings::GetRecorder() const
2212 return pImp
->xRecorder
;
2215 void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference
< com::sun::star::frame::XDispatchRecorder
>& rRecorder
)
2217 pImp
->xRecorder
= rRecorder
;
2220 void SfxBindings::ContextChanged_Impl()
2222 if ( !pImp
->bInUpdate
&& ( !pImp
->bContextChanged
|| !pImp
->bAllMsgDirty
) )
2224 InvalidateAll( sal_True
);
2228 uno::Reference
< frame::XDispatch
> SfxBindings::GetDispatch( const SfxSlot
* pSlot
, const util::URL
& aURL
, sal_Bool bMasterCommand
)
2230 uno::Reference
< frame::XDispatch
> xRet
;
2231 SfxStateCache
* pCache
= GetStateCache( pSlot
->nSlotId
);
2232 if ( pCache
&& !bMasterCommand
)
2233 xRet
= pCache
->GetInternalDispatch();
2236 // dispatches for slaves are unbound, they don't have a state
2237 SfxOfficeDispatch
* pDispatch
= bMasterCommand
?
2238 new SfxOfficeDispatch( pDispatcher
, pSlot
, aURL
) :
2239 new SfxOfficeDispatch( *this, pDispatcher
, pSlot
, aURL
);
2241 pDispatch
->SetMasterUnoCommand( bMasterCommand
);
2242 xRet
= uno::Reference
< frame::XDispatch
>( pDispatch
);
2244 pCache
= GetStateCache( pSlot
->nSlotId
);
2246 DBG_ASSERT( pCache
, "No cache for OfficeDispatch!" );
2247 if ( pCache
&& !bMasterCommand
)
2248 pCache
->SetInternalDispatch( xRet
);
2254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */