| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sfx2.hxx" |
| |
| #include <hash_map> |
| #include <svl/itempool.hxx> |
| #include <svl/itemiter.hxx> |
| #include <svl/eitem.hxx> |
| #include <svl/aeitem.hxx> |
| #include <svl/intitem.hxx> |
| #include <svl/stritem.hxx> |
| #include <svl/visitem.hxx> |
| #include <com/sun/star/util/XURLTransformer.hpp> |
| #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp> |
| #include <com/sun/star/frame/XDispatch.hpp> |
| #include <com/sun/star/frame/XDispatchProvider.hpp> |
| #include <com/sun/star/frame/XStatusListener.hpp> |
| #include <com/sun/star/frame/FrameSearchFlag.hpp> |
| #include <com/sun/star/frame/XDispatchProviderInterception.hpp> |
| #include <com/sun/star/frame/FeatureStateEvent.hpp> |
| #include <com/sun/star/frame/DispatchDescriptor.hpp> |
| #include <com/sun/star/frame/XController.hpp> |
| #include <comphelper/processfactory.hxx> |
| #include <svtools/itemdel.hxx> |
| |
| #ifndef GCC |
| #endif |
| |
| // wg. nInReschedule |
| #include "appdata.hxx" |
| #include <sfx2/bindings.hxx> |
| #include <sfx2/msg.hxx> |
| #include "statcach.hxx" |
| #include <sfx2/ctrlitem.hxx> |
| #include <sfx2/app.hxx> |
| #include <sfx2/dispatch.hxx> |
| #include <sfx2/request.hxx> |
| #include <sfx2/objface.hxx> |
| #include "sfxtypes.hxx" |
| #include "workwin.hxx" |
| #include <sfx2/unoctitm.hxx> |
| #include <sfx2/sfx.hrc> |
| #include <sfx2/sfxuno.hxx> |
| #include <sfx2/viewfrm.hxx> |
| #include <sfx2/objsh.hxx> |
| #include <sfx2/msgpool.hxx> |
| |
| #include <comphelper/uieventslogger.hxx> |
| #include <com/sun/star/frame/XModuleManager.hpp> |
| |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::util; |
| |
| DBG_NAME(SfxBindingsMsgPos) |
| DBG_NAME(SfxBindingsUpdateServers) |
| DBG_NAME(SfxBindingsCreateSet) |
| DBG_NAME(SfxBindingsUpdateCtrl1) |
| DBG_NAME(SfxBindingsUpdateCtrl2) |
| DBG_NAME(SfxBindingsNextJob_Impl0) |
| DBG_NAME(SfxBindingsNextJob_Impl) |
| DBG_NAME(SfxBindingsUpdate_Impl) |
| DBG_NAME(SfxBindingsInvalidateAll) |
| |
| //==================================================================== |
| |
| static sal_uInt16 nTimeOut = 300; |
| |
| #define TIMEOUT_FIRST nTimeOut |
| #define TIMEOUT_UPDATING 20 |
| #define TIMEOUT_IDLE 2500 |
| |
| static sal_uInt32 nCache1 = 0; |
| static sal_uInt32 nCache2 = 0; |
| |
| typedef std::hash_map< sal_uInt16, bool > InvalidateSlotMap; |
| |
| //==================================================================== |
| |
| DECL_PTRARRAY(SfxStateCacheArr_Impl, SfxStateCache*, 32, 16) |
| |
| //==================================================================== |
| |
| class SfxAsyncExec_Impl |
| { |
| ::com::sun::star::util::URL aCommand; |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp; |
| Timer aTimer; |
| |
| public: |
| |
| SfxAsyncExec_Impl( const ::com::sun::star::util::URL& rCmd, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& rDisp ) |
| : aCommand( rCmd ) |
| , xDisp( rDisp ) |
| { |
| aTimer.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl, TimerHdl) ); |
| aTimer.SetTimeout( 0 ); |
| aTimer.Start(); |
| } |
| |
| DECL_LINK( TimerHdl, Timer*); |
| }; |
| |
| IMPL_LINK(SfxAsyncExec_Impl, TimerHdl, Timer*, pTimer) |
| { |
| (void)pTimer; // unused |
| aTimer.Stop(); |
| |
| Sequence<beans::PropertyValue> aSeq; |
| xDisp->dispatch( aCommand, aSeq ); |
| |
| delete this; |
| return 0L; |
| } |
| |
| class SfxBindings_Impl |
| { |
| public: |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchRecorder > xRecorder; |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv; |
| SfxUnoControllerArr_Impl* |
| pUnoCtrlArr; |
| SfxWorkWindow* pWorkWin; |
| SfxBindings* pSubBindings; |
| SfxBindings* pSuperBindings; |
| SfxStateCacheArr_Impl* pCaches; // je ein cache fuer jede gebundene |
| sal_uInt16 nCachedFunc1; // index der zuletzt gerufenen |
| sal_uInt16 nCachedFunc2; // index der vorletzt gerufenen |
| sal_uInt16 nMsgPos; // Message-Position, ab der zu aktualisieren ist |
| SfxPopupAction ePopupAction; // in DeleteFloatinWindow() abgefragt |
| sal_Bool bContextChanged; |
| sal_Bool bMsgDirty; // wurde ein MessageServer invalidiert? |
| sal_Bool bAllMsgDirty; // wurden die MessageServer invalidiert? |
| sal_Bool bAllDirty; // nach InvalidateAll |
| sal_Bool bCtrlReleased; // waehrend EnterRegistrations |
| AutoTimer aTimer; // fuer volatile Slots |
| sal_Bool bInUpdate; // fuer Assertions |
| sal_Bool bInNextJob; // fuer Assertions |
| sal_Bool bFirstRound; // Erste Runde im Update |
| sal_uInt16 nFirstShell; // Shell, die in erster Runde bevorzugt wird |
| sal_uInt16 nOwnRegLevel; // z"ahlt die echten Locks, ohne die der SuperBindings |
| InvalidateSlotMap m_aInvalidateSlots; // store slots which are invalidated while in update |
| }; |
| |
| //-------------------------------------------------------------------- |
| |
| struct SfxFoundCache_Impl |
| { |
| sal_uInt16 nSlotId; // die Slot-Id |
| sal_uInt16 nWhichId; // falls verf"ugbar die Which-Id, sonst nSlotId |
| const SfxSlot* pSlot; // Pointer auf den <Master-Slot> |
| SfxStateCache* pCache; // Pointer auf den StatusCache, ggf. 0 |
| |
| SfxFoundCache_Impl(): |
| nSlotId(0), |
| nWhichId(0), |
| pSlot(0), |
| pCache(0) |
| {} |
| |
| SfxFoundCache_Impl(SfxFoundCache_Impl&r): |
| nSlotId(r.nSlotId), |
| nWhichId(r.nWhichId), |
| pSlot(r.pSlot), |
| pCache(r.pCache) |
| {} |
| |
| SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ): |
| nSlotId(nS), |
| nWhichId(nW), |
| pSlot(pS), |
| pCache(pC) |
| {} |
| |
| int operator<( const SfxFoundCache_Impl &r ) const |
| { return nWhichId < r.nWhichId; } |
| |
| int operator==( const SfxFoundCache_Impl &r ) const |
| { return nWhichId== r.nWhichId; } |
| }; |
| |
| //-------------------------------------------------------------------------- |
| |
| SV_DECL_PTRARR_SORT_DEL(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*, 16, 16 ) |
| SV_IMPL_OP_PTRARR_SORT(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*); |
| |
| //========================================================================== |
| |
| SfxBindings::SfxBindings() |
| : pImp(new SfxBindings_Impl), |
| pDispatcher(0), |
| nRegLevel(1) // geht erst auf 0, wenn Dispatcher gesetzt |
| { |
| pImp->nMsgPos = 0; |
| pImp->bAllMsgDirty = sal_True; |
| pImp->bContextChanged = sal_False; |
| pImp->bMsgDirty = sal_True; |
| pImp->bAllDirty = sal_True; |
| pImp->ePopupAction = SFX_POPUP_DELETE; |
| pImp->nCachedFunc1 = 0; |
| pImp->nCachedFunc2 = 0; |
| pImp->bCtrlReleased = sal_False; |
| pImp->bFirstRound = sal_False; |
| pImp->bInNextJob = sal_False; |
| pImp->bInUpdate = sal_False; |
| pImp->pSubBindings = NULL; |
| pImp->pSuperBindings = NULL; |
| pImp->pWorkWin = NULL; |
| pImp->pUnoCtrlArr = NULL; |
| pImp->nOwnRegLevel = nRegLevel; |
| |
| // all caches are valid (no pending invalidate-job) |
| // create the list of caches |
| pImp->pCaches = new SfxStateCacheArr_Impl; |
| pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob_Impl) ); |
| } |
| |
| //==================================================================== |
| |
| SfxBindings::~SfxBindings() |
| |
| /* [Beschreibung] |
| |
| Destruktor der Klasse SfxBindings. Die eine, f"ur jede <SfxApplication> |
| existierende Instanz wird von der <SfxApplication> nach Ausf"urhung |
| von <SfxApplication::Exit()> automatisch zerst"ort. |
| |
| Noch existierende <SfxControllerItem> Instanzen, die bei dieser |
| SfxBindings Instanz angemeldet sind, werden im Destruktor |
| automatisch zerst"ort. Dies sind i.d.R. Floating-Toolboxen, Value-Sets |
| etc. Arrays von SfxControllerItems d"urfen zu diesem Zeitpunkt nicht |
| mehr exisitieren. |
| */ |
| |
| { |
| // Die SubBindings sollen ja nicht gelocked werden ! |
| pImp->pSubBindings = NULL; |
| |
| ENTERREGISTRATIONS(); |
| |
| pImp->aTimer.Stop(); |
| DeleteControllers_Impl(); |
| |
| // Caches selbst l"oschen |
| sal_uInt16 nCount = pImp->pCaches->Count(); |
| for ( sal_uInt16 nCache = 0; nCache < nCount; ++nCache ) |
| delete pImp->pCaches->GetObject(nCache); |
| |
| DELETEZ( pImp->pWorkWin ); |
| |
| delete pImp->pCaches; |
| delete pImp; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::DeleteControllers_Impl() |
| { |
| // in der ersten Runde den SfxPopupWindows l"oschen |
| sal_uInt16 nCount = pImp->pCaches->Count(); |
| sal_uInt16 nCache; |
| for ( nCache = 0; nCache < nCount; ++nCache ) |
| { |
| // merken wo man ist |
| SfxStateCache *pCache = pImp->pCaches->GetObject(nCache); |
| sal_uInt16 nSlotId = pCache->GetId(); |
| |
| // SfxPopupWindow l"oschen lassen |
| pCache->DeleteFloatingWindows(); |
| |
| // da der Cache verkleinert worden sein kann, wiederaufsetzen |
| sal_uInt16 nNewCount = pImp->pCaches->Count(); |
| if ( nNewCount < nCount ) |
| { |
| nCache = GetSlotPos(nSlotId); |
| if ( nCache >= nNewCount || |
| nSlotId != pImp->pCaches->GetObject(nCache)->GetId() ) |
| --nCache; |
| nCount = nNewCount; |
| } |
| } |
| |
| // alle Caches l"oschen |
| for ( nCache = pImp->pCaches->Count(); nCache > 0; --nCache ) |
| { |
| // Cache via ::com::sun::star::sdbcx::Index besorgen |
| SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1); |
| |
| // alle Controller in dem Cache unbinden |
| SfxControllerItem *pNext; |
| for ( SfxControllerItem *pCtrl = pCache->GetItemLink(); |
| pCtrl; pCtrl = pNext ) |
| { |
| pNext = pCtrl->GetItemLink(); |
| pCtrl->UnBind(); |
| } |
| |
| if ( pCache->GetInternalController() ) |
| pCache->GetInternalController()->UnBind(); |
| |
| // Cache l"oschen |
| if( nCache-1 < pImp->pCaches->Count() ) |
| delete (*pImp->pCaches)[nCache-1]; |
| pImp->pCaches->Remove(nCache-1, 1); |
| } |
| |
| if( pImp->pUnoCtrlArr ) |
| { |
| sal_uInt16 nCtrlCount = pImp->pUnoCtrlArr->Count(); |
| for ( sal_uInt16 n=nCtrlCount; n>0; n-- ) |
| { |
| SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1]; |
| pCtrl->ReleaseBindings(); |
| } |
| |
| DBG_ASSERT( !pImp->pUnoCtrlArr->Count(), "UnoControllerItems nicht entfernt!" ); |
| DELETEZ( pImp->pUnoCtrlArr ); |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| SfxPopupAction SfxBindings::GetPopupAction_Impl() const |
| { |
| return pImp->ePopupAction; |
| } |
| |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::HidePopups( bool bHide ) |
| { |
| // SfxPopupWindows hiden |
| HidePopupCtrls_Impl( bHide ); |
| SfxBindings *pSub = pImp->pSubBindings; |
| while ( pSub ) |
| { |
| pImp->pSubBindings->HidePopupCtrls_Impl( bHide ); |
| pSub = pSub->pImp->pSubBindings; |
| } |
| |
| // SfxChildWindows hiden |
| DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" ); |
| if ( pImp->pWorkWin ) |
| pImp->pWorkWin->HidePopups_Impl( bHide, sal_True ); |
| } |
| |
| void SfxBindings::HidePopupCtrls_Impl( FASTBOOL bHide ) |
| { |
| if ( bHide ) |
| { |
| // SfxPopupWindows hiden |
| pImp->ePopupAction = SFX_POPUP_HIDE; |
| } |
| else |
| { |
| // SfxPopupWindows showen |
| pImp->ePopupAction = SFX_POPUP_SHOW; |
| } |
| |
| for ( sal_uInt16 nCache = 0; nCache < pImp->pCaches->Count(); ++nCache ) |
| pImp->pCaches->GetObject(nCache)->DeleteFloatingWindows(); |
| pImp->ePopupAction = SFX_POPUP_DELETE; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Update_Impl |
| ( |
| SfxStateCache* pCache // der upzudatende SfxStatusCache |
| ) |
| { |
| if( pCache->GetDispatch().is() && pCache->GetItemLink() ) |
| { |
| pCache->SetCachedState(sal_True); |
| if ( !pCache->GetInternalController() ) |
| return; |
| } |
| |
| if ( !pDispatcher ) |
| return; |
| DBG_PROFSTART(SfxBindingsUpdate_Impl); |
| |
| // alle mit derselben Statusmethode zusammensammeln, die dirty sind |
| SfxDispatcher &rDispat = *pDispatcher; |
| const SfxSlot *pRealSlot = 0; |
| const SfxSlotServer* pMsgServer = 0; |
| SfxFoundCacheArr_Impl aFound; |
| SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound ); |
| sal_Bool bUpdated = sal_False; |
| if ( pSet ) |
| { |
| // Status erfragen |
| if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) ) |
| { |
| // Status posten |
| const SfxInterface *pInterface = |
| rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface(); |
| for ( sal_uInt16 nPos = 0; nPos < aFound.Count(); ++nPos ) |
| { |
| const SfxFoundCache_Impl *pFound = aFound[nPos]; |
| sal_uInt16 nWhich = pFound->nWhichId; |
| const SfxPoolItem *pItem = 0; |
| SfxItemState eState = pSet->GetItemState(nWhich, sal_True, &pItem); |
| if ( eState == SFX_ITEM_DEFAULT && SfxItemPool::IsWhich(nWhich) ) |
| pItem = &pSet->Get(nWhich); |
| UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState ); |
| } |
| bUpdated = sal_True; |
| } |
| |
| delete pSet; |
| } |
| |
| if ( !bUpdated && pCache ) |
| { |
| // Wenn pCache == NULL und kein SlotServer ( z.B. weil Dispatcher gelockt! ), |
| // darf nat"urlich kein Update versucht werden |
| SfxFoundCache_Impl aFoundCache( |
| pCache->GetId(), 0, |
| pRealSlot, pCache ); |
| UpdateControllers_Impl( 0, &aFoundCache, 0, SFX_ITEM_DISABLED); |
| } |
| |
| DBG_PROFSTOP(SfxBindingsUpdate_Impl); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::InvalidateSlotsInMap_Impl() |
| { |
| InvalidateSlotMap::const_iterator pIter = pImp->m_aInvalidateSlots.begin(); |
| while ( pIter != pImp->m_aInvalidateSlots.end() ) |
| { |
| Invalidate( pIter->first ); |
| ++pIter; |
| } |
| pImp->m_aInvalidateSlots.clear(); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( sal_uInt16 nId ) |
| { |
| pImp->m_aInvalidateSlots[nId] = sal_True; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Update |
| ( |
| sal_uInt16 nId // die gebundene und upzudatende Slot-Id |
| ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| //!!TLX: Fuehrte zu Vorlagenkatalogstillstand |
| // if ( nRegLevel ) |
| // return; |
| |
| if ( pDispatcher ) |
| pDispatcher->Flush(); |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Update( nId ); |
| |
| SfxStateCache* pCache = GetStateCache( nId ); |
| if ( pCache ) |
| { |
| pImp->bInUpdate = sal_True; |
| if ( pImp->bMsgDirty ) |
| { |
| UpdateSlotServer_Impl(); |
| pCache = GetStateCache( nId ); |
| } |
| |
| if (pCache) |
| { |
| sal_Bool bInternalUpdate = sal_True; |
| if( pCache->GetDispatch().is() && pCache->GetItemLink() ) |
| { |
| pCache->SetCachedState(sal_True); |
| bInternalUpdate = ( pCache->GetInternalController() != 0 ); |
| } |
| |
| if ( bInternalUpdate ) |
| { |
| // Status erfragen |
| const SfxSlotServer* pMsgServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| if ( !pCache->IsControllerDirty() && |
| ( !pMsgServer || |
| !pMsgServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) ) |
| { |
| pImp->bInUpdate = sal_False; |
| InvalidateSlotsInMap_Impl(); |
| return; |
| } |
| if (!pMsgServer) |
| { |
| pCache->SetState(SFX_ITEM_DISABLED, 0); |
| pImp->bInUpdate = sal_False; |
| InvalidateSlotsInMap_Impl(); |
| return; |
| } |
| |
| Update_Impl(pCache); |
| } |
| |
| pImp->bAllDirty = sal_False; |
| } |
| |
| pImp->bInUpdate = sal_False; |
| InvalidateSlotsInMap_Impl(); |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Update() |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Update(); |
| |
| if ( pDispatcher ) |
| { |
| if ( nRegLevel ) |
| return; |
| |
| pImp->bInUpdate = sal_True; |
| pDispatcher->Flush(); |
| pDispatcher->Update_Impl(); |
| while ( !NextJob_Impl(0) ) |
| ; // loop |
| pImp->bInUpdate = sal_False; |
| InvalidateSlotsInMap_Impl(); |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::SetState |
| ( |
| const SfxItemSet& rSet // zu setzende Status-Werte |
| ) |
| { |
| // wenn gelockt, dann nur invalidieren |
| if ( nRegLevel ) |
| { |
| SfxItemIter aIter(rSet); |
| for ( const SfxPoolItem *pItem = aIter.FirstItem(); |
| pItem; |
| pItem = aIter.NextItem() ) |
| Invalidate( pItem->Which() ); |
| } |
| else |
| { |
| // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind |
| if ( pImp->bMsgDirty ) |
| UpdateSlotServer_Impl(); |
| |
| // "uber das ItemSet iterieren, falls Slot gebunden, updaten |
| //! Bug: WhichIter verwenden und ggf. VoidItems hochschicken |
| SfxItemIter aIter(rSet); |
| for ( const SfxPoolItem *pItem = aIter.FirstItem(); |
| pItem; |
| pItem = aIter.NextItem() ) |
| { |
| SfxStateCache* pCache = |
| GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) ); |
| if ( pCache ) |
| { |
| // Status updaten |
| if ( !pCache->IsControllerDirty() ) |
| pCache->Invalidate(sal_False); |
| pCache->SetState( SFX_ITEM_AVAILABLE, pItem ); |
| |
| //! nicht implementiert: Updates von EnumSlots via MasterSlots |
| } |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::SetState |
| ( |
| const SfxPoolItem& rItem // zu setzender Status-Wert |
| ) |
| { |
| if ( nRegLevel ) |
| { |
| Invalidate( rItem.Which() ); |
| } |
| else |
| { |
| // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind |
| if ( pImp->bMsgDirty ) |
| UpdateSlotServer_Impl(); |
| |
| // falls der Slot gebunden ist, updaten |
| DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ), |
| "cannot set items with which-id" ); |
| SfxStateCache* pCache = GetStateCache( rItem.Which() ); |
| if ( pCache ) |
| { |
| // Status updaten |
| if ( !pCache->IsControllerDirty() ) |
| pCache->Invalidate(sal_False); |
| pCache->SetState( SFX_ITEM_AVAILABLE, &rItem ); |
| |
| //! nicht implementiert: Updates von EnumSlots via MasterSlots |
| } |
| } |
| } |
| |
| |
| //-------------------------------------------------------------------- |
| |
| SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId ) |
| { |
| SfxStateCache* pCache = GetStateCache( nId ); |
| if ( !pCache && pImp->pSubBindings ) |
| return pImp->pSubBindings->GetAnyStateCache_Impl( nId ); |
| return pCache; |
| } |
| |
| SfxStateCache* SfxBindings::GetStateCache |
| ( |
| sal_uInt16 nId /* Slot-Id, deren SfxStatusCache gefunden |
| werden soll */, |
| sal_uInt16* pPos /* 0 bzw. Position, ab der die Bindings |
| bin"ar durchsucht werden sollen. Liefert |
| die Position zur"uck, an der nId gefunden |
| wurde, bzw. an der es einfef"ugt werden |
| w"urde. */ |
| ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| // is the specified function bound? |
| const sal_uInt16 nStart = ( pPos ? *pPos : 0 ); |
| const sal_uInt16 nPos = GetSlotPos( nId, nStart ); |
| |
| if ( nPos < pImp->pCaches->Count() && |
| (*pImp->pCaches)[nPos]->GetId() == nId ) |
| { |
| if ( pPos ) |
| *pPos = nPos; |
| return (*pImp->pCaches)[nPos]; |
| } |
| return 0; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::InvalidateAll |
| ( |
| sal_Bool bWithMsg /* sal_True |
| Slot-Server als ung"ultig markieren |
| |
| sal_False |
| Slot-Server bleiben g"ultig */ |
| ) |
| { |
| DBG_PROFSTART(SfxBindingsInvalidateAll); |
| DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" ); |
| |
| DBG_MEMTEST(); |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->InvalidateAll( bWithMsg ); |
| |
| // ist schon alles dirty gesetzt oder downing => nicht zu tun |
| if ( !pDispatcher || |
| ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) || |
| SFX_APP()->IsDowning() ) |
| { |
| DBG_PROFSTOP(SfxBindingsInvalidateAll); |
| return; |
| } |
| |
| pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg; |
| pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg; |
| pImp->bAllDirty = sal_True; |
| |
| for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n ) |
| pImp->pCaches->GetObject(n)->Invalidate(bWithMsg); |
| /* |
| ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame |
| ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY ); |
| |
| if ( bWithMsg && xFrame.is() ) |
| xFrame->contextChanged(); |
| */ |
| pImp->nMsgPos = 0; |
| if ( !nRegLevel ) |
| { |
| pImp->aTimer.Stop(); |
| pImp->aTimer.SetTimeout(TIMEOUT_FIRST); |
| pImp->aTimer.Start(); |
| // pImp->bFirstRound = sal_True; |
| // pImp->nFirstShell = 0; |
| } |
| |
| DBG_PROFSTOP(SfxBindingsInvalidateAll); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Invalidate |
| ( |
| const sal_uInt16* pIds /* numerisch sortiertes 0-terminiertes Array |
| von Slot-Ids (einzel, nicht als Paare!) */ |
| ) |
| { |
| DBG_PROFSTART(SfxBindingsInvalidateAll); |
| // DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" ); |
| |
| DBG_MEMTEST(); |
| |
| if ( pImp->bInUpdate ) |
| { |
| sal_Int32 i = 0; |
| while ( pIds[i] != 0 ) |
| AddSlotToInvalidateSlotsMap_Impl( pIds[i++] ); |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Invalidate( pIds ); |
| return; |
| } |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Invalidate( pIds ); |
| |
| // ist schon alles dirty gesetzt oder downing => nicht zu tun |
| if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() ) |
| return; |
| |
| // in immer kleiner werdenden Berichen bin"ar suchen |
| for ( sal_uInt16 n = GetSlotPos(*pIds); |
| *pIds && n < pImp->pCaches->Count(); |
| n = GetSlotPos(*pIds, n) ) |
| { |
| // falls SID "uberhaupt gebunden ist, den Cache invalidieren |
| SfxStateCache *pCache = pImp->pCaches->GetObject(n); |
| if ( pCache->GetId() == *pIds ) |
| pCache->Invalidate(sal_False); |
| |
| // n"achste SID |
| if ( !*++pIds ) |
| break; |
| DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" ); |
| } |
| |
| // falls nicht gelockt, Update-Timer starten |
| pImp->nMsgPos = 0; |
| if ( !nRegLevel ) |
| { |
| pImp->aTimer.Stop(); |
| pImp->aTimer.SetTimeout(TIMEOUT_FIRST); |
| pImp->aTimer.Start(); |
| // pImp->bFirstRound = sal_True; |
| // pImp->nFirstShell = 0; |
| } |
| |
| DBG_PROFSTOP(SfxBindingsInvalidateAll); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::InvalidateShell |
| ( |
| const SfxShell& rSh /* Die <SfxShell>, deren Slot-Ids |
| invalidiert werden sollen. */, |
| |
| sal_Bool bDeep /* sal_True |
| auch die, von der SfxShell |
| ererbten Slot-Ids werden invalidert |
| |
| sal_False |
| die ererbten und nicht "uberladenen |
| Slot-Ids werden invalidiert */ |
| //! MI: z. Zt. immer bDeep |
| ) |
| { |
| DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" ); |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->InvalidateShell( rSh, bDeep ); |
| |
| if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() ) |
| return; |
| |
| DBG_PROFSTART(SfxBindingsInvalidateAll); |
| DBG_MEMTEST(); |
| |
| // Jetzt schon flushen, wird in GetShellLevel(rSh) sowieso gemacht; wichtig, |
| // damit pImp->bAll(Msg)Dirty korrekt gesetzt ist |
| pDispatcher->Flush(); |
| |
| if ( !pDispatcher || |
| ( pImp->bAllDirty && pImp->bAllMsgDirty ) || |
| SFX_APP()->IsDowning() ) |
| { |
| // Wenn sowieso demn"achst alle Server geholt werden |
| return; |
| } |
| |
| // Level finden |
| sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh); |
| if ( nLevel != USHRT_MAX ) |
| { |
| for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n ) |
| { |
| SfxStateCache *pCache = pImp->pCaches->GetObject(n); |
| const SfxSlotServer *pMsgServer = |
| pCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel ) |
| pCache->Invalidate(sal_False); |
| } |
| pImp->nMsgPos = 0; |
| if ( !nRegLevel ) |
| { |
| pImp->aTimer.Stop(); |
| pImp->aTimer.SetTimeout(TIMEOUT_FIRST); |
| pImp->aTimer.Start(); |
| pImp->bFirstRound = sal_True; |
| pImp->nFirstShell = nLevel; |
| } |
| } |
| |
| DBG_PROFSTOP(SfxBindingsInvalidateAll); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Invalidate |
| ( |
| sal_uInt16 nId // zu invalidierende Slot-Id |
| ) |
| { |
| DBG_MEMTEST(); |
| // DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" ); |
| |
| if ( pImp->bInUpdate ) |
| { |
| AddSlotToInvalidateSlotsMap_Impl( nId ); |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Invalidate( nId ); |
| return; |
| } |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Invalidate( nId ); |
| |
| if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() ) |
| return; |
| |
| SfxStateCache* pCache = GetStateCache(nId); |
| if ( pCache ) |
| { |
| pCache->Invalidate(sal_False); |
| pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos); |
| if ( !nRegLevel ) |
| { |
| pImp->aTimer.Stop(); |
| pImp->aTimer.SetTimeout(TIMEOUT_FIRST); |
| pImp->aTimer.Start(); |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Invalidate |
| ( |
| sal_uInt16 nId, // zu invalidierende Slot-Id |
| sal_Bool bWithItem, // StateCache clearen ? |
| sal_Bool bWithMsg // SlotServer neu holen ? |
| ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" ); |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg ); |
| |
| if ( SFX_APP()->IsDowning() ) |
| return; |
| |
| SfxStateCache* pCache = GetStateCache(nId); |
| if ( pCache ) |
| { |
| if ( bWithItem ) |
| pCache->ClearCache(); |
| pCache->Invalidate(bWithMsg); |
| |
| if ( !pDispatcher || pImp->bAllDirty ) |
| return; |
| |
| pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos); |
| if ( !nRegLevel ) |
| { |
| pImp->aTimer.Stop(); |
| pImp->aTimer.SetTimeout(TIMEOUT_FIRST); |
| pImp->aTimer.Start(); |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| sal_Bool SfxBindings::IsBound( sal_uInt16 nSlotId, sal_uInt16 nStartSearchAt ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| return GetStateCache(nSlotId, &nStartSearchAt ) != 0; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| sal_uInt16 SfxBindings::GetSlotPos( sal_uInt16 nId, sal_uInt16 nStartSearchAt ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| DBG_PROFSTART(SfxBindingsMsgPos); |
| |
| // answer immediately if a function-seek comes repeated |
| if ( pImp->nCachedFunc1 < pImp->pCaches->Count() && |
| (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId ) |
| { |
| ++nCache1; |
| DBG_PROFSTOP(SfxBindingsMsgPos); |
| return pImp->nCachedFunc1; |
| } |
| if ( pImp->nCachedFunc2 < pImp->pCaches->Count() && |
| (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId ) |
| { |
| ++nCache2; |
| |
| // swap the caches |
| sal_uInt16 nTemp = pImp->nCachedFunc1; |
| pImp->nCachedFunc1 = pImp->nCachedFunc2; |
| pImp->nCachedFunc2 = nTemp; |
| DBG_PROFSTOP(SfxBindingsMsgPos); |
| return pImp->nCachedFunc1; |
| } |
| |
| // binary search, if not found, seek to target-position |
| if ( pImp->pCaches->Count() <= nStartSearchAt ) |
| { |
| DBG_PROFSTOP(SfxBindingsMsgPos); |
| return 0; |
| } |
| if ( pImp->pCaches->Count() == (nStartSearchAt+1) ) |
| { |
| DBG_PROFSTOP(SfxBindingsMsgPos); |
| return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1; |
| } |
| sal_uInt16 nLow = nStartSearchAt; |
| sal_uInt16 nMid = 0; |
| sal_uInt16 nHigh = 0; |
| sal_Bool bFound = sal_False; |
| nHigh = pImp->pCaches->Count() - 1; |
| while ( !bFound && nLow <= nHigh ) |
| { |
| nMid = (nLow + nHigh) >> 1; |
| DBG_ASSERT( nMid < pImp->pCaches->Count(), "bsearch ist buggy" ); |
| int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() ); |
| if ( nDiff < 0) |
| { if ( nMid == 0 ) |
| break; |
| nHigh = nMid - 1; |
| } |
| else if ( nDiff > 0 ) |
| { nLow = nMid + 1; |
| if ( nLow == 0 ) |
| break; |
| } |
| else |
| bFound = sal_True; |
| } |
| sal_uInt16 nPos = bFound ? nMid : nLow; |
| DBG_ASSERT( nPos <= pImp->pCaches->Count(), "" ); |
| DBG_ASSERT( nPos == pImp->pCaches->Count() || |
| nId <= (*pImp->pCaches)[nPos]->GetId(), "" ); |
| DBG_ASSERT( nPos == nStartSearchAt || |
| nId > (*pImp->pCaches)[nPos-1]->GetId(), "" ); |
| DBG_ASSERT( ( (nPos+1) >= pImp->pCaches->Count() ) || |
| nId < (*pImp->pCaches)[nPos+1]->GetId(), "" ); |
| pImp->nCachedFunc2 = pImp->nCachedFunc1; |
| pImp->nCachedFunc1 = nPos; |
| DBG_PROFSTOP(SfxBindingsMsgPos); |
| return nPos; |
| } |
| //-------------------------------------------------------------------- |
| void SfxBindings::RegisterInternal_Impl( SfxControllerItem& rItem ) |
| { |
| Register_Impl( rItem, sal_True ); |
| |
| } |
| |
| void SfxBindings::Register( SfxControllerItem& rItem ) |
| { |
| Register_Impl( rItem, sal_False ); |
| } |
| |
| void SfxBindings::Register_Impl( SfxControllerItem& rItem, sal_Bool bInternal ) |
| { |
| DBG_MEMTEST(); |
| // DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" ); |
| DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" ); |
| |
| // insert new cache if it does not already exist |
| sal_uInt16 nId = rItem.GetId(); |
| sal_uInt16 nPos = GetSlotPos(nId); |
| if ( nPos >= pImp->pCaches->Count() || |
| (*pImp->pCaches)[nPos]->GetId() != nId ) |
| { |
| SfxStateCache* pCache = new SfxStateCache(nId); |
| pImp->pCaches->Insert( nPos, pCache ); |
| DBG_ASSERT( nPos == 0 || |
| (*pImp->pCaches)[nPos]->GetId() > |
| (*pImp->pCaches)[nPos-1]->GetId(), "" ); |
| DBG_ASSERT( (nPos == pImp->pCaches->Count()-1) || |
| (*pImp->pCaches)[nPos]->GetId() < |
| (*pImp->pCaches)[nPos+1]->GetId(), "" ); |
| pImp->bMsgDirty = sal_True; |
| } |
| |
| // enqueue the new binding |
| if ( bInternal ) |
| { |
| (*pImp->pCaches)[nPos]->SetInternalController( &rItem ); |
| } |
| else |
| { |
| SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem); |
| rItem.ChangeItemLink(pOldItem); |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::Release( SfxControllerItem& rItem ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| //! DBG_ASSERT( nRegLevel > 0, "release without EnterRegistrations" ); |
| DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" ); |
| ENTERREGISTRATIONS(); |
| |
| // find the bound function |
| sal_uInt16 nId = rItem.GetId(); |
| sal_uInt16 nPos = GetSlotPos(nId); |
| SfxStateCache* pCache = (*pImp->pCaches)[nPos]; |
| if ( pCache->GetId() == nId ) |
| { |
| if ( pCache->GetInternalController() == &rItem ) |
| { |
| pCache->ReleaseInternalController(); |
| } |
| else |
| { |
| // is this the first binding in the list? |
| SfxControllerItem* pItem = pCache->GetItemLink(); |
| if ( pItem == &rItem ) |
| pCache->ChangeItemLink( rItem.GetItemLink() ); |
| else |
| { |
| // search the binding in the list |
| while ( pItem && pItem->GetItemLink() != &rItem ) |
| pItem = pItem->GetItemLink(); |
| |
| // unlink it if it was found |
| if ( pItem ) |
| pItem->ChangeItemLink( rItem.GetItemLink() ); |
| } |
| } |
| |
| // was this the last controller? |
| if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() ) |
| { |
| #ifdef slow |
| // remove the BoundFunc |
| delete (*pImp->pCaches)[nPos]; |
| pImp->pCaches->Remove(nPos, 1); |
| #endif |
| pImp->bCtrlReleased = sal_True; |
| } |
| } |
| |
| LEAVEREGISTRATIONS(); |
| } |
| |
| //-------------------------------------------------------------------- |
| const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, |
| const SfxPoolItem **ppInternalArgs ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| if( !nId || !pDispatcher ) |
| return NULL; |
| |
| return Execute_Impl( nId, ppItems, nModi, SFX_CALLMODE_SYNCHRON, ppInternalArgs ); |
| } |
| |
| sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode, |
| const SfxPoolItem **ppInternalArgs ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| if( !nId || !pDispatcher ) |
| return sal_False; |
| |
| const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs ); |
| return ( pRet != 0 ); |
| } |
| |
| void SfxBindings::ExecuteGlobal_Impl( sal_uInt16 nId ) |
| { |
| if( nId && pDispatcher ) |
| Execute_Impl( nId, NULL, 0, SFX_CALLMODE_ASYNCHRON, NULL, sal_True ); |
| } |
| |
| const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode, |
| const SfxPoolItem **ppInternalArgs, sal_Bool bGlobalOnly ) |
| { |
| SfxStateCache *pCache = GetStateCache( nId ); |
| if ( !pCache ) |
| { |
| SfxBindings *pBind = pImp->pSubBindings; |
| while ( pBind ) |
| { |
| if ( pBind->GetStateCache( nId ) ) |
| return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly ); |
| pBind = pBind->pImp->pSubBindings; |
| }; |
| } |
| |
| SfxDispatcher &rDispatcher = *pDispatcher; |
| rDispatcher.Flush(); |
| rDispatcher.GetFrame(); // -Wall is this required??? |
| |
| // get SlotServer (Slot+ShellLevel) and Shell from cache |
| sal_Bool bDeleteCache = sal_False; |
| if ( !pCache ) |
| { |
| // Execution of non cached slots (Accelerators don't use Controllers) |
| // slot is uncached, use SlotCache to handle external dispatch providers |
| pCache = new SfxStateCache( nId ); |
| pCache->GetSlotServer( rDispatcher, pImp->xProv ); |
| bDeleteCache = sal_True; |
| } |
| |
| if ( pCache && pCache->GetDispatch().is() ) |
| { |
| DBG_ASSERT( !ppInternalArgs, "Internal args get lost when dispatched!" ); |
| |
| SfxItemPool &rPool = GetDispatcher()->GetFrame()->GetObjectShell()->GetPool(); |
| SfxRequest aReq( nId, nCallMode, rPool ); |
| aReq.SetModifier( nModi ); |
| if( ppItems ) |
| while( *ppItems ) |
| aReq.AppendItem( **ppItems++ ); |
| |
| // cache binds to an external dispatch provider |
| pCache->Dispatch( aReq.GetArgs(), nCallMode == SFX_CALLMODE_SYNCHRON ); |
| if ( bDeleteCache ) |
| DELETEZ( pCache ); |
| SfxPoolItem *pVoid = new SfxVoidItem( nId ); |
| DeleteItemOnIdle( pVoid ); |
| return pVoid; |
| } |
| |
| // slot is handled internally by SfxDispatcher |
| if ( pImp->bMsgDirty ) |
| UpdateSlotServer_Impl(); |
| |
| SfxShell *pShell=0; |
| const SfxSlot *pSlot=0; |
| |
| // if slot was uncached, we should have created a cache in this method! |
| DBG_ASSERT( pCache, "This code needs a cache!"); |
| const SfxSlotServer* pServer = pCache ? pCache->GetSlotServer( rDispatcher, pImp->xProv ) : 0; |
| if ( !pServer ) |
| { |
| return NULL; |
| } |
| else |
| { |
| pShell = rDispatcher.GetShell( pServer->GetShellLevel() ); |
| pSlot = pServer->GetSlot(); |
| } |
| |
| if ( bGlobalOnly ) |
| if ( !pShell->ISA(SfxModule) && !pShell->ISA(SfxApplication) && !pShell->ISA(SfxViewFrame) ) |
| return NULL; |
| |
| SfxItemPool &rPool = pShell->GetPool(); |
| SfxRequest aReq( nId, nCallMode, rPool ); |
| aReq.SetModifier( nModi ); |
| if( ppItems ) |
| while( *ppItems ) |
| aReq.AppendItem( **ppItems++ ); |
| if ( ppInternalArgs ) |
| { |
| SfxAllItemSet aSet( rPool ); |
| for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg ) |
| aSet.Put( **pArg ); |
| aReq.SetInternalArgs_Impl( aSet ); |
| } |
| |
| Execute_Impl( aReq, pSlot, pShell ); |
| |
| const SfxPoolItem* pRet = aReq.GetReturnValue(); |
| if ( !pRet ) |
| { |
| SfxPoolItem *pVoid = new SfxVoidItem( nId ); |
| DeleteItemOnIdle( pVoid ); |
| pRet = pVoid; |
| } |
| |
| if ( bDeleteCache ) |
| delete pCache; |
| |
| return pRet; |
| } |
| |
| void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell ) |
| { |
| SfxItemPool &rPool = pShell->GetPool(); |
| |
| if ( SFX_KIND_ENUM == pSlot->GetKind() ) |
| { |
| // bei Enum-Slots muss der Master mit dem Wert des Enums executet werden |
| const SfxSlot *pRealSlot = pShell->GetInterface()->GetRealSlot(pSlot); |
| const sal_uInt16 nSlotId = pRealSlot->GetSlotId(); |
| aReq.SetSlot( nSlotId ); |
| aReq.AppendItem( SfxAllEnumItem( rPool.GetWhich(nSlotId), pSlot->GetValue() ) ); |
| pDispatcher->_Execute( *pShell, *pRealSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD ); |
| } |
| else if ( SFX_KIND_ATTR == pSlot->GetKind() ) |
| { |
| // bei Attr-Slots muss der Which-Wert gemapped werden |
| const sal_uInt16 nSlotId = pSlot->GetSlotId(); |
| aReq.SetSlot( nSlotId ); |
| if ( pSlot->IsMode(SFX_SLOT_TOGGLE) ) |
| { |
| // an togglebare-Attribs (Bools) wird der Wert angeheangt |
| sal_uInt16 nWhich = pSlot->GetWhich(rPool); |
| SfxItemSet aSet(rPool, nWhich, nWhich, 0); |
| SfxStateFunc aFunc = pSlot->GetStateFnc(); |
| pShell->CallState( aFunc, aSet ); |
| const SfxPoolItem *pOldItem; |
| SfxItemState eState = aSet.GetItemState(nWhich, sal_True, &pOldItem); |
| if ( eState == SFX_ITEM_DISABLED ) |
| return; |
| |
| if ( SFX_ITEM_AVAILABLE == eState && SfxItemPool::IsWhich(nWhich) ) |
| pOldItem = &aSet.Get(nWhich); |
| |
| if ( SFX_ITEM_SET == eState || |
| ( SFX_ITEM_AVAILABLE == eState && |
| SfxItemPool::IsWhich(nWhich) && |
| pOldItem ) ) |
| { |
| if ( pOldItem->ISA(SfxBoolItem) ) |
| { |
| // wir koennen Bools toggeln |
| sal_Bool bOldValue = ((const SfxBoolItem *)pOldItem)->GetValue(); |
| SfxBoolItem *pNewItem = (SfxBoolItem*) (pOldItem->Clone()); |
| pNewItem->SetValue( !bOldValue ); |
| aReq.AppendItem( *pNewItem ); |
| delete pNewItem; |
| } |
| else if ( pOldItem->ISA(SfxEnumItemInterface) && |
| ((SfxEnumItemInterface *)pOldItem)->HasBoolValue()) |
| { |
| // und Enums mit Bool-Interface |
| SfxEnumItemInterface *pNewItem = |
| (SfxEnumItemInterface*) (pOldItem->Clone()); |
| pNewItem->SetBoolValue(!((SfxEnumItemInterface *)pOldItem)->GetBoolValue()); |
| aReq.AppendItem( *pNewItem ); |
| delete pNewItem; |
| } |
| else { |
| DBG_ERROR( "Toggle only for Enums and Bools allowed" ); |
| } |
| } |
| else if ( SFX_ITEM_DONTCARE == eState ) |
| { |
| // ein Status-Item per Factory erzeugen |
| SfxPoolItem *pNewItem = pSlot->GetType()->CreateItem(); |
| DBG_ASSERT( pNewItem, "Toggle an Slot ohne ItemFactory" ); |
| pNewItem->SetWhich( nWhich ); |
| |
| if ( pNewItem->ISA(SfxBoolItem) ) |
| { |
| // wir koennen Bools toggeln |
| ((SfxBoolItem*)pNewItem)->SetValue( sal_True ); |
| aReq.AppendItem( *pNewItem ); |
| } |
| else if ( pNewItem->ISA(SfxEnumItemInterface) && |
| ((SfxEnumItemInterface *)pNewItem)->HasBoolValue()) |
| { |
| // und Enums mit Bool-Interface |
| ((SfxEnumItemInterface*)pNewItem)->SetBoolValue(sal_True); |
| aReq.AppendItem( *pNewItem ); |
| } |
| else { |
| DBG_ERROR( "Toggle only for Enums and Bools allowed" ); |
| } |
| delete pNewItem; |
| } |
| else { |
| DBG_ERROR( "suspicious Toggle-Slot" ); |
| } |
| } |
| |
| pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD ); |
| } |
| else |
| pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD ); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::UpdateSlotServer_Impl() |
| { |
| DBG_PROFSTART(SfxBindingsUpdateServers); |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| // synchronisieren |
| pDispatcher->Flush(); |
| // pDispatcher->Update_Impl(); |
| |
| if ( pImp->bAllMsgDirty ) |
| { |
| if ( !nRegLevel ) |
| { |
| ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame |
| ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY ); |
| //if ( xFrame.is() ) |
| // xFrame->contextChanged(); |
| pImp->bContextChanged = sal_False; |
| } |
| else |
| pImp->bContextChanged = sal_True; |
| } |
| |
| const sal_uInt16 nCount = pImp->pCaches->Count(); |
| for(sal_uInt16 i = 0; i < nCount; ++i) |
| { |
| SfxStateCache *pCache = pImp->pCaches->GetObject(i); |
| pCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| } |
| pImp->bMsgDirty = pImp->bAllMsgDirty = sal_False; |
| |
| Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) ); |
| |
| DBG_PROFSTOP(SfxBindingsUpdateServers); |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| #ifdef WNT |
| int __cdecl CmpUS_Impl(const void *p1, const void *p2) |
| #else |
| int CmpUS_Impl(const void *p1, const void *p2) |
| #endif |
| |
| /* [Beschreibung] |
| |
| Interne Vergleichsfunktion fuer qsort. |
| */ |
| |
| { |
| return *(sal_uInt16 *)p1 - *(sal_uInt16 *)p2; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| SfxItemSet* SfxBindings::CreateSet_Impl |
| ( |
| SfxStateCache*& pCache, // in: Status-Cache von nId |
| const SfxSlot*& pRealSlot, // out: RealSlot zu nId |
| const SfxSlotServer** pMsgServer, // out: Slot-Server zu nId |
| SfxFoundCacheArr_Impl& rFound // out: Liste der Caches der Siblings |
| ) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl mit dirty MessageServer" ); |
| |
| const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| if(!pMsgSvr || !pDispatcher) |
| return 0; |
| |
| DBG_PROFSTART(SfxBindingsCreateSet); |
| pRealSlot = 0; |
| *pMsgServer = pMsgSvr; |
| |
| sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel(); |
| SfxShell *pShell = pDispatcher->GetShell( nShellLevel ); |
| if ( !pShell ) // seltener GPF beim Browsen durch Update aus Inet-Notify |
| return 0; |
| |
| SfxItemPool &rPool = pShell->GetPool(); |
| |
| // hole die Status-Methode, von der pCache bedient wird |
| SfxStateFunc pFnc = 0; |
| const SfxInterface *pInterface = pShell->GetInterface(); |
| if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() ) |
| { |
| pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot()); |
| pCache = GetStateCache( pRealSlot->GetSlotId() ); |
| // DBG_ASSERT( pCache, "Kein Slotcache fuer den Masterslot gefunden!" ); |
| } |
| else |
| pRealSlot = pMsgSvr->GetSlot(); |
| |
| // |
| // Achtung: pCache darf auch NULL sein !!! |
| // |
| |
| pFnc = pRealSlot->GetStateFnc(); |
| |
| // der RealSlot ist immer drin |
| const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl( |
| pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache ); |
| rFound.Insert( pFound ); |
| |
| sal_uInt16 nSlot = pRealSlot->GetSlotId(); |
| if ( !(nSlot >= SID_VERB_START && nSlot <= SID_VERB_END) ) |
| { |
| pInterface = pInterface->GetRealInterfaceForSlot( pRealSlot ); |
| DBG_ASSERT (pInterface,"Slot in angegebener Shell nicht gefunden!"); |
| } |
| |
| // Durchsuche die Bindings nach den von derselben Funktion bedienten Slots. |
| // Daf"ur kommen nur Slots in Frage, die es im gefundenen Interface gibt. |
| |
| // Die Position des Statecaches im StateCache-Array |
| sal_uInt16 nCachePos = pImp->nMsgPos; |
| const SfxSlot *pSibling = pRealSlot->GetNextSlot(); |
| |
| // Die Slots eines Interfaces sind im Kreis verkettet |
| while ( pSibling > pRealSlot ) |
| { |
| SfxStateFunc pSiblingFnc=0; |
| SfxStateCache *pSiblingCache = |
| GetStateCache( pSibling->GetSlotId(), &nCachePos ); |
| |
| // Ist der Slot "uberhaupt gecached ? |
| if ( pSiblingCache ) |
| { |
| const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| if ( pServ && pServ->GetShellLevel() == nShellLevel ) |
| pSiblingFnc = pServ->GetSlot()->GetStateFnc(); |
| } |
| |
| // Mu\s der Slot "uberhaupt upgedatet werden ? |
| bool bInsert = pSiblingCache && pSiblingCache->IsControllerDirty(); |
| |
| // Bugfix #26161#: Es reicht nicht, nach der selben Shell zu fragen !! |
| bool bSameMethod = pSiblingCache && pFnc == pSiblingFnc; |
| |
| // Wenn der Slot ein nicht-dirty MasterSlot ist, dann ist vielleicht |
| // einer seiner Slaves dirty ? Dann wird der Masterslot doch eingef"ugt. |
| if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() ) |
| { |
| // auch Slave-Slots auf Binding pru"fen |
| const SfxSlot* pFirstSlave = pSibling->GetLinkedSlot(); |
| for ( const SfxSlot *pSlaveSlot = pFirstSlave; |
| !bInsert; |
| pSlaveSlot = pSlaveSlot->GetNextSlot()) |
| { |
| // Die Slaves zeigen auf ihren Master |
| DBG_ASSERT(pSlaveSlot->GetLinkedSlot() == pSibling, |
| "Falsche Master/Slave-Beziehung!"); |
| |
| sal_uInt16 nCurMsgPos = pImp->nMsgPos; |
| const SfxStateCache *pSlaveCache = |
| GetStateCache( pSlaveSlot->GetSlotId(), &nCurMsgPos ); |
| |
| // Ist der Slave-Slot gecached und dirty ? |
| bInsert = pSlaveCache && pSlaveCache->IsControllerDirty(); |
| |
| // Slaves sind untereinander im Kreis verkettet |
| if (pSlaveSlot->GetNextSlot() == pFirstSlave) |
| break; |
| } |
| } |
| |
| if ( bInsert && bSameMethod ) |
| { |
| const SfxFoundCache_Impl *pFoundCache = new SfxFoundCache_Impl( |
| pSibling->GetSlotId(), pSibling->GetWhich(rPool), |
| pSibling, pSiblingCache ); |
| |
| rFound.Insert( pFoundCache ); |
| } |
| |
| pSibling = pSibling->GetNextSlot(); |
| } |
| |
| // aus den Ranges ein Set erzeugen |
| sal_uInt16 *pRanges = new sal_uInt16[rFound.Count() * 2 + 1]; |
| int j = 0; |
| sal_uInt16 i = 0; |
| while ( i < rFound.Count() ) |
| { |
| pRanges[j++] = rFound[i]->nWhichId; |
| // aufeinanderfolgende Zahlen |
| for ( ; i < rFound.Count()-1; ++i ) |
| if ( rFound[i]->nWhichId+1 != rFound[i+1]->nWhichId ) |
| break; |
| pRanges[j++] = rFound[i++]->nWhichId; |
| } |
| pRanges[j] = 0; // terminierende NULL |
| SfxItemSet *pSet = new SfxItemSet(rPool, pRanges); |
| delete [] pRanges; |
| DBG_PROFSTOP(SfxBindingsCreateSet); |
| return pSet; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::UpdateControllers_Impl |
| ( |
| const SfxInterface* pIF, // das diese Id momentan bedienende Interface |
| const SfxFoundCache_Impl* pFound, // Cache, Slot, Which etc. |
| const SfxPoolItem* pItem, // item to send to controller |
| SfxItemState eState // state of item |
| ) |
| { |
| DBG_ASSERT( !pFound->pSlot || SFX_KIND_ENUM != pFound->pSlot->GetKind(), |
| "direct update of enum slot isn't allowed" ); |
| DBG_PROFSTART(SfxBindingsUpdateCtrl1); |
| |
| SfxStateCache* pCache = pFound->pCache; |
| const SfxSlot* pSlot = pFound->pSlot; |
| DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" ); |
| |
| // insofern gebunden, die Controller f"uer den Slot selbst updaten |
| if ( pCache && pCache->IsControllerDirty() ) |
| { |
| if ( SFX_ITEM_DONTCARE == eState ) |
| { |
| // uneindeuting |
| pCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 ); |
| } |
| else if ( SFX_ITEM_DEFAULT == eState && |
| pFound->nWhichId > SFX_WHICH_MAX ) |
| { |
| // kein Status oder Default aber ohne Pool |
| SfxVoidItem aVoid(0); |
| pCache->SetState( SFX_ITEM_UNKNOWN, &aVoid ); |
| } |
| else if ( SFX_ITEM_DISABLED == eState ) |
| pCache->SetState(SFX_ITEM_DISABLED, 0); |
| else |
| pCache->SetState(SFX_ITEM_AVAILABLE, pItem); |
| } |
| |
| DBG_PROFSTOP(SfxBindingsUpdateCtrl1); |
| |
| // insofern vorhanden und gebunden, die Controller f"uer Slave-Slots |
| // (Enum-Werte) des Slots updaten |
| DBG_PROFSTART(SfxBindingsUpdateCtrl2); |
| DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem || |
| pItem->ISA(SfxEnumItemInterface), |
| "master slot with non-enum-type found" ); |
| const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0; |
| if ( pIF && pFirstSlave) |
| { |
| // Items auf EnumItem casten |
| const SfxEnumItemInterface *pEnumItem = |
| PTR_CAST(SfxEnumItemInterface,pItem); |
| if ( eState == SFX_ITEM_AVAILABLE && !pEnumItem ) |
| eState = SFX_ITEM_DONTCARE; |
| else |
| eState = SfxControllerItem::GetItemState( pEnumItem ); |
| |
| // "uber alle Slaves-Slots iterieren |
| for ( const SfxSlot *pSlave = pFirstSlave; pSlave; pSlave = pSlave->GetNextSlot() ) |
| { |
| DBG_ASSERT(pSlave, "Falsche SlaveSlot-Verkettung!"); |
| DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed"); |
| DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"falscher MasterSlot!"); |
| |
| // ist die Funktion gebunden? |
| SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() ); |
| if ( pEnumCache ) |
| { |
| pEnumCache->Invalidate(sal_False); |
| |
| HACK(CONTROL/SELECT Kram) |
| if ( eState == SFX_ITEM_DONTCARE && pFound->nWhichId == 10144 ) |
| { |
| SfxVoidItem aVoid(0); |
| pEnumCache->SetState( SFX_ITEM_UNKNOWN, &aVoid ); |
| |
| if (pSlave->GetNextSlot() == pFirstSlave) |
| break; |
| |
| continue; |
| } |
| |
| if ( SFX_ITEM_DISABLED == eState || !pEnumItem->IsEnabled( pSlave->GetSlotId()) ) |
| { |
| // disabled |
| pEnumCache->SetState(SFX_ITEM_DISABLED, 0); |
| } |
| else if ( SFX_ITEM_AVAILABLE == eState ) |
| { |
| // enum-Wert ermitteln |
| sal_uInt16 nValue = pEnumItem->GetEnumValue(); |
| SfxBoolItem aBool( pFound->nWhichId, pSlave->GetValue() == nValue ); |
| pEnumCache->SetState(SFX_ITEM_AVAILABLE, &aBool); |
| } |
| else |
| { |
| // uneindeuting |
| pEnumCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 ); |
| } |
| } |
| |
| if (pSlave->GetNextSlot() == pFirstSlave) |
| break; |
| } |
| } |
| |
| DBG_PROFSTOP(SfxBindingsUpdateCtrl2); |
| } |
| |
| |
| //-------------------------------------------------------------------- |
| |
| IMPL_LINK( SfxBindings, NextJob_Impl, Timer *, pTimer ) |
| { |
| #ifdef DBG_UTIL |
| // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT or another MS library |
| // try to get them here |
| try |
| { |
| #endif |
| const unsigned MAX_INPUT_DELAY = 200; |
| |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| DBG_PROFSTART(SfxBindingsNextJob_Impl0); |
| |
| if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY && pTimer ) |
| { |
| pImp->aTimer.SetTimeout(TIMEOUT_UPDATING); |
| return sal_True; |
| } |
| |
| SfxApplication *pSfxApp = SFX_APP(); |
| |
| if( pDispatcher ) |
| pDispatcher->Update_Impl(); |
| |
| // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do |
| SfxViewFrame* pFrame = pDispatcher->GetFrame(); |
| //<!--Modified by PengYunQuan for Validity Cell Range Picker |
| //if ( (pFrame && pFrame->GetObjectShell()->IsInModalMode()) || pSfxApp->IsDowning() || !pImp->pCaches->Count() ) |
| if ( (pFrame && !pFrame->GetObjectShell()->AcceptStateUpdate()) || pSfxApp->IsDowning() || !pImp->pCaches->Count() ) |
| //-->Modified by PengYunQuan for Validity Cell Range Picker |
| { |
| DBG_PROFSTOP(SfxBindingsNextJob_Impl0); |
| return sal_True; |
| } |
| if ( !pDispatcher || !pDispatcher->IsFlushed() ) |
| { |
| DBG_PROFSTOP(SfxBindingsNextJob_Impl0); |
| return sal_True; |
| } |
| |
| // gfs. alle Server aktualisieren / geschieht in eigener Zeitscheibe |
| if ( pImp->bMsgDirty ) |
| { |
| UpdateSlotServer_Impl(); |
| DBG_PROFSTOP(SfxBindingsNextJob_Impl0); |
| return sal_False; |
| } |
| |
| DBG_PROFSTOP(SfxBindingsNextJob_Impl0); |
| DBG_PROFSTART(SfxBindingsNextJob_Impl); |
| pImp->bAllDirty = sal_False; |
| pImp->aTimer.SetTimeout(TIMEOUT_UPDATING); |
| |
| // at least 10 loops and further if more jobs are available but no input |
| bool bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule; |
| sal_uInt16 nLoops = 10; |
| pImp->bInNextJob = sal_True; |
| const sal_uInt16 nCount = pImp->pCaches->Count(); |
| while ( pImp->nMsgPos < nCount ) |
| { |
| // iterate through the bound functions |
| sal_Bool bJobDone = sal_False; |
| while ( !bJobDone ) |
| { |
| SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos]; |
| DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" ); |
| sal_Bool bWasDirty = pCache->IsControllerDirty(); |
| if ( bWasDirty ) |
| { |
| /* |
| sal_Bool bSkip = sal_False; |
| if ( pImp->bFirstRound ) |
| { |
| // Falls beim Update eine Shell vorgezogen werden soll, |
| // kommt in einer ersten Update-Runde nur diese dran |
| const SfxSlotServer *pMsgServer = |
| pCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| if ( pMsgServer && |
| pMsgServer->GetShellLevel() != pImp->nFirstShell ) |
| bSkip = sal_True; |
| } |
| |
| if ( !bSkip ) |
| { |
| */ |
| Update_Impl( pCache ); |
| DBG_ASSERT( nCount == pImp->pCaches->Count(), |
| "Reschedule in StateChanged => buff" ); |
| // } |
| } |
| |
| // skip to next function binding |
| ++pImp->nMsgPos; |
| |
| // keep job if it is not completed, but any input is available |
| bJobDone = pImp->nMsgPos >= nCount; |
| if ( bJobDone && pImp->bFirstRound ) |
| { |
| // Update der bevorzugten Shell ist gelaufen, nun d"urfen |
| // auch die anderen |
| bJobDone = sal_False; |
| pImp->bFirstRound = sal_False; |
| pImp->nMsgPos = 0; |
| } |
| |
| if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) ) |
| { |
| DBG_PROFSTOP(SfxBindingsNextJob_Impl); |
| pImp->bInNextJob = sal_False; |
| return sal_False; |
| } |
| } |
| } |
| |
| pImp->nMsgPos = 0; |
| |
| // check for volatile slots |
| bool bVolatileSlotsPresent = false; |
| for ( sal_uInt16 n = 0; n < nCount; ++n ) |
| { |
| SfxStateCache* pCache = (*pImp->pCaches)[n]; |
| const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv); |
| if ( pSlotServer && pSlotServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) |
| { |
| pCache->Invalidate(sal_False); |
| bVolatileSlotsPresent = true; |
| } |
| } |
| |
| if (bVolatileSlotsPresent) |
| pImp->aTimer.SetTimeout(TIMEOUT_IDLE); |
| else |
| pImp->aTimer.Stop(); |
| |
| // Update-Runde ist beendet |
| pImp->bInNextJob = sal_False; |
| Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE)); |
| DBG_PROFSTOP(SfxBindingsNextJob_Impl); |
| return sal_True; |
| #ifdef DBG_UTIL |
| } |
| catch (...) |
| { |
| DBG_ERROR("C++ exception caught!"); |
| pImp->bInNextJob = sal_False; |
| } |
| |
| return sal_False; |
| #endif |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| sal_uInt16 SfxBindings::EnterRegistrations(const char *pFile, int nLine) |
| { |
| (void)pFile; |
| (void)nLine; |
| DBG_MEMTEST(); |
| #ifdef DBG_UTIL |
| ByteString aMsg; |
| aMsg.Fill( Min(nRegLevel, sal_uInt16(8) ) ); |
| aMsg += "this = "; |
| aMsg += ByteString::CreateFromInt32((long)this); |
| aMsg += " Level = "; |
| aMsg += ByteString::CreateFromInt32(nRegLevel); |
| aMsg += " SfxBindings::EnterRegistrations "; |
| if(pFile) { |
| aMsg += "File: "; |
| aMsg += pFile; |
| aMsg += " Line: "; |
| aMsg += ByteString::CreateFromInt32(nLine); |
| } |
| // FILE* pLog = fopen( "c:\\bindings.log", "a+w" ); |
| // fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog ); |
| // fclose( pLog ); |
| DbgTrace( aMsg.GetBuffer() ); |
| #endif |
| |
| // Wenn Bindings gelockt werden, auch SubBindings locken |
| if ( pImp->pSubBindings ) |
| { |
| pImp->pSubBindings->ENTERREGISTRATIONS(); |
| |
| // Dieses EnterRegistrations ist f"ur die SubBindings kein "echtes" |
| pImp->pSubBindings->pImp->nOwnRegLevel--; |
| |
| // Bindings synchronisieren |
| pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel + 1; |
| } |
| |
| pImp->nOwnRegLevel++; |
| |
| // check if this is the outer most level |
| if ( ++nRegLevel == 1 ) |
| { |
| // stop background-processing |
| pImp->aTimer.Stop(); |
| |
| // flush the cache |
| pImp->nCachedFunc1 = 0; |
| pImp->nCachedFunc2 = 0; |
| |
| // merken, ob ganze Caches verschwunden sind |
| pImp->bCtrlReleased = sal_False; |
| } |
| |
| return nRegLevel; |
| } |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel, const char *pFile, int nLine ) |
| { |
| (void)nLevel; // unused variable |
| (void)pFile; |
| (void)nLine; |
| DBG_MEMTEST(); |
| DBG_ASSERT( nRegLevel, "Leave without Enter" ); |
| DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" ); |
| |
| // Nur wenn die SubBindings noch von den SuperBindings gelockt sind, diesen Lock entfernen |
| // ( d.h. wenn es mehr Locks als "echte" Locks dort gibt ) |
| if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel ) |
| { |
| // Bindings synchronisieren |
| pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel; |
| |
| // Dieses LeaveRegistrations ist f"ur die SubBindings kein "echtes" |
| pImp->pSubBindings->pImp->nOwnRegLevel++; |
| pImp->pSubBindings->LEAVEREGISTRATIONS(); |
| } |
| |
| pImp->nOwnRegLevel--; |
| |
| // check if this is the outer most level |
| if ( --nRegLevel == 0 && !SFX_APP()->IsDowning() ) |
| { |
| if ( pImp->bContextChanged ) |
| { |
| pImp->bContextChanged = sal_False; |
| /* |
| ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame |
| ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY ); |
| if ( xFrame.is() ) |
| xFrame->contextChanged();*/ |
| } |
| |
| #ifndef slow |
| SfxViewFrame* pFrame = pDispatcher->GetFrame(); |
| |
| // ggf unbenutzte Caches entfernen bzw. PlugInInfo aufbereiten |
| if ( pImp->bCtrlReleased ) |
| { |
| for ( sal_uInt16 nCache = pImp->pCaches->Count(); nCache > 0; --nCache ) |
| { |
| // Cache via ::com::sun::star::sdbcx::Index besorgen |
| SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1); |
| |
| // kein Controller mehr interessiert |
| if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() ) |
| { |
| // Cache entfernen. Safety: first remove and then delete |
| SfxStateCache* pSfxStateCache = (*pImp->pCaches)[nCache-1]; |
| pImp->pCaches->Remove(nCache-1, 1); |
| delete pSfxStateCache; |
| } |
| else |
| { |
| // neue Controller mit den alten Items benachrichtigen |
| //!pCache->SetCachedState(); |
| } |
| } |
| } |
| #endif |
| // restart background-processing |
| pImp->nMsgPos = 0; |
| if ( !pFrame || !pFrame->GetObjectShell() ) |
| return; |
| if ( pImp->pCaches && pImp->pCaches->Count() ) |
| { |
| pImp->aTimer.Stop(); |
| pImp->aTimer.SetTimeout(TIMEOUT_FIRST); |
| pImp->aTimer.Start(); |
| // pImp->bFirstRound = sal_True; |
| } |
| } |
| |
| #ifdef DBG_UTIL |
| ByteString aMsg; |
| aMsg.Fill( Min(nRegLevel, sal_uInt16(8)) ); |
| aMsg += "this = "; |
| aMsg += ByteString::CreateFromInt32((long)this); |
| aMsg += " Level = "; |
| aMsg += ByteString::CreateFromInt32(nRegLevel); |
| aMsg += " SfxBindings::LeaveRegistrations "; |
| if(pFile) { |
| aMsg += "File: "; |
| aMsg += pFile; |
| aMsg += " Line: "; |
| aMsg += ByteString::CreateFromInt32(nLine); |
| } |
| // FILE* pLog = fopen( "c:\\bindings.log", "a+w" ); |
| // fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog ); |
| // fclose( pLog ); |
| DbgTrace( aMsg.GetBuffer() ); |
| #endif |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| const SfxSlot* SfxBindings::GetSlot(sal_uInt16 nSlotId) |
| { |
| DBG_MEMTEST(); |
| DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" ); |
| |
| // syncronisieren |
| pDispatcher->Flush(); |
| if ( pImp->bMsgDirty ) |
| UpdateSlotServer_Impl(); |
| |
| // get the cache for the specified function; return if not bound |
| SfxStateCache* pCache = GetStateCache(nSlotId); |
| return pCache && pCache->GetSlotServer(*pDispatcher, pImp->xProv)? |
| pCache->GetSlotServer(*pDispatcher, pImp->xProv)->GetSlot(): 0; |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::SetDispatcher( SfxDispatcher *pDisp ) |
| { |
| SfxDispatcher *pOldDispat = pDispatcher; |
| if ( pDisp != pDispatcher ) |
| { |
| if ( pOldDispat ) |
| { |
| SfxBindings* pBind = pOldDispat->GetBindings(); |
| while ( pBind ) |
| { |
| if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp ) |
| pBind->SetSubBindings_Impl( NULL ); |
| pBind = pBind->pImp->pSubBindings; |
| } |
| } |
| |
| pDispatcher = pDisp; |
| |
| ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv; |
| if ( pDisp ) |
| xProv = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > |
| ( pDisp->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY ); |
| |
| SetDispatchProvider_Impl( xProv ); |
| InvalidateAll( sal_True ); |
| InvalidateUnoControllers_Impl(); |
| |
| if ( pDispatcher && !pOldDispat ) |
| { |
| if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat ) |
| { |
| DBG_ERROR( "SubBindings vor Aktivieren schon gesetzt!" ); |
| pImp->pSubBindings->ENTERREGISTRATIONS(); |
| } |
| LEAVEREGISTRATIONS(); |
| } |
| else if( !pDispatcher ) |
| { |
| ENTERREGISTRATIONS(); |
| if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat ) |
| { |
| DBG_ERROR( "SubBindings im Deaktivieren immer noch gesetzt!" ); |
| pImp->pSubBindings->LEAVEREGISTRATIONS(); |
| } |
| } |
| |
| Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) ); |
| |
| if ( pDisp ) |
| { |
| SfxBindings* pBind = pDisp->GetBindings(); |
| while ( pBind && pBind != this ) |
| { |
| if ( !pBind->pImp->pSubBindings ) |
| { |
| pBind->SetSubBindings_Impl( this ); |
| break; |
| } |
| |
| pBind = pBind->pImp->pSubBindings; |
| } |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| |
| void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId ) |
| { |
| GetStateCache(nSlotId)->ClearCache(); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SfxBindings::StartUpdate_Impl( sal_Bool bComplete ) |
| { |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->StartUpdate_Impl( bComplete ); |
| |
| if ( !bComplete ) |
| // Update darf unterbrochen werden |
| NextJob_Impl(&pImp->aTimer); |
| else |
| // alle Slots am St"uck updaten |
| NextJob_Impl(0); |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, SfxPoolItem* &rpState ) |
| { |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp; |
| SfxStateCache *pCache = GetStateCache( nSlot ); |
| if ( pCache ) |
| xDisp = pCache->GetDispatch(); |
| if ( xDisp.is() || !pCache ) |
| { |
| const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pDispatcher->GetFrame() ).GetSlot( nSlot ); |
| if ( !pSlot || !pSlot->pUnoName ) |
| return SFX_ITEM_DISABLED; |
| |
| ::com::sun::star::util::URL aURL; |
| ::rtl::OUString aCmd( DEFINE_CONST_UNICODE(".uno:")); |
| aURL.Protocol = aCmd; |
| aURL.Path = ::rtl::OUString::createFromAscii(pSlot->GetUnoName()); |
| aCmd += aURL.Path; |
| aURL.Complete = aCmd; |
| aURL.Main = aCmd; |
| |
| if ( !xDisp.is() ) |
| xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); |
| |
| if ( xDisp.is() ) |
| { |
| ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY ); |
| SfxOfficeDispatch* pDisp = NULL; |
| if ( xTunnel.is() ) |
| { |
| sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier()); |
| pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation )); |
| } |
| |
| if ( !pDisp ) |
| { |
| sal_Bool bDeleteCache = sal_False; |
| if ( !pCache ) |
| { |
| pCache = new SfxStateCache( nSlot ); |
| pCache->GetSlotServer( *GetDispatcher_Impl(), pImp->xProv ); |
| bDeleteCache = sal_True; |
| } |
| |
| SfxItemState eState = SFX_ITEM_SET; |
| SfxPoolItem *pItem=NULL; |
| BindDispatch_Impl *pBind = new BindDispatch_Impl( xDisp, aURL, pCache, pSlot ); |
| pBind->acquire(); |
| xDisp->addStatusListener( pBind, aURL ); |
| if ( !pBind->GetStatus().IsEnabled ) |
| { |
| eState = SFX_ITEM_DISABLED; |
| } |
| else |
| { |
| ::com::sun::star::uno::Any aAny = pBind->GetStatus().State; |
| ::com::sun::star::uno::Type pType = aAny.getValueType(); |
| |
| if ( pType == ::getBooleanCppuType() ) |
| { |
| sal_Bool bTemp = false; |
| aAny >>= bTemp ; |
| pItem = new SfxBoolItem( nSlot, bTemp ); |
| } |
| else if ( pType == ::getCppuType((const sal_uInt16*)0) ) |
| { |
| sal_uInt16 nTemp = 0; |
| aAny >>= nTemp ; |
| pItem = new SfxUInt16Item( nSlot, nTemp ); |
| } |
| else if ( pType == ::getCppuType((const sal_uInt32*)0) ) |
| { |
| sal_uInt32 nTemp = 0; |
| aAny >>= nTemp ; |
| pItem = new SfxUInt32Item( nSlot, nTemp ); |
| } |
| else if ( pType == ::getCppuType((const ::rtl::OUString*)0) ) |
| { |
| ::rtl::OUString sTemp ; |
| aAny >>= sTemp ; |
| pItem = new SfxStringItem( nSlot, sTemp ); |
| } |
| else |
| pItem = new SfxVoidItem( nSlot ); |
| } |
| |
| xDisp->removeStatusListener( pBind, aURL ); |
| pBind->Release(); |
| rpState = pItem; |
| if ( bDeleteCache ) |
| DELETEZ( pCache ); |
| return eState; |
| } |
| } |
| } |
| |
| // Dann am Dispatcher testen; da die von dort zur"uckgegebenen Items immer |
| // DELETE_ON_IDLE sind, mu\s eine Kopie davon gezogen werden, um einen |
| // Eigent"umer"ubergang zu erm"oglichen |
| const SfxPoolItem *pItem = NULL; |
| SfxItemState eState = pDispatcher->QueryState( nSlot, pItem ); |
| if ( eState == SFX_ITEM_SET ) |
| { |
| DBG_ASSERT( pItem, "SFX_ITEM_SET aber kein Item!" ); |
| if ( pItem ) |
| rpState = pItem->Clone(); |
| } |
| else if ( eState == SFX_ITEM_AVAILABLE && pItem ) |
| { |
| rpState = pItem->Clone(); |
| } |
| |
| return eState; |
| } |
| |
| void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub ) |
| { |
| if ( pImp->pSubBindings ) |
| { |
| pImp->pSubBindings->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () ); |
| pImp->pSubBindings->pImp->pSuperBindings = NULL; |
| } |
| |
| pImp->pSubBindings = pSub; |
| |
| if ( pSub ) |
| { |
| pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv ); |
| pSub->pImp->pSuperBindings = this; |
| } |
| } |
| |
| SfxBindings* SfxBindings::GetSubBindings_Impl( sal_Bool bTop ) const |
| { |
| SfxBindings *pRet = pImp->pSubBindings; |
| if ( bTop ) |
| { |
| while ( pRet->pImp->pSubBindings ) |
| pRet = pRet->pImp->pSubBindings; |
| } |
| |
| return pRet; |
| } |
| |
| void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork ) |
| { |
| pImp->pWorkWin = pWork; |
| } |
| |
| SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const |
| { |
| return pImp->pWorkWin; |
| } |
| |
| void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl ) |
| { |
| if ( !pImp->pUnoCtrlArr ) |
| pImp->pUnoCtrlArr = new SfxUnoControllerArr_Impl; |
| pImp->pUnoCtrlArr->Insert( pControl, pImp->pUnoCtrlArr->Count() ); |
| } |
| |
| void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl ) |
| { |
| if ( pImp->pUnoCtrlArr ) |
| { |
| sal_uInt16 nPos = pImp->pUnoCtrlArr->GetPos( pControl ); |
| if ( nPos != 0xFFFF ) |
| { |
| pImp->pUnoCtrlArr->Remove( nPos ); |
| return; |
| } |
| } |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->ReleaseUnoController_Impl( pControl ); |
| } |
| |
| void SfxBindings::InvalidateUnoControllers_Impl() |
| { |
| if ( pImp->pUnoCtrlArr ) |
| { |
| sal_uInt16 nCount = pImp->pUnoCtrlArr->Count(); |
| for ( sal_uInt16 n=nCount; n>0; n-- ) |
| { |
| SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1]; |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > xRef( (::cppu::OWeakObject*)pCtrl, ::com::sun::star::uno::UNO_QUERY ); |
| pCtrl->ReleaseDispatch(); |
| pCtrl->GetNewDispatch(); |
| } |
| } |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->InvalidateUnoControllers_Impl(); |
| } |
| |
| sal_Bool SfxBindings::IsInUpdate() const |
| { |
| sal_Bool bInUpdate = pImp->bInUpdate; |
| if ( !bInUpdate && pImp->pSubBindings ) |
| bInUpdate = pImp->pSubBindings->IsInUpdate(); |
| return bInUpdate; |
| } |
| |
| void SfxBindings::SetVisibleState( sal_uInt16 nId, sal_Bool bShow ) |
| { |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp; |
| SfxStateCache *pCache = GetStateCache( nId ); |
| if ( pCache ) |
| pCache->SetVisibleState( bShow ); |
| } |
| |
| void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame ) |
| { |
| if ( rFrame.is() || !pDispatcher ) |
| SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) ); |
| else |
| SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( |
| pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ) ); |
| } |
| |
| const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxBindings::GetActiveFrame() const |
| { |
| const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( pImp->xProv, ::com::sun::star::uno::UNO_QUERY ); |
| if ( xFrame.is() || !pDispatcher ) |
| return xFrame; |
| else |
| return pDispatcher->GetFrame()->GetFrame().GetFrameInterface(); |
| } |
| |
| void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv ) |
| { |
| sal_Bool bInvalidate = ( rProv != pImp->xProv ); |
| if ( bInvalidate ) |
| { |
| pImp->xProv = rProv; |
| InvalidateAll( sal_True ); |
| InvalidateUnoControllers_Impl(); |
| } |
| |
| if ( pImp->pSubBindings ) |
| pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv ); |
| } |
| |
| const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & SfxBindings::GetDispatchProvider_Impl() const |
| { |
| return pImp->xProv; |
| } |
| |
| SystemWindow* SfxBindings::GetSystemWindow() const |
| { |
| SfxViewFrame *pFrame = pDispatcher->GetFrame(); |
| while ( pFrame->GetParentViewFrame_Impl() ) |
| pFrame = pFrame->GetParentViewFrame_Impl(); |
| SfxViewFrame* pTop = pFrame->GetTopViewFrame(); |
| return pTop->GetFrame().GetTopWindow_Impl(); |
| } |
| |
| sal_Bool SfxBindings::ExecuteCommand_Impl( const String& rCommand ) |
| { |
| ::com::sun::star::util::URL aURL; |
| aURL.Complete = rCommand; |
| Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY ); |
| xTrans->parseStrict( aURL ); |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); |
| if ( xDisp.is() ) |
| { |
| if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# |
| { |
| ::rtl::OUString sAppName; |
| try |
| { |
| static ::rtl::OUString our_aModuleManagerName = ::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager"); |
| ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = |
| ::comphelper::getProcessServiceFactory(); |
| ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > xModuleManager( |
| xServiceManager->createInstance(our_aModuleManagerName) |
| , ::com::sun::star::uno::UNO_QUERY_THROW); |
| ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame( |
| pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY_THROW); |
| sAppName = xModuleManager->identify(xFrame); |
| } catch(::com::sun::star::uno::Exception&) {} |
| Sequence<beans::PropertyValue> source; |
| ::comphelper::UiEventsLogger::appendDispatchOrigin(source, sAppName, ::rtl::OUString::createFromAscii("SfxAsyncExec")); |
| ::comphelper::UiEventsLogger::logDispatch(aURL, source); |
| } |
| new SfxAsyncExec_Impl( aURL, xDisp ); |
| return sal_True; |
| } |
| |
| return sal_False; |
| } |
| |
| com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxBindings::GetRecorder() const |
| { |
| return pImp->xRecorder; |
| } |
| |
| void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder >& rRecorder ) |
| { |
| pImp->xRecorder = rRecorder; |
| } |
| |
| void SfxBindings::ContextChanged_Impl() |
| { |
| if ( !pImp->bInUpdate && ( !pImp->bContextChanged || !pImp->bAllMsgDirty ) ) |
| { |
| InvalidateAll( sal_True ); |
| } |
| } |
| |
| uno::Reference < frame::XDispatch > SfxBindings::GetDispatch( const SfxSlot* pSlot, const util::URL& aURL, sal_Bool bMasterCommand ) |
| { |
| uno::Reference < frame::XDispatch > xRet; |
| SfxStateCache* pCache = GetStateCache( pSlot->nSlotId ); |
| if ( pCache && !bMasterCommand ) |
| xRet = pCache->GetInternalDispatch(); |
| if ( !xRet.is() ) |
| { |
| // dispatches for slaves are unbound, they don't have a state |
| SfxOfficeDispatch* pDispatch = bMasterCommand ? |
| new SfxOfficeDispatch( pDispatcher, pSlot, aURL ) : |
| new SfxOfficeDispatch( *this, pDispatcher, pSlot, aURL ); |
| |
| pDispatch->SetMasterUnoCommand( bMasterCommand ); |
| xRet = uno::Reference < frame::XDispatch >( pDispatch ); |
| if ( !pCache ) |
| pCache = GetStateCache( pSlot->nSlotId ); |
| |
| DBG_ASSERT( pCache, "No cache for OfficeDispatch!" ); |
| if ( pCache && !bMasterCommand ) |
| pCache->SetInternalDispatch( xRet ); |
| } |
| |
| return xRet; |
| } |