1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bindings.cxx,v $
10 * $Revision: 1.53.46.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
35 #include <svtools/itempool.hxx>
36 #include <svtools/itemiter.hxx>
37 #include <svtools/eitem.hxx>
38 #include <svtools/aeitem.hxx>
39 #include <svtools/intitem.hxx>
40 #include <svtools/stritem.hxx>
41 #include <svtools/visitem.hxx>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
44 #include <com/sun/star/frame/XDispatch.hpp>
45 #include <com/sun/star/frame/XDispatchProvider.hpp>
46 #include <com/sun/star/frame/XStatusListener.hpp>
47 #include <com/sun/star/frame/FrameSearchFlag.hpp>
48 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
49 #include <com/sun/star/frame/FeatureStateEvent.hpp>
50 #include <com/sun/star/frame/DispatchDescriptor.hpp>
51 #include <com/sun/star/frame/XController.hpp>
52 #include <comphelper/processfactory.hxx>
53 #include <svtools/itemdel.hxx>
59 #include "appdata.hxx"
60 #include <sfx2/bindings.hxx>
61 #include <sfx2/msg.hxx>
62 #include "statcach.hxx"
63 #include <sfx2/ctrlitem.hxx>
64 #include <sfx2/app.hxx>
65 #include <sfx2/dispatch.hxx>
66 #include <sfx2/request.hxx>
67 #include <sfx2/objface.hxx>
68 #include "sfxtypes.hxx"
69 #include "workwin.hxx"
70 #include <sfx2/macrconf.hxx>
71 #include <sfx2/unoctitm.hxx>
72 #include <sfx2/sfx.hrc>
73 #include <sfx2/sfxuno.hxx>
74 #include <sfx2/topfrm.hxx>
75 #include <sfx2/objsh.hxx>
76 #include <sfx2/msgpool.hxx>
78 #include <comphelper/uieventslogger.hxx>
79 #include <com/sun/star/frame/XModuleManager.hpp>
82 using namespace ::com::sun::star
;
83 using namespace ::com::sun::star::uno
;
84 using namespace ::com::sun::star::util
;
86 DBG_NAME(SfxBindingsMsgPos
)
87 DBG_NAME(SfxBindingsUpdateServers
)
88 DBG_NAME(SfxBindingsCreateSet
)
89 DBG_NAME(SfxBindingsUpdateCtrl1
)
90 DBG_NAME(SfxBindingsUpdateCtrl2
)
91 DBG_NAME(SfxBindingsNextJob_Impl0
)
92 DBG_NAME(SfxBindingsNextJob_Impl
)
93 DBG_NAME(SfxBindingsUpdate_Impl
)
94 DBG_NAME(SfxBindingsInvalidateAll
)
96 //====================================================================
98 static USHORT nTimeOut
= 300;
100 #define TIMEOUT_FIRST nTimeOut
101 #define TIMEOUT_UPDATING 20
102 #define TIMEOUT_IDLE 2500
104 static sal_uInt32 nCache1
= 0;
105 static sal_uInt32 nCache2
= 0;
107 typedef std::hash_map
< USHORT
, bool > InvalidateSlotMap
;
109 //====================================================================
111 DECL_PTRARRAY(SfxStateCacheArr_Impl
, SfxStateCache
*, 32, 16)
113 //====================================================================
115 class SfxAsyncExec_Impl
117 ::com::sun::star::util::URL aCommand
;
118 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
123 SfxAsyncExec_Impl( const ::com::sun::star::util::URL
& rCmd
, const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
>& rDisp
)
127 aTimer
.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl
, TimerHdl
) );
128 aTimer
.SetTimeout( 0 );
132 DECL_LINK( TimerHdl
, Timer
*);
135 IMPL_LINK(SfxAsyncExec_Impl
, TimerHdl
, Timer
*, pTimer
)
137 (void)pTimer
; // unused
140 Sequence
<beans::PropertyValue
> aSeq
;
141 xDisp
->dispatch( aCommand
, aSeq
);
147 class SfxBindings_Impl
150 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchRecorder
> xRecorder
;
151 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> xProv
;
152 SfxUnoControllerArr_Impl
*
154 SfxWorkWindow
* pWorkWin
;
155 SfxBindings
* pSubBindings
;
156 SfxBindings
* pSuperBindings
;
157 SfxStateCacheArr_Impl
* pCaches
; // je ein cache fuer jede gebundene
158 sal_uInt16 nCachedFunc1
; // index der zuletzt gerufenen
159 sal_uInt16 nCachedFunc2
; // index der vorletzt gerufenen
160 sal_uInt16 nMsgPos
; // Message-Position, ab der zu aktualisieren ist
161 SfxPopupAction ePopupAction
; // in DeleteFloatinWindow() abgefragt
162 sal_Bool bContextChanged
;
163 sal_Bool bMsgDirty
; // wurde ein MessageServer invalidiert?
164 sal_Bool bAllMsgDirty
; // wurden die MessageServer invalidiert?
165 sal_Bool bAllDirty
; // nach InvalidateAll
166 sal_Bool bCtrlReleased
; // waehrend EnterRegistrations
167 AutoTimer aTimer
; // fuer volatile Slots
168 sal_Bool bInUpdate
; // fuer Assertions
169 sal_Bool bInNextJob
; // fuer Assertions
170 sal_Bool bFirstRound
; // Erste Runde im Update
171 sal_uInt16 nFirstShell
; // Shell, die in erster Runde bevorzugt wird
172 sal_uInt16 nOwnRegLevel
; // z"ahlt die echten Locks, ohne die der SuperBindings
173 InvalidateSlotMap m_aInvalidateSlots
; // store slots which are invalidated while in update
176 //--------------------------------------------------------------------
178 struct SfxFoundCache_Impl
180 sal_uInt16 nSlotId
; // die Slot-Id
181 sal_uInt16 nWhichId
; // falls verf"ugbar die Which-Id, sonst nSlotId
182 const SfxSlot
* pSlot
; // Pointer auf den <Master-Slot>
183 SfxStateCache
* pCache
; // Pointer auf den StatusCache, ggf. 0
185 SfxFoundCache_Impl():
192 SfxFoundCache_Impl(SfxFoundCache_Impl
&r
):
194 nWhichId(r
.nWhichId
),
199 SfxFoundCache_Impl(sal_uInt16 nS
, sal_uInt16 nW
, const SfxSlot
*pS
, SfxStateCache
*pC
):
206 int operator<( const SfxFoundCache_Impl
&r
) const
207 { return nWhichId
< r
.nWhichId
; }
209 int operator==( const SfxFoundCache_Impl
&r
) const
210 { return nWhichId
== r
.nWhichId
; }
213 //--------------------------------------------------------------------------
215 SV_DECL_PTRARR_SORT_DEL(SfxFoundCacheArr_Impl
, SfxFoundCache_Impl
*, 16, 16 )
216 SV_IMPL_OP_PTRARR_SORT(SfxFoundCacheArr_Impl
, SfxFoundCache_Impl
*);
218 //==========================================================================
220 SfxBindings::SfxBindings()
221 : pImp(new SfxBindings_Impl
),
223 nRegLevel(1) // geht erst auf 0, wenn Dispatcher gesetzt
226 pImp
->bAllMsgDirty
= sal_True
;
227 pImp
->bContextChanged
= sal_False
;
228 pImp
->bMsgDirty
= sal_True
;
229 pImp
->bAllDirty
= sal_True
;
230 pImp
->ePopupAction
= SFX_POPUP_DELETE
;
231 pImp
->nCachedFunc1
= 0;
232 pImp
->nCachedFunc2
= 0;
233 pImp
->bCtrlReleased
= sal_False
;
234 pImp
->bFirstRound
= sal_False
;
235 pImp
->bInNextJob
= sal_False
;
236 pImp
->bInUpdate
= sal_False
;
237 pImp
->pSubBindings
= NULL
;
238 pImp
->pSuperBindings
= NULL
;
239 pImp
->pWorkWin
= NULL
;
240 pImp
->pUnoCtrlArr
= NULL
;
241 pImp
->nOwnRegLevel
= nRegLevel
;
243 // all caches are valid (no pending invalidate-job)
244 // create the list of caches
245 pImp
->pCaches
= new SfxStateCacheArr_Impl
;
246 pImp
->aTimer
.SetTimeoutHdl( LINK(this, SfxBindings
, NextJob_Impl
) );
249 //====================================================================
251 SfxBindings::~SfxBindings()
255 Destruktor der Klasse SfxBindings. Die eine, f"ur jede <SfxApplication>
256 existierende Instanz wird von der <SfxApplication> nach Ausf"urhung
257 von <SfxApplication::Exit()> automatisch zerst"ort.
259 Noch existierende <SfxControllerItem> Instanzen, die bei dieser
260 SfxBindings Instanz angemeldet sind, werden im Destruktor
261 automatisch zerst"ort. Dies sind i.d.R. Floating-Toolboxen, Value-Sets
262 etc. Arrays von SfxControllerItems d"urfen zu diesem Zeitpunkt nicht
267 // Die SubBindings sollen ja nicht gelocked werden !
268 pImp
->pSubBindings
= NULL
;
270 ENTERREGISTRATIONS();
273 DeleteControllers_Impl();
275 // Caches selbst l"oschen
276 sal_uInt16 nCount
= pImp
->pCaches
->Count();
277 for ( sal_uInt16 nCache
= 0; nCache
< nCount
; ++nCache
)
278 delete pImp
->pCaches
->GetObject(nCache
);
280 DELETEZ( pImp
->pWorkWin
);
282 delete pImp
->pCaches
;
286 //--------------------------------------------------------------------
288 void SfxBindings::DeleteControllers_Impl()
290 // in der ersten Runde den SfxPopupWindows l"oschen
291 sal_uInt16 nCount
= pImp
->pCaches
->Count();
293 for ( nCache
= 0; nCache
< nCount
; ++nCache
)
296 SfxStateCache
*pCache
= pImp
->pCaches
->GetObject(nCache
);
297 sal_uInt16 nSlotId
= pCache
->GetId();
299 // SfxPopupWindow l"oschen lassen
300 pCache
->DeleteFloatingWindows();
302 // da der Cache verkleinert worden sein kann, wiederaufsetzen
303 sal_uInt16 nNewCount
= pImp
->pCaches
->Count();
304 if ( nNewCount
< nCount
)
306 nCache
= GetSlotPos(nSlotId
);
307 if ( nCache
>= nNewCount
||
308 nSlotId
!= pImp
->pCaches
->GetObject(nCache
)->GetId() )
314 // alle Caches l"oschen
315 for ( nCache
= pImp
->pCaches
->Count(); nCache
> 0; --nCache
)
317 // Cache via ::com::sun::star::sdbcx::Index besorgen
318 SfxStateCache
*pCache
= pImp
->pCaches
->GetObject(nCache
-1);
320 // alle Controller in dem Cache unbinden
321 SfxControllerItem
*pNext
;
322 for ( SfxControllerItem
*pCtrl
= pCache
->GetItemLink();
323 pCtrl
; pCtrl
= pNext
)
325 pNext
= pCtrl
->GetItemLink();
329 if ( pCache
->GetInternalController() )
330 pCache
->GetInternalController()->UnBind();
333 if( nCache
-1 < pImp
->pCaches
->Count() )
334 delete (*pImp
->pCaches
)[nCache
-1];
335 pImp
->pCaches
->Remove(nCache
-1, 1);
338 if( pImp
->pUnoCtrlArr
)
340 sal_uInt16 nCtrlCount
= pImp
->pUnoCtrlArr
->Count();
341 for ( sal_uInt16 n
=nCtrlCount
; n
>0; n
-- )
343 SfxUnoControllerItem
*pCtrl
= (*pImp
->pUnoCtrlArr
)[n
-1];
344 pCtrl
->ReleaseBindings();
347 DBG_ASSERT( !pImp
->pUnoCtrlArr
->Count(), "UnoControllerItems nicht entfernt!" );
348 DELETEZ( pImp
->pUnoCtrlArr
);
352 //--------------------------------------------------------------------
354 SfxPopupAction
SfxBindings::GetPopupAction_Impl() const
356 return pImp
->ePopupAction
;
360 //--------------------------------------------------------------------
362 void SfxBindings::HidePopups( bool bHide
)
364 // SfxPopupWindows hiden
365 HidePopupCtrls_Impl( bHide
);
366 SfxBindings
*pSub
= pImp
->pSubBindings
;
369 pImp
->pSubBindings
->HidePopupCtrls_Impl( bHide
);
370 pSub
= pSub
->pImp
->pSubBindings
;
373 // SfxChildWindows hiden
374 DBG_ASSERT( pDispatcher
, "HidePopups not allowed without dispatcher" );
375 if ( pImp
->pWorkWin
)
376 pImp
->pWorkWin
->HidePopups_Impl( bHide
, sal_True
);
379 void SfxBindings::HidePopupCtrls_Impl( FASTBOOL bHide
)
383 // SfxPopupWindows hiden
384 pImp
->ePopupAction
= SFX_POPUP_HIDE
;
388 // SfxPopupWindows showen
389 pImp
->ePopupAction
= SFX_POPUP_SHOW
;
392 for ( sal_uInt16 nCache
= 0; nCache
< pImp
->pCaches
->Count(); ++nCache
)
393 pImp
->pCaches
->GetObject(nCache
)->DeleteFloatingWindows();
394 pImp
->ePopupAction
= SFX_POPUP_DELETE
;
397 //--------------------------------------------------------------------
399 void SfxBindings::Update_Impl
401 SfxStateCache
* pCache
// der upzudatende SfxStatusCache
404 if( pCache
->GetDispatch().is() && pCache
->GetItemLink() )
406 pCache
->SetCachedState(TRUE
);
407 if ( !pCache
->GetInternalController() )
413 DBG_PROFSTART(SfxBindingsUpdate_Impl
);
415 // alle mit derselben Statusmethode zusammensammeln, die dirty sind
416 SfxDispatcher
&rDispat
= *pDispatcher
;
417 const SfxSlot
*pRealSlot
= 0;
418 const SfxSlotServer
* pMsgServer
= 0;
419 SfxFoundCacheArr_Impl aFound
;
420 SfxItemSet
*pSet
= CreateSet_Impl( pCache
, pRealSlot
, &pMsgServer
, aFound
);
421 sal_Bool bUpdated
= sal_False
;
425 if ( rDispat
._FillState( *pMsgServer
, *pSet
, pRealSlot
) )
428 const SfxInterface
*pInterface
=
429 rDispat
.GetShell(pMsgServer
->GetShellLevel())->GetInterface();
430 for ( sal_uInt16 nPos
= 0; nPos
< aFound
.Count(); ++nPos
)
432 const SfxFoundCache_Impl
*pFound
= aFound
[nPos
];
433 sal_uInt16 nWhich
= pFound
->nWhichId
;
434 const SfxPoolItem
*pItem
= 0;
435 SfxItemState eState
= pSet
->GetItemState(nWhich
, sal_True
, &pItem
);
436 if ( eState
== SFX_ITEM_DEFAULT
&& SfxItemPool::IsWhich(nWhich
) )
437 pItem
= &pSet
->Get(nWhich
);
438 UpdateControllers_Impl( pInterface
, aFound
[nPos
], pItem
, eState
);
446 if ( !bUpdated
&& pCache
)
448 // Wenn pCache == NULL und kein SlotServer ( z.B. weil Dispatcher gelockt! ),
449 // darf nat"urlich kein Update versucht werden
450 SfxFoundCache_Impl
aFoundCache(
453 UpdateControllers_Impl( 0, &aFoundCache
, 0, SFX_ITEM_DISABLED
);
456 DBG_PROFSTOP(SfxBindingsUpdate_Impl
);
459 //--------------------------------------------------------------------
461 void SfxBindings::InvalidateSlotsInMap_Impl()
463 InvalidateSlotMap::const_iterator pIter
= pImp
->m_aInvalidateSlots
.begin();
464 while ( pIter
!= pImp
->m_aInvalidateSlots
.end() )
466 Invalidate( pIter
->first
);
469 pImp
->m_aInvalidateSlots
.clear();
472 //--------------------------------------------------------------------
474 void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( USHORT nId
)
476 pImp
->m_aInvalidateSlots
[nId
] = sal_True
;
479 //--------------------------------------------------------------------
481 void SfxBindings::Update
483 sal_uInt16 nId
// die gebundene und upzudatende Slot-Id
487 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
489 //!!TLX: Fuehrte zu Vorlagenkatalogstillstand
494 pDispatcher
->Flush();
496 if ( pImp
->pSubBindings
)
497 pImp
->pSubBindings
->Update( nId
);
499 SfxStateCache
* pCache
= GetStateCache( nId
);
502 pImp
->bInUpdate
= sal_True
;
503 if ( pImp
->bMsgDirty
)
505 UpdateSlotServer_Impl();
506 pCache
= GetStateCache( nId
);
511 BOOL bInternalUpdate
= TRUE
;
512 if( pCache
->GetDispatch().is() && pCache
->GetItemLink() )
514 pCache
->SetCachedState(TRUE
);
515 bInternalUpdate
= ( pCache
->GetInternalController() != 0 );
518 if ( bInternalUpdate
)
521 const SfxSlotServer
* pMsgServer
= pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
522 if ( !pCache
->IsControllerDirty() &&
524 !pMsgServer
->GetSlot()->IsMode(SFX_SLOT_VOLATILE
) ) )
526 pImp
->bInUpdate
= sal_False
;
527 InvalidateSlotsInMap_Impl();
532 pCache
->SetState(SFX_ITEM_DISABLED
, 0);
533 pImp
->bInUpdate
= sal_False
;
534 InvalidateSlotsInMap_Impl();
541 pImp
->bAllDirty
= sal_False
;
544 pImp
->bInUpdate
= sal_False
;
545 InvalidateSlotsInMap_Impl();
549 //--------------------------------------------------------------------
551 void SfxBindings::Update()
554 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
556 if ( pImp
->pSubBindings
)
557 pImp
->pSubBindings
->Update();
564 pImp
->bInUpdate
= sal_True
;
565 pDispatcher
->Flush();
566 pDispatcher
->Update_Impl();
567 while ( !NextJob_Impl(0) )
569 pImp
->bInUpdate
= sal_False
;
570 InvalidateSlotsInMap_Impl();
574 //--------------------------------------------------------------------
576 void SfxBindings::SetState
578 const SfxItemSet
& rSet
// zu setzende Status-Werte
581 // wenn gelockt, dann nur invalidieren
584 SfxItemIter
aIter(rSet
);
585 for ( const SfxPoolItem
*pItem
= aIter
.FirstItem();
587 pItem
= aIter
.NextItem() )
588 Invalidate( pItem
->Which() );
592 // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
593 if ( pImp
->bMsgDirty
)
594 UpdateSlotServer_Impl();
596 // "uber das ItemSet iterieren, falls Slot gebunden, updaten
597 //! Bug: WhichIter verwenden und ggf. VoidItems hochschicken
598 SfxItemIter
aIter(rSet
);
599 for ( const SfxPoolItem
*pItem
= aIter
.FirstItem();
601 pItem
= aIter
.NextItem() )
603 SfxStateCache
* pCache
=
604 GetStateCache( rSet
.GetPool()->GetSlotId(pItem
->Which()) );
608 if ( !pCache
->IsControllerDirty() )
609 pCache
->Invalidate(sal_False
);
610 pCache
->SetState( SFX_ITEM_AVAILABLE
, pItem
);
612 //! nicht implementiert: Updates von EnumSlots via MasterSlots
618 //--------------------------------------------------------------------
620 void SfxBindings::SetState
622 const SfxPoolItem
& rItem
// zu setzender Status-Wert
627 Invalidate( rItem
.Which() );
631 // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
632 if ( pImp
->bMsgDirty
)
633 UpdateSlotServer_Impl();
635 // falls der Slot gebunden ist, updaten
636 DBG_ASSERT( SfxItemPool::IsSlot( rItem
.Which() ),
637 "cannot set items with which-id" );
638 SfxStateCache
* pCache
= GetStateCache( rItem
.Which() );
642 if ( !pCache
->IsControllerDirty() )
643 pCache
->Invalidate(sal_False
);
644 pCache
->SetState( SFX_ITEM_AVAILABLE
, &rItem
);
646 //! nicht implementiert: Updates von EnumSlots via MasterSlots
652 //--------------------------------------------------------------------
654 SfxStateCache
* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId
)
656 SfxStateCache
* pCache
= GetStateCache( nId
);
657 if ( !pCache
&& pImp
->pSubBindings
)
658 return pImp
->pSubBindings
->GetAnyStateCache_Impl( nId
);
662 SfxStateCache
* SfxBindings::GetStateCache
664 sal_uInt16 nId
/* Slot-Id, deren SfxStatusCache gefunden
666 sal_uInt16
* pPos
/* 0 bzw. Position, ab der die Bindings
667 bin"ar durchsucht werden sollen. Liefert
668 die Position zur"uck, an der nId gefunden
669 wurde, bzw. an der es einfef"ugt werden
674 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
675 // is the specified function bound?
676 const sal_uInt16 nStart
= ( pPos
? *pPos
: 0 );
677 const sal_uInt16 nPos
= GetSlotPos( nId
, nStart
);
679 if ( nPos
< pImp
->pCaches
->Count() &&
680 (*pImp
->pCaches
)[nPos
]->GetId() == nId
)
684 return (*pImp
->pCaches
)[nPos
];
689 //--------------------------------------------------------------------
691 void SfxBindings::InvalidateAll
693 sal_Bool bWithMsg
/* sal_True
694 Slot-Server als ung"ultig markieren
697 Slot-Server bleiben g"ultig */
700 DBG_PROFSTART(SfxBindingsInvalidateAll
);
701 DBG_ASSERT( !pImp
->bInUpdate
, "SfxBindings::Invalidate while in update" );
705 if ( pImp
->pSubBindings
)
706 pImp
->pSubBindings
->InvalidateAll( bWithMsg
);
708 // ist schon alles dirty gesetzt oder downing => nicht zu tun
710 ( pImp
->bAllDirty
&& ( !bWithMsg
|| pImp
->bAllMsgDirty
) ) ||
711 SFX_APP()->IsDowning() )
713 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
717 pImp
->bAllMsgDirty
= pImp
->bAllMsgDirty
|| bWithMsg
;
718 pImp
->bMsgDirty
= pImp
->bMsgDirty
|| pImp
->bAllMsgDirty
|| bWithMsg
;
719 pImp
->bAllDirty
= sal_True
;
721 for ( sal_uInt16 n
= 0; n
< pImp
->pCaches
->Count(); ++n
)
722 pImp
->pCaches
->GetObject(n
)->Invalidate(bWithMsg
);
724 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
725 ( pDispatcher->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY );
727 if ( bWithMsg && xFrame.is() )
728 xFrame->contextChanged();
734 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
735 pImp
->aTimer
.Start();
736 // pImp->bFirstRound = sal_True;
737 // pImp->nFirstShell = 0;
740 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
743 //--------------------------------------------------------------------
745 void SfxBindings::Invalidate
747 const sal_uInt16
* pIds
/* numerisch sortiertes 0-terminiertes Array
748 von Slot-Ids (einzel, nicht als Paare!) */
751 DBG_PROFSTART(SfxBindingsInvalidateAll
);
752 // DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
756 if ( pImp
->bInUpdate
)
759 while ( pIds
[i
] != 0 )
760 AddSlotToInvalidateSlotsMap_Impl( pIds
[i
++] );
762 if ( pImp
->pSubBindings
)
763 pImp
->pSubBindings
->Invalidate( pIds
);
767 if ( pImp
->pSubBindings
)
768 pImp
->pSubBindings
->Invalidate( pIds
);
770 // ist schon alles dirty gesetzt oder downing => nicht zu tun
771 if ( !pDispatcher
|| pImp
->bAllDirty
|| SFX_APP()->IsDowning() )
774 // in immer kleiner werdenden Berichen bin"ar suchen
775 for ( sal_uInt16 n
= GetSlotPos(*pIds
);
776 *pIds
&& n
< pImp
->pCaches
->Count();
777 n
= GetSlotPos(*pIds
, n
) )
779 // falls SID "uberhaupt gebunden ist, den Cache invalidieren
780 SfxStateCache
*pCache
= pImp
->pCaches
->GetObject(n
);
781 if ( pCache
->GetId() == *pIds
)
782 pCache
->Invalidate(sal_False
);
787 DBG_ASSERT( *pIds
> *(pIds
-1), "pIds unsorted" );
790 // falls nicht gelockt, Update-Timer starten
795 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
796 pImp
->aTimer
.Start();
797 // pImp->bFirstRound = sal_True;
798 // pImp->nFirstShell = 0;
801 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
804 //--------------------------------------------------------------------
806 void SfxBindings::InvalidateShell
808 const SfxShell
& rSh
/* Die <SfxShell>, deren Slot-Ids
809 invalidiert werden sollen. */,
811 sal_Bool bDeep
/* sal_True
812 auch die, von der SfxShell
813 ererbten Slot-Ids werden invalidert
816 die ererbten und nicht "uberladenen
817 Slot-Ids werden invalidiert */
818 //! MI: z. Zt. immer bDeep
821 DBG_ASSERT( !pImp
->bInUpdate
, "SfxBindings::Invalidate while in update" );
823 if ( pImp
->pSubBindings
)
824 pImp
->pSubBindings
->InvalidateShell( rSh
, bDeep
);
826 if ( !pDispatcher
|| pImp
->bAllDirty
|| SFX_APP()->IsDowning() )
829 DBG_PROFSTART(SfxBindingsInvalidateAll
);
832 // Jetzt schon flushen, wird in GetShellLevel(rSh) sowieso gemacht; wichtig,
833 // damit pImp->bAll(Msg)Dirty korrekt gesetzt ist
834 pDispatcher
->Flush();
837 ( pImp
->bAllDirty
&& pImp
->bAllMsgDirty
) ||
838 SFX_APP()->IsDowning() )
840 // Wenn sowieso demn"achst alle Server geholt werden
845 sal_uInt16 nLevel
= pDispatcher
->GetShellLevel(rSh
);
846 if ( nLevel
!= USHRT_MAX
)
848 for ( sal_uInt16 n
= 0; n
< pImp
->pCaches
->Count(); ++n
)
850 SfxStateCache
*pCache
= pImp
->pCaches
->GetObject(n
);
851 const SfxSlotServer
*pMsgServer
=
852 pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
853 if ( pMsgServer
&& pMsgServer
->GetShellLevel() == nLevel
)
854 pCache
->Invalidate(sal_False
);
860 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
861 pImp
->aTimer
.Start();
862 pImp
->bFirstRound
= sal_True
;
863 pImp
->nFirstShell
= nLevel
;
867 DBG_PROFSTOP(SfxBindingsInvalidateAll
);
870 //--------------------------------------------------------------------
872 void SfxBindings::Invalidate
874 sal_uInt16 nId
// zu invalidierende Slot-Id
878 // DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
880 if ( pImp
->bInUpdate
)
882 AddSlotToInvalidateSlotsMap_Impl( nId
);
883 if ( pImp
->pSubBindings
)
884 pImp
->pSubBindings
->Invalidate( nId
);
888 if ( pImp
->pSubBindings
)
889 pImp
->pSubBindings
->Invalidate( nId
);
891 if ( !pDispatcher
|| pImp
->bAllDirty
|| SFX_APP()->IsDowning() )
894 SfxStateCache
* pCache
= GetStateCache(nId
);
897 pCache
->Invalidate(sal_False
);
898 pImp
->nMsgPos
= Min(GetSlotPos(nId
), pImp
->nMsgPos
);
902 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
903 pImp
->aTimer
.Start();
908 //--------------------------------------------------------------------
910 void SfxBindings::Invalidate
912 sal_uInt16 nId
, // zu invalidierende Slot-Id
913 sal_Bool bWithItem
, // StateCache clearen ?
914 sal_Bool bWithMsg
// SlotServer neu holen ?
918 DBG_ASSERT( !pImp
->bInUpdate
, "SfxBindings::Invalidate while in update" );
920 if ( pImp
->pSubBindings
)
921 pImp
->pSubBindings
->Invalidate( nId
, bWithItem
, bWithMsg
);
923 if ( SFX_APP()->IsDowning() )
926 SfxStateCache
* pCache
= GetStateCache(nId
);
930 pCache
->ClearCache();
931 pCache
->Invalidate(bWithMsg
);
933 if ( !pDispatcher
|| pImp
->bAllDirty
)
936 pImp
->nMsgPos
= Min(GetSlotPos(nId
), pImp
->nMsgPos
);
940 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
941 pImp
->aTimer
.Start();
946 //--------------------------------------------------------------------
948 sal_Bool
SfxBindings::IsBound( sal_uInt16 nSlotId
, sal_uInt16 nStartSearchAt
)
951 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
952 return GetStateCache(nSlotId
, &nStartSearchAt
) != 0;
955 //--------------------------------------------------------------------
957 sal_uInt16
SfxBindings::GetSlotPos( sal_uInt16 nId
, sal_uInt16 nStartSearchAt
)
960 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
961 DBG_PROFSTART(SfxBindingsMsgPos
);
963 // answer immediately if a function-seek comes repeated
964 if ( pImp
->nCachedFunc1
< pImp
->pCaches
->Count() &&
965 (*pImp
->pCaches
)[pImp
->nCachedFunc1
]->GetId() == nId
)
968 DBG_PROFSTOP(SfxBindingsMsgPos
);
969 return pImp
->nCachedFunc1
;
971 if ( pImp
->nCachedFunc2
< pImp
->pCaches
->Count() &&
972 (*pImp
->pCaches
)[pImp
->nCachedFunc2
]->GetId() == nId
)
977 sal_uInt16 nTemp
= pImp
->nCachedFunc1
;
978 pImp
->nCachedFunc1
= pImp
->nCachedFunc2
;
979 pImp
->nCachedFunc2
= nTemp
;
980 DBG_PROFSTOP(SfxBindingsMsgPos
);
981 return pImp
->nCachedFunc1
;
984 // binary search, if not found, seek to target-position
985 if ( pImp
->pCaches
->Count() <= nStartSearchAt
)
987 DBG_PROFSTOP(SfxBindingsMsgPos
);
990 if ( pImp
->pCaches
->Count() == (nStartSearchAt
+1) )
992 DBG_PROFSTOP(SfxBindingsMsgPos
);
993 return (*pImp
->pCaches
)[nStartSearchAt
]->GetId() >= nId
? 0 : 1;
995 sal_uInt16 nLow
= nStartSearchAt
;
997 sal_uInt16 nHigh
= 0;
998 sal_Bool bFound
= sal_False
;
999 nHigh
= pImp
->pCaches
->Count() - 1;
1000 while ( !bFound
&& nLow
<= nHigh
)
1002 nMid
= (nLow
+ nHigh
) >> 1;
1003 DBG_ASSERT( nMid
< pImp
->pCaches
->Count(), "bsearch ist buggy" );
1004 int nDiff
= (int) nId
- (int) ( ((*pImp
->pCaches
)[nMid
])->GetId() );
1010 else if ( nDiff
> 0 )
1018 sal_uInt16 nPos
= bFound
? nMid
: nLow
;
1019 DBG_ASSERT( nPos
<= pImp
->pCaches
->Count(), "" );
1020 DBG_ASSERT( nPos
== pImp
->pCaches
->Count() ||
1021 nId
<= (*pImp
->pCaches
)[nPos
]->GetId(), "" );
1022 DBG_ASSERT( nPos
== nStartSearchAt
||
1023 nId
> (*pImp
->pCaches
)[nPos
-1]->GetId(), "" );
1024 DBG_ASSERT( ( (nPos
+1) >= pImp
->pCaches
->Count() ) ||
1025 nId
< (*pImp
->pCaches
)[nPos
+1]->GetId(), "" );
1026 pImp
->nCachedFunc2
= pImp
->nCachedFunc1
;
1027 pImp
->nCachedFunc1
= nPos
;
1028 DBG_PROFSTOP(SfxBindingsMsgPos
);
1031 //--------------------------------------------------------------------
1032 void SfxBindings::RegisterInternal_Impl( SfxControllerItem
& rItem
)
1034 Register_Impl( rItem
, TRUE
);
1038 void SfxBindings::Register( SfxControllerItem
& rItem
)
1040 Register_Impl( rItem
, FALSE
);
1043 void SfxBindings::Register_Impl( SfxControllerItem
& rItem
, BOOL bInternal
)
1046 DBG_ASSERT( nRegLevel
> 0, "registration without EnterRegistrations" );
1047 DBG_ASSERT( !pImp
->bInNextJob
, "SfxBindings::Register while status-updating" );
1049 // insert new cache if it does not already exist
1050 sal_uInt16 nId
= rItem
.GetId();
1051 sal_uInt16 nPos
= GetSlotPos(nId
);
1052 if ( nPos
>= pImp
->pCaches
->Count() ||
1053 (*pImp
->pCaches
)[nPos
]->GetId() != nId
)
1055 SfxStateCache
* pCache
= new SfxStateCache(nId
);
1056 pImp
->pCaches
->Insert( nPos
, pCache
);
1057 DBG_ASSERT( nPos
== 0 ||
1058 (*pImp
->pCaches
)[nPos
]->GetId() >
1059 (*pImp
->pCaches
)[nPos
-1]->GetId(), "" );
1060 DBG_ASSERT( (nPos
== pImp
->pCaches
->Count()-1) ||
1061 (*pImp
->pCaches
)[nPos
]->GetId() <
1062 (*pImp
->pCaches
)[nPos
+1]->GetId(), "" );
1063 pImp
->bMsgDirty
= sal_True
;
1066 // enqueue the new binding
1069 (*pImp
->pCaches
)[nPos
]->SetInternalController( &rItem
);
1073 SfxControllerItem
*pOldItem
= (*pImp
->pCaches
)[nPos
]->ChangeItemLink(&rItem
);
1074 rItem
.ChangeItemLink(pOldItem
);
1078 //--------------------------------------------------------------------
1080 void SfxBindings::Release( SfxControllerItem
& rItem
)
1083 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1084 //! DBG_ASSERT( nRegLevel > 0, "release without EnterRegistrations" );
1085 DBG_ASSERT( !pImp
->bInNextJob
, "SfxBindings::Release while status-updating" );
1086 ENTERREGISTRATIONS();
1088 // find the bound function
1089 sal_uInt16 nId
= rItem
.GetId();
1090 sal_uInt16 nPos
= GetSlotPos(nId
);
1091 SfxStateCache
* pCache
= (*pImp
->pCaches
)[nPos
];
1092 if ( pCache
->GetId() == nId
)
1094 if ( pCache
->GetInternalController() == &rItem
)
1096 pCache
->ReleaseInternalController();
1100 // is this the first binding in the list?
1101 SfxControllerItem
* pItem
= pCache
->GetItemLink();
1102 if ( pItem
== &rItem
)
1103 pCache
->ChangeItemLink( rItem
.GetItemLink() );
1106 // search the binding in the list
1107 while ( pItem
&& pItem
->GetItemLink() != &rItem
)
1108 pItem
= pItem
->GetItemLink();
1110 // unlink it if it was found
1112 pItem
->ChangeItemLink( rItem
.GetItemLink() );
1116 // was this the last controller?
1117 if ( pCache
->GetItemLink() == 0 && !pCache
->GetInternalController() )
1120 // remove the BoundFunc
1121 delete (*pImp
->pCaches
)[nPos
];
1122 pImp
->pCaches
->Remove(nPos
, 1);
1124 if ( SfxMacroConfig::IsMacroSlot( nId
) )
1126 delete (*pImp
->pCaches
)[nPos
];
1127 pImp
->pCaches
->Remove(nPos
, 1);
1130 pImp
->bCtrlReleased
= sal_True
;
1134 LEAVEREGISTRATIONS();
1137 //--------------------------------------------------------------------
1138 const SfxPoolItem
* SfxBindings::ExecuteSynchron( sal_uInt16 nId
, const SfxPoolItem
** ppItems
, sal_uInt16 nModi
,
1139 const SfxPoolItem
**ppInternalArgs
)
1142 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1144 if( !nId
|| !pDispatcher
)
1147 return Execute_Impl( nId
, ppItems
, nModi
, SFX_CALLMODE_SYNCHRON
, ppInternalArgs
);
1150 sal_Bool
SfxBindings::Execute( sal_uInt16 nId
, const SfxPoolItem
** ppItems
, sal_uInt16 nModi
, SfxCallMode nCallMode
,
1151 const SfxPoolItem
**ppInternalArgs
)
1154 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1156 if( !nId
|| !pDispatcher
)
1159 const SfxPoolItem
* pRet
= Execute_Impl( nId
, ppItems
, nModi
, nCallMode
, ppInternalArgs
);
1160 return ( pRet
!= 0 );
1163 void SfxBindings::ExecuteGlobal_Impl( USHORT nId
)
1165 if( nId
&& pDispatcher
)
1166 Execute_Impl( nId
, NULL
, 0, SFX_CALLMODE_ASYNCHRON
, NULL
, TRUE
);
1169 const SfxPoolItem
* SfxBindings::Execute_Impl( sal_uInt16 nId
, const SfxPoolItem
** ppItems
, sal_uInt16 nModi
, SfxCallMode nCallMode
,
1170 const SfxPoolItem
**ppInternalArgs
, BOOL bGlobalOnly
)
1172 SfxStateCache
*pCache
= GetStateCache( nId
);
1175 SfxBindings
*pBind
= pImp
->pSubBindings
;
1178 if ( pBind
->GetStateCache( nId
) )
1179 return pBind
->Execute_Impl( nId
, ppItems
, nModi
, nCallMode
, ppInternalArgs
, bGlobalOnly
);
1180 pBind
= pBind
->pImp
->pSubBindings
;
1184 SfxDispatcher
&rDispatcher
= *pDispatcher
;
1185 rDispatcher
.Flush();
1186 rDispatcher
.GetFrame(); // -Wall is this required???
1188 // get SlotServer (Slot+ShellLevel) and Shell from cache
1189 sal_Bool bDeleteCache
= sal_False
;
1192 // Execution of non cached slots (Accelerators don't use Controllers)
1193 // slot is uncached, use SlotCache to handle external dispatch providers
1194 pCache
= new SfxStateCache( nId
);
1195 pCache
->GetSlotServer( rDispatcher
, pImp
->xProv
);
1196 bDeleteCache
= sal_True
;
1199 if ( pCache
&& pCache
->GetDispatch().is() )
1201 DBG_ASSERT( !ppInternalArgs
, "Internal args get lost when dispatched!" );
1203 SfxItemPool
&rPool
= GetDispatcher()->GetFrame()->GetObjectShell()->GetPool();
1204 SfxRequest
aReq( nId
, nCallMode
, rPool
);
1205 aReq
.SetModifier( nModi
);
1208 aReq
.AppendItem( **ppItems
++ );
1210 // cache binds to an external dispatch provider
1211 pCache
->Dispatch( aReq
.GetArgs(), nCallMode
== SFX_CALLMODE_SYNCHRON
);
1214 SfxPoolItem
*pVoid
= new SfxVoidItem( nId
);
1215 DeleteItemOnIdle( pVoid
);
1219 // slot is handled internally by SfxDispatcher
1220 if ( pImp
->bMsgDirty
)
1221 UpdateSlotServer_Impl();
1224 const SfxSlot
*pSlot
=0;
1226 // if slot was uncached, we should have created a cache in this method!
1227 DBG_ASSERT( pCache
, "This code needs a cache!");
1228 const SfxSlotServer
* pServer
= pCache
? pCache
->GetSlotServer( rDispatcher
, pImp
->xProv
) : 0;
1235 pShell
= rDispatcher
.GetShell( pServer
->GetShellLevel() );
1236 pSlot
= pServer
->GetSlot();
1240 if ( !pShell
->ISA(SfxModule
) && !pShell
->ISA(SfxApplication
) && !pShell
->ISA(SfxViewFrame
) )
1243 SfxItemPool
&rPool
= pShell
->GetPool();
1244 SfxRequest
aReq( nId
, nCallMode
, rPool
);
1245 aReq
.SetModifier( nModi
);
1248 aReq
.AppendItem( **ppItems
++ );
1249 if ( ppInternalArgs
)
1251 SfxAllItemSet
aSet( rPool
);
1252 for ( const SfxPoolItem
**pArg
= ppInternalArgs
; *pArg
; ++pArg
)
1254 aReq
.SetInternalArgs_Impl( aSet
);
1257 Execute_Impl( aReq
, pSlot
, pShell
);
1259 const SfxPoolItem
* pRet
= aReq
.GetReturnValue();
1262 SfxPoolItem
*pVoid
= new SfxVoidItem( nId
);
1263 DeleteItemOnIdle( pVoid
);
1273 void SfxBindings::Execute_Impl( SfxRequest
& aReq
, const SfxSlot
* pSlot
, SfxShell
* pShell
)
1275 SfxItemPool
&rPool
= pShell
->GetPool();
1277 if ( SFX_KIND_ENUM
== pSlot
->GetKind() )
1279 // bei Enum-Slots muss der Master mit dem Wert des Enums executet werden
1280 const SfxSlot
*pRealSlot
= pShell
->GetInterface()->GetRealSlot(pSlot
);
1281 const sal_uInt16 nSlotId
= pRealSlot
->GetSlotId();
1282 aReq
.SetSlot( nSlotId
);
1283 aReq
.AppendItem( SfxAllEnumItem( rPool
.GetWhich(nSlotId
), pSlot
->GetValue() ) );
1284 pDispatcher
->_Execute( *pShell
, *pRealSlot
, aReq
, aReq
.GetCallMode() | SFX_CALLMODE_RECORD
);
1286 else if ( SFX_KIND_ATTR
== pSlot
->GetKind() )
1288 // bei Attr-Slots muss der Which-Wert gemapped werden
1289 const sal_uInt16 nSlotId
= pSlot
->GetSlotId();
1290 aReq
.SetSlot( nSlotId
);
1291 if ( pSlot
->IsMode(SFX_SLOT_TOGGLE
) )
1293 // an togglebare-Attribs (Bools) wird der Wert angeheangt
1294 sal_uInt16 nWhich
= pSlot
->GetWhich(rPool
);
1295 SfxItemSet
aSet(rPool
, nWhich
, nWhich
, 0);
1296 SfxStateFunc aFunc
= pSlot
->GetStateFnc();
1297 pShell
->CallState( aFunc
, aSet
);
1298 const SfxPoolItem
*pOldItem
;
1299 SfxItemState eState
= aSet
.GetItemState(nWhich
, sal_True
, &pOldItem
);
1300 if ( eState
== SFX_ITEM_DISABLED
)
1303 if ( SFX_ITEM_AVAILABLE
== eState
&& SfxItemPool::IsWhich(nWhich
) )
1304 pOldItem
= &aSet
.Get(nWhich
);
1306 if ( SFX_ITEM_SET
== eState
||
1307 ( SFX_ITEM_AVAILABLE
== eState
&&
1308 SfxItemPool::IsWhich(nWhich
) &&
1311 if ( pOldItem
->ISA(SfxBoolItem
) )
1313 // wir koennen Bools toggeln
1314 sal_Bool bOldValue
= ((const SfxBoolItem
*)pOldItem
)->GetValue();
1315 SfxBoolItem
*pNewItem
= (SfxBoolItem
*) (pOldItem
->Clone());
1316 pNewItem
->SetValue( !bOldValue
);
1317 aReq
.AppendItem( *pNewItem
);
1320 else if ( pOldItem
->ISA(SfxEnumItemInterface
) &&
1321 ((SfxEnumItemInterface
*)pOldItem
)->HasBoolValue())
1323 // und Enums mit Bool-Interface
1324 SfxEnumItemInterface
*pNewItem
=
1325 (SfxEnumItemInterface
*) (pOldItem
->Clone());
1326 pNewItem
->SetBoolValue(!((SfxEnumItemInterface
*)pOldItem
)->GetBoolValue());
1327 aReq
.AppendItem( *pNewItem
);
1331 DBG_ERROR( "Toggle only for Enums and Bools allowed" );
1334 else if ( SFX_ITEM_DONTCARE
== eState
)
1336 // ein Status-Item per Factory erzeugen
1337 SfxPoolItem
*pNewItem
= pSlot
->GetType()->CreateItem();
1338 DBG_ASSERT( pNewItem
, "Toggle an Slot ohne ItemFactory" );
1339 pNewItem
->SetWhich( nWhich
);
1341 if ( pNewItem
->ISA(SfxBoolItem
) )
1343 // wir koennen Bools toggeln
1344 ((SfxBoolItem
*)pNewItem
)->SetValue( sal_True
);
1345 aReq
.AppendItem( *pNewItem
);
1347 else if ( pNewItem
->ISA(SfxEnumItemInterface
) &&
1348 ((SfxEnumItemInterface
*)pNewItem
)->HasBoolValue())
1350 // und Enums mit Bool-Interface
1351 ((SfxEnumItemInterface
*)pNewItem
)->SetBoolValue(sal_True
);
1352 aReq
.AppendItem( *pNewItem
);
1355 DBG_ERROR( "Toggle only for Enums and Bools allowed" );
1360 DBG_ERROR( "suspicious Toggle-Slot" );
1364 pDispatcher
->_Execute( *pShell
, *pSlot
, aReq
, aReq
.GetCallMode() | SFX_CALLMODE_RECORD
);
1367 pDispatcher
->_Execute( *pShell
, *pSlot
, aReq
, aReq
.GetCallMode() | SFX_CALLMODE_RECORD
);
1370 //--------------------------------------------------------------------
1372 void SfxBindings::UpdateSlotServer_Impl()
1374 DBG_PROFSTART(SfxBindingsUpdateServers
);
1376 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1379 pDispatcher
->Flush();
1380 // pDispatcher->Update_Impl();
1382 if ( pImp
->bAllMsgDirty
)
1386 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> xFrame
1387 ( pDispatcher
->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY
);
1388 //if ( xFrame.is() )
1389 // xFrame->contextChanged();
1390 pImp
->bContextChanged
= FALSE
;
1393 pImp
->bContextChanged
= TRUE
;
1396 const sal_uInt16 nCount
= pImp
->pCaches
->Count();
1397 for(sal_uInt16 i
= 0; i
< nCount
; ++i
)
1399 SfxStateCache
*pCache
= pImp
->pCaches
->GetObject(i
);
1400 pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1402 pImp
->bMsgDirty
= pImp
->bAllMsgDirty
= sal_False
;
1404 Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED
) );
1406 DBG_PROFSTOP(SfxBindingsUpdateServers
);
1409 //--------------------------------------------------------------------
1412 int __cdecl
CmpUS_Impl(const void *p1
, const void *p2
)
1414 int CmpUS_Impl(const void *p1
, const void *p2
)
1419 Interne Vergleichsfunktion fuer qsort.
1423 return *(sal_uInt16
*)p1
- *(sal_uInt16
*)p2
;
1426 //--------------------------------------------------------------------
1428 SfxItemSet
* SfxBindings::CreateSet_Impl
1430 SfxStateCache
*& pCache
, // in: Status-Cache von nId
1431 const SfxSlot
*& pRealSlot
, // out: RealSlot zu nId
1432 const SfxSlotServer
** pMsgServer
, // out: Slot-Server zu nId
1433 SfxFoundCacheArr_Impl
& rFound
// out: Liste der Caches der Siblings
1437 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1439 DBG_ASSERT( !pImp
->bMsgDirty
, "CreateSet_Impl mit dirty MessageServer" );
1441 const SfxSlotServer
* pMsgSvr
= pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1442 if(!pMsgSvr
|| !pDispatcher
)
1445 DBG_PROFSTART(SfxBindingsCreateSet
);
1447 *pMsgServer
= pMsgSvr
;
1449 sal_uInt16 nShellLevel
= pMsgSvr
->GetShellLevel();
1450 SfxShell
*pShell
= pDispatcher
->GetShell( nShellLevel
);
1451 if ( !pShell
) // seltener GPF beim Browsen durch Update aus Inet-Notify
1454 SfxItemPool
&rPool
= pShell
->GetPool();
1456 // hole die Status-Methode, von der pCache bedient wird
1457 SfxStateFunc pFnc
= 0;
1458 const SfxInterface
*pInterface
= pShell
->GetInterface();
1459 if ( SFX_KIND_ENUM
== pMsgSvr
->GetSlot()->GetKind() )
1461 pRealSlot
= pInterface
->GetRealSlot(pMsgSvr
->GetSlot());
1462 pCache
= GetStateCache( pRealSlot
->GetSlotId() );
1463 // DBG_ASSERT( pCache, "Kein Slotcache fuer den Masterslot gefunden!" );
1466 pRealSlot
= pMsgSvr
->GetSlot();
1469 // Achtung: pCache darf auch NULL sein !!!
1472 pFnc
= pRealSlot
->GetStateFnc();
1474 // der RealSlot ist immer drin
1475 const SfxFoundCache_Impl
*pFound
= new SfxFoundCache_Impl(
1476 pRealSlot
->GetSlotId(), pRealSlot
->GetWhich(rPool
), pRealSlot
, pCache
);
1477 rFound
.Insert( pFound
);
1479 USHORT nSlot
= pRealSlot
->GetSlotId();
1480 if ( !SfxMacroConfig::IsMacroSlot( nSlot
) && !(nSlot
>= SID_VERB_START
&& nSlot
<= SID_VERB_END
) )
1482 pInterface
= pInterface
->GetRealInterfaceForSlot( pRealSlot
);
1483 DBG_ASSERT (pInterface
,"Slot in angegebener Shell nicht gefunden!");
1486 // Durchsuche die Bindings nach den von derselben Funktion bedienten Slots.
1487 // Daf"ur kommen nur Slots in Frage, die es im gefundenen Interface gibt.
1489 // Die Position des Statecaches im StateCache-Array
1490 sal_uInt16 nCachePos
= pImp
->nMsgPos
;
1491 const SfxSlot
*pSibling
= pRealSlot
->GetNextSlot();
1493 // Die Slots eines Interfaces sind im Kreis verkettet
1494 while ( pSibling
> pRealSlot
)
1496 SfxStateFunc pSiblingFnc
=0;
1497 SfxStateCache
*pSiblingCache
=
1498 GetStateCache( pSibling
->GetSlotId(), &nCachePos
);
1500 // Ist der Slot "uberhaupt gecached ?
1501 if ( pSiblingCache
)
1503 const SfxSlotServer
*pServ
= pSiblingCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1504 if ( pServ
&& pServ
->GetShellLevel() == nShellLevel
)
1505 pSiblingFnc
= pServ
->GetSlot()->GetStateFnc();
1508 // Mu\s der Slot "uberhaupt upgedatet werden ?
1509 FASTBOOL bInsert
= pSiblingCache
&& pSiblingCache
->IsControllerDirty();
1511 // Bugfix #26161#: Es reicht nicht, nach der selben Shell zu fragen !!
1512 FASTBOOL bSameMethod
= pSiblingCache
&& pFnc
== pSiblingFnc
;
1514 // Wenn der Slot ein nicht-dirty MasterSlot ist, dann ist vielleicht
1515 // einer seiner Slaves dirty ? Dann wird der Masterslot doch eingef"ugt.
1516 if ( !bInsert
&& bSameMethod
&& pSibling
->GetLinkedSlot() )
1518 // auch Slave-Slots auf Binding pru"fen
1519 const SfxSlot
* pFirstSlave
= pSibling
->GetLinkedSlot();
1520 for ( const SfxSlot
*pSlaveSlot
= pFirstSlave
;
1522 pSlaveSlot
= pSlaveSlot
->GetNextSlot())
1524 // Die Slaves zeigen auf ihren Master
1525 DBG_ASSERT(pSlaveSlot
->GetLinkedSlot() == pSibling
,
1526 "Falsche Master/Slave-Beziehung!");
1528 sal_uInt16 nCurMsgPos
= pImp
->nMsgPos
;
1529 const SfxStateCache
*pSlaveCache
=
1530 GetStateCache( pSlaveSlot
->GetSlotId(), &nCurMsgPos
);
1532 // Ist der Slave-Slot gecached und dirty ?
1533 bInsert
= pSlaveCache
&& pSlaveCache
->IsControllerDirty();
1535 // Slaves sind untereinander im Kreis verkettet
1536 if (pSlaveSlot
->GetNextSlot() == pFirstSlave
)
1541 if ( bInsert
&& bSameMethod
)
1543 const SfxFoundCache_Impl
*pFoundCache
= new SfxFoundCache_Impl(
1544 pSibling
->GetSlotId(), pSibling
->GetWhich(rPool
),
1545 pSibling
, pSiblingCache
);
1547 rFound
.Insert( pFoundCache
);
1550 pSibling
= pSibling
->GetNextSlot();
1553 // aus den Ranges ein Set erzeugen
1554 sal_uInt16
*pRanges
= new sal_uInt16
[rFound
.Count() * 2 + 1];
1557 while ( i
< rFound
.Count() )
1559 pRanges
[j
++] = rFound
[i
]->nWhichId
;
1560 // aufeinanderfolgende Zahlen
1561 for ( ; i
< rFound
.Count()-1; ++i
)
1562 if ( rFound
[i
]->nWhichId
+1 != rFound
[i
+1]->nWhichId
)
1564 pRanges
[j
++] = rFound
[i
++]->nWhichId
;
1566 pRanges
[j
] = 0; // terminierende NULL
1567 SfxItemSet
*pSet
= new SfxItemSet(rPool
, pRanges
);
1569 DBG_PROFSTOP(SfxBindingsCreateSet
);
1573 //--------------------------------------------------------------------
1575 void SfxBindings::UpdateControllers_Impl
1577 const SfxInterface
* pIF
, // das diese Id momentan bedienende Interface
1578 const SfxFoundCache_Impl
* pFound
, // Cache, Slot, Which etc.
1579 const SfxPoolItem
* pItem
, // item to send to controller
1580 SfxItemState eState
// state of item
1583 DBG_ASSERT( !pFound
->pSlot
|| SFX_KIND_ENUM
!= pFound
->pSlot
->GetKind(),
1584 "direct update of enum slot isn't allowed" );
1585 DBG_PROFSTART(SfxBindingsUpdateCtrl1
);
1587 SfxStateCache
* pCache
= pFound
->pCache
;
1588 const SfxSlot
* pSlot
= pFound
->pSlot
;
1589 DBG_ASSERT( !pCache
|| !pSlot
|| pCache
->GetId() == pSlot
->GetSlotId(), "SID mismatch" );
1591 // insofern gebunden, die Controller f"uer den Slot selbst updaten
1592 if ( pCache
&& pCache
->IsControllerDirty() )
1594 if ( SFX_ITEM_DONTCARE
== eState
)
1597 pCache
->SetState( SFX_ITEM_DONTCARE
, (SfxPoolItem
*)-1 );
1599 else if ( SFX_ITEM_DEFAULT
== eState
&&
1600 pFound
->nWhichId
> SFX_WHICH_MAX
)
1602 // kein Status oder Default aber ohne Pool
1603 SfxVoidItem
aVoid(0);
1604 pCache
->SetState( SFX_ITEM_UNKNOWN
, &aVoid
);
1606 else if ( SFX_ITEM_DISABLED
== eState
)
1607 pCache
->SetState(SFX_ITEM_DISABLED
, 0);
1609 pCache
->SetState(SFX_ITEM_AVAILABLE
, pItem
);
1612 DBG_PROFSTOP(SfxBindingsUpdateCtrl1
);
1614 // insofern vorhanden und gebunden, die Controller f"uer Slave-Slots
1615 // (Enum-Werte) des Slots updaten
1616 DBG_PROFSTART(SfxBindingsUpdateCtrl2
);
1617 DBG_ASSERT( !pSlot
|| 0 == pSlot
->GetLinkedSlot() || !pItem
||
1618 pItem
->ISA(SfxEnumItemInterface
),
1619 "master slot with non-enum-type found" );
1620 const SfxSlot
*pFirstSlave
= pSlot
? pSlot
->GetLinkedSlot() : 0;
1621 if ( pIF
&& pFirstSlave
)
1623 // Items auf EnumItem casten
1624 const SfxEnumItemInterface
*pEnumItem
=
1625 PTR_CAST(SfxEnumItemInterface
,pItem
);
1626 if ( eState
== SFX_ITEM_AVAILABLE
&& !pEnumItem
)
1627 eState
= SFX_ITEM_DONTCARE
;
1629 eState
= SfxControllerItem::GetItemState( pEnumItem
);
1631 // "uber alle Slaves-Slots iterieren
1632 for ( const SfxSlot
*pSlave
= pFirstSlave
; pSlave
; pSlave
= pSlave
->GetNextSlot() )
1634 DBG_ASSERT(pSlave
, "Falsche SlaveSlot-Verkettung!");
1635 DBG_ASSERT(SFX_KIND_ENUM
== pSlave
->GetKind(),"non enum slaves aren't allowed");
1636 DBG_ASSERT(pSlave
->GetMasterSlotId() == pSlot
->GetSlotId(),"falscher MasterSlot!");
1638 // ist die Funktion gebunden?
1639 SfxStateCache
*pEnumCache
= GetStateCache( pSlave
->GetSlotId() );
1642 pEnumCache
->Invalidate(sal_False
);
1644 HACK(CONTROL
/SELECT Kram
)
1645 if ( eState
== SFX_ITEM_DONTCARE
&& pFound
->nWhichId
== 10144 )
1647 SfxVoidItem
aVoid(0);
1648 pEnumCache
->SetState( SFX_ITEM_UNKNOWN
, &aVoid
);
1650 if (pSlave
->GetNextSlot() == pFirstSlave
)
1656 if ( SFX_ITEM_DISABLED
== eState
|| !pEnumItem
->IsEnabled( pSlave
->GetSlotId()) )
1659 pEnumCache
->SetState(SFX_ITEM_DISABLED
, 0);
1661 else if ( SFX_ITEM_AVAILABLE
== eState
)
1663 // enum-Wert ermitteln
1664 sal_uInt16 nValue
= pEnumItem
->GetEnumValue();
1665 SfxBoolItem
aBool( pFound
->nWhichId
, pSlave
->GetValue() == nValue
);
1666 pEnumCache
->SetState(SFX_ITEM_AVAILABLE
, &aBool
);
1671 pEnumCache
->SetState( SFX_ITEM_DONTCARE
, (SfxPoolItem
*)-1 );
1675 if (pSlave
->GetNextSlot() == pFirstSlave
)
1680 DBG_PROFSTOP(SfxBindingsUpdateCtrl2
);
1684 //--------------------------------------------------------------------
1686 IMPL_LINK( SfxBindings
, NextJob_Impl
, Timer
*, pTimer
)
1689 // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT or another MS library
1690 // try to get them here
1694 const unsigned MAX_INPUT_DELAY
= 200;
1697 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
1699 DBG_PROFSTART(SfxBindingsNextJob_Impl0
);
1701 if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY
&& pTimer
)
1703 pImp
->aTimer
.SetTimeout(TIMEOUT_UPDATING
);
1707 SfxApplication
*pSfxApp
= SFX_APP();
1710 pDispatcher
->Update_Impl();
1712 // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
1713 SfxViewFrame
* pFrame
= pDispatcher
->GetFrame();
1714 if ( (pFrame
&& pFrame
->GetObjectShell()->IsInModalMode()) || pSfxApp
->IsDowning() || !pImp
->pCaches
->Count() )
1716 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1719 if ( !pDispatcher
|| !pDispatcher
->IsFlushed() )
1721 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1725 // gfs. alle Server aktualisieren / geschieht in eigener Zeitscheibe
1726 if ( pImp
->bMsgDirty
)
1728 UpdateSlotServer_Impl();
1729 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1733 DBG_PROFSTOP(SfxBindingsNextJob_Impl0
);
1734 DBG_PROFSTART(SfxBindingsNextJob_Impl
);
1735 pImp
->bAllDirty
= sal_False
;
1736 pImp
->aTimer
.SetTimeout(TIMEOUT_UPDATING
);
1738 // at least 10 loops and further if more jobs are available but no input
1739 FASTBOOL bPreEmptive
= pTimer
&& !pSfxApp
->Get_Impl()->nInReschedule
;
1740 sal_uInt16 nLoops
= 10;
1741 pImp
->bInNextJob
= sal_True
;
1742 const sal_uInt16 nCount
= pImp
->pCaches
->Count();
1743 while ( pImp
->nMsgPos
< nCount
)
1745 // iterate through the bound functions
1746 sal_Bool bJobDone
= sal_False
;
1749 SfxStateCache
* pCache
= (*pImp
->pCaches
)[pImp
->nMsgPos
];
1750 DBG_ASSERT( pCache
, "invalid SfxStateCache-position in job queue" );
1751 sal_Bool bWasDirty
= pCache
->IsControllerDirty();
1755 sal_Bool bSkip = sal_False;
1756 if ( pImp->bFirstRound )
1758 // Falls beim Update eine Shell vorgezogen werden soll,
1759 // kommt in einer ersten Update-Runde nur diese dran
1760 const SfxSlotServer *pMsgServer =
1761 pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1763 pMsgServer->GetShellLevel() != pImp->nFirstShell )
1770 Update_Impl( pCache
);
1771 DBG_ASSERT( nCount
== pImp
->pCaches
->Count(),
1772 "Reschedule in StateChanged => buff" );
1776 // skip to next function binding
1779 // keep job if it is not completed, but any input is available
1780 bJobDone
= pImp
->nMsgPos
>= nCount
;
1781 if ( bJobDone
&& pImp
->bFirstRound
)
1783 // Update der bevorzugten Shell ist gelaufen, nun d"urfen
1785 bJobDone
= sal_False
;
1786 pImp
->bFirstRound
= sal_False
;
1790 if ( bWasDirty
&& !bJobDone
&& bPreEmptive
&& (--nLoops
== 0) )
1792 DBG_PROFSTOP(SfxBindingsNextJob_Impl
);
1793 pImp
->bInNextJob
= sal_False
;
1801 // check for volatile slots
1802 bool bVolatileSlotsPresent
= false;
1803 for ( sal_uInt16 n
= 0; n
< nCount
; ++n
)
1805 SfxStateCache
* pCache
= (*pImp
->pCaches
)[n
];
1806 const SfxSlotServer
*pSlotServer
= pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
);
1807 if ( pSlotServer
&& pSlotServer
->GetSlot()->IsMode(SFX_SLOT_VOLATILE
) )
1809 pCache
->Invalidate(sal_False
);
1810 bVolatileSlotsPresent
= true;
1814 if (bVolatileSlotsPresent
)
1815 pImp
->aTimer
.SetTimeout(TIMEOUT_IDLE
);
1817 pImp
->aTimer
.Stop();
1819 // Update-Runde ist beendet
1820 pImp
->bInNextJob
= sal_False
;
1821 Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE
));
1822 DBG_PROFSTOP(SfxBindingsNextJob_Impl
);
1828 DBG_ERROR("C++ exception caught!");
1829 pImp
->bInNextJob
= sal_False
;
1836 //--------------------------------------------------------------------
1838 sal_uInt16
SfxBindings::EnterRegistrations(const char *pFile
, int nLine
)
1845 aMsg
.Fill( Min(nRegLevel
, sal_uInt16(8) ) );
1847 aMsg
+= ByteString::CreateFromInt32((long)this);
1848 aMsg
+= " Level = ";
1849 aMsg
+= ByteString::CreateFromInt32(nRegLevel
);
1850 aMsg
+= " SfxBindings::EnterRegistrations ";
1855 aMsg
+= ByteString::CreateFromInt32(nLine
);
1857 // FILE* pLog = fopen( "c:\\bindings.log", "a+w" );
1858 // fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog );
1860 DbgTrace( aMsg
.GetBuffer() );
1863 // Wenn Bindings gelockt werden, auch SubBindings locken
1864 if ( pImp
->pSubBindings
)
1866 pImp
->pSubBindings
->ENTERREGISTRATIONS();
1868 // Dieses EnterRegistrations ist f"ur die SubBindings kein "echtes"
1869 pImp
->pSubBindings
->pImp
->nOwnRegLevel
--;
1871 // Bindings synchronisieren
1872 pImp
->pSubBindings
->nRegLevel
= nRegLevel
+ pImp
->pSubBindings
->pImp
->nOwnRegLevel
+ 1;
1875 pImp
->nOwnRegLevel
++;
1877 // check if this is the outer most level
1878 if ( ++nRegLevel
== 1 )
1880 // stop background-processing
1881 pImp
->aTimer
.Stop();
1884 pImp
->nCachedFunc1
= 0;
1885 pImp
->nCachedFunc2
= 0;
1887 // merken, ob ganze Caches verschwunden sind
1888 pImp
->bCtrlReleased
= sal_False
;
1893 //--------------------------------------------------------------------
1895 void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel
, const char *pFile
, int nLine
)
1897 (void)nLevel
; // unused variable
1901 DBG_ASSERT( nRegLevel
, "Leave without Enter" );
1902 DBG_ASSERT( nLevel
== USHRT_MAX
|| nLevel
== nRegLevel
, "wrong Leave" );
1904 // Nur wenn die SubBindings noch von den SuperBindings gelockt sind, diesen Lock entfernen
1905 // ( d.h. wenn es mehr Locks als "echte" Locks dort gibt )
1906 if ( pImp
->pSubBindings
&& pImp
->pSubBindings
->nRegLevel
> pImp
->pSubBindings
->pImp
->nOwnRegLevel
)
1908 // Bindings synchronisieren
1909 pImp
->pSubBindings
->nRegLevel
= nRegLevel
+ pImp
->pSubBindings
->pImp
->nOwnRegLevel
;
1911 // Dieses LeaveRegistrations ist f"ur die SubBindings kein "echtes"
1912 pImp
->pSubBindings
->pImp
->nOwnRegLevel
++;
1913 pImp
->pSubBindings
->LEAVEREGISTRATIONS();
1916 pImp
->nOwnRegLevel
--;
1918 // check if this is the outer most level
1919 if ( --nRegLevel
== 0 && !SFX_APP()->IsDowning() )
1921 if ( pImp
->bContextChanged
)
1923 pImp
->bContextChanged
= FALSE
;
1925 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
1926 ( pDispatcher->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY );
1928 xFrame->contextChanged();*/
1932 SfxViewFrame
* pFrame
= pDispatcher
->GetFrame();
1934 // ggf unbenutzte Caches entfernen bzw. PlugInInfo aufbereiten
1935 if ( pImp
->bCtrlReleased
)
1937 for ( sal_uInt16 nCache
= pImp
->pCaches
->Count(); nCache
> 0; --nCache
)
1939 // Cache via ::com::sun::star::sdbcx::Index besorgen
1940 SfxStateCache
*pCache
= pImp
->pCaches
->GetObject(nCache
-1);
1942 // kein Controller mehr interessiert
1943 if ( pCache
->GetItemLink() == 0 && !pCache
->GetInternalController() )
1945 // Cache entfernen. Safety: first remove and then delete
1946 SfxStateCache
* pSfxStateCache
= (*pImp
->pCaches
)[nCache
-1];
1947 pImp
->pCaches
->Remove(nCache
-1, 1);
1948 delete pSfxStateCache
;
1952 // neue Controller mit den alten Items benachrichtigen
1953 //!pCache->SetCachedState();
1958 // restart background-processing
1960 if ( !pFrame
|| !pFrame
->GetObjectShell() )
1962 if ( pImp
->pCaches
&& pImp
->pCaches
->Count() )
1964 pImp
->aTimer
.Stop();
1965 pImp
->aTimer
.SetTimeout(TIMEOUT_FIRST
);
1966 pImp
->aTimer
.Start();
1967 // pImp->bFirstRound = sal_True;
1973 aMsg
.Fill( Min(nRegLevel
, sal_uInt16(8)) );
1975 aMsg
+= ByteString::CreateFromInt32((long)this);
1976 aMsg
+= " Level = ";
1977 aMsg
+= ByteString::CreateFromInt32(nRegLevel
);
1978 aMsg
+= " SfxBindings::LeaveRegistrations ";
1983 aMsg
+= ByteString::CreateFromInt32(nLine
);
1985 // FILE* pLog = fopen( "c:\\bindings.log", "a+w" );
1986 // fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog );
1988 DbgTrace( aMsg
.GetBuffer() );
1992 //--------------------------------------------------------------------
1994 const SfxSlot
* SfxBindings::GetSlot(sal_uInt16 nSlotId
)
1997 DBG_ASSERT( pImp
->pCaches
!= 0, "SfxBindings not initialized" );
2000 pDispatcher
->Flush();
2001 if ( pImp
->bMsgDirty
)
2002 UpdateSlotServer_Impl();
2004 // get the cache for the specified function; return if not bound
2005 SfxStateCache
* pCache
= GetStateCache(nSlotId
);
2006 return pCache
&& pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
)?
2007 pCache
->GetSlotServer(*pDispatcher
, pImp
->xProv
)->GetSlot(): 0;
2010 //--------------------------------------------------------------------
2012 void SfxBindings::SetDispatcher( SfxDispatcher
*pDisp
)
2014 SfxDispatcher
*pOldDispat
= pDispatcher
;
2015 if ( pDisp
!= pDispatcher
)
2019 SfxBindings
* pBind
= pOldDispat
->GetBindings();
2022 if ( pBind
->pImp
->pSubBindings
== this && pBind
->pDispatcher
!= pDisp
)
2023 pBind
->SetSubBindings_Impl( NULL
);
2024 pBind
= pBind
->pImp
->pSubBindings
;
2028 pDispatcher
= pDisp
;
2030 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> xProv
;
2032 xProv
= ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
>
2033 ( pDisp
->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY
);
2035 SetDispatchProvider_Impl( xProv
);
2036 InvalidateAll( sal_True
);
2037 InvalidateUnoControllers_Impl();
2039 if ( pDispatcher
&& !pOldDispat
)
2041 if ( pImp
->pSubBindings
&& pImp
->pSubBindings
->pDispatcher
!= pOldDispat
)
2043 DBG_ERROR( "SubBindings vor Aktivieren schon gesetzt!" );
2044 pImp
->pSubBindings
->ENTERREGISTRATIONS();
2046 LEAVEREGISTRATIONS();
2048 else if( !pDispatcher
)
2050 ENTERREGISTRATIONS();
2051 if ( pImp
->pSubBindings
&& pImp
->pSubBindings
->pDispatcher
!= pOldDispat
)
2053 DBG_ERROR( "SubBindings im Deaktivieren immer noch gesetzt!" );
2054 pImp
->pSubBindings
->LEAVEREGISTRATIONS();
2058 Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED
) );
2062 SfxBindings
* pBind
= pDisp
->GetBindings();
2063 while ( pBind
&& pBind
!= this )
2065 if ( !pBind
->pImp
->pSubBindings
)
2067 pBind
->SetSubBindings_Impl( this );
2071 pBind
= pBind
->pImp
->pSubBindings
;
2077 //--------------------------------------------------------------------
2079 void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId
)
2081 GetStateCache(nSlotId
)->ClearCache();
2084 //--------------------------------------------------------------------
2085 void SfxBindings::StartUpdate_Impl( sal_Bool bComplete
)
2087 if ( pImp
->pSubBindings
)
2088 pImp
->pSubBindings
->StartUpdate_Impl( bComplete
);
2091 // Update darf unterbrochen werden
2092 NextJob_Impl(&pImp
->aTimer
);
2094 // alle Slots am St"uck updaten
2098 //-------------------------------------------------------------------------
2100 SfxItemState
SfxBindings::QueryState( sal_uInt16 nSlot
, SfxPoolItem
* &rpState
)
2102 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
2103 SfxStateCache
*pCache
= GetStateCache( nSlot
);
2105 xDisp
= pCache
->GetDispatch();
2106 if ( xDisp
.is() || !pCache
)
2108 const SfxSlot
* pSlot
= SfxSlotPool::GetSlotPool( pDispatcher
->GetFrame() ).GetSlot( nSlot
);
2109 if ( !pSlot
|| !pSlot
->pUnoName
)
2110 return SFX_ITEM_DISABLED
;
2112 ::com::sun::star::util::URL aURL
;
2113 ::rtl::OUString
aCmd( DEFINE_CONST_UNICODE(".uno:"));
2114 aURL
.Protocol
= aCmd
;
2115 aURL
.Path
= ::rtl::OUString::createFromAscii(pSlot
->GetUnoName());
2117 aURL
.Complete
= aCmd
;
2121 xDisp
= pImp
->xProv
->queryDispatch( aURL
, ::rtl::OUString(), 0 );
2125 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XUnoTunnel
> xTunnel( xDisp
, ::com::sun::star::uno::UNO_QUERY
);
2126 SfxOfficeDispatch
* pDisp
= NULL
;
2129 sal_Int64 nImplementation
= xTunnel
->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
2130 pDisp
= reinterpret_cast< SfxOfficeDispatch
* >( sal::static_int_cast
< sal_IntPtr
>( nImplementation
));
2135 BOOL bDeleteCache
= FALSE
;
2138 pCache
= new SfxStateCache( nSlot
);
2139 pCache
->GetSlotServer( *GetDispatcher_Impl(), pImp
->xProv
);
2140 bDeleteCache
= TRUE
;
2143 SfxItemState eState
= SFX_ITEM_SET
;
2144 SfxPoolItem
*pItem
=NULL
;
2145 BindDispatch_Impl
*pBind
= new BindDispatch_Impl( xDisp
, aURL
, pCache
, pSlot
);
2147 xDisp
->addStatusListener( pBind
, aURL
);
2148 if ( !pBind
->GetStatus().IsEnabled
)
2150 eState
= SFX_ITEM_DISABLED
;
2154 ::com::sun::star::uno::Any aAny
= pBind
->GetStatus().State
;
2155 ::com::sun::star::uno::Type pType
= aAny
.getValueType();
2157 if ( pType
== ::getBooleanCppuType() )
2159 sal_Bool bTemp
= false;
2161 pItem
= new SfxBoolItem( nSlot
, bTemp
);
2163 else if ( pType
== ::getCppuType((const sal_uInt16
*)0) )
2165 sal_uInt16 nTemp
= 0;
2167 pItem
= new SfxUInt16Item( nSlot
, nTemp
);
2169 else if ( pType
== ::getCppuType((const sal_uInt32
*)0) )
2171 sal_uInt32 nTemp
= 0;
2173 pItem
= new SfxUInt32Item( nSlot
, nTemp
);
2175 else if ( pType
== ::getCppuType((const ::rtl::OUString
*)0) )
2177 ::rtl::OUString sTemp
;
2179 pItem
= new SfxStringItem( nSlot
, sTemp
);
2182 pItem
= new SfxVoidItem( nSlot
);
2185 xDisp
->removeStatusListener( pBind
, aURL
);
2195 // Dann am Dispatcher testen; da die von dort zur"uckgegebenen Items immer
2196 // DELETE_ON_IDLE sind, mu\s eine Kopie davon gezogen werden, um einen
2197 // Eigent"umer"ubergang zu erm"oglichen
2198 const SfxPoolItem
*pItem
= NULL
;
2199 SfxItemState eState
= pDispatcher
->QueryState( nSlot
, pItem
);
2200 if ( eState
== SFX_ITEM_SET
)
2202 DBG_ASSERT( pItem
, "SFX_ITEM_SET aber kein Item!" );
2204 rpState
= pItem
->Clone();
2206 else if ( eState
== SFX_ITEM_AVAILABLE
&& pItem
)
2208 rpState
= pItem
->Clone();
2214 void SfxBindings::SetSubBindings_Impl( SfxBindings
*pSub
)
2216 if ( pImp
->pSubBindings
)
2218 pImp
->pSubBindings
->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> () );
2219 pImp
->pSubBindings
->pImp
->pSuperBindings
= NULL
;
2222 pImp
->pSubBindings
= pSub
;
2226 pImp
->pSubBindings
->SetDispatchProvider_Impl( pImp
->xProv
);
2227 pSub
->pImp
->pSuperBindings
= this;
2231 SfxBindings
* SfxBindings::GetSubBindings_Impl( sal_Bool bTop
) const
2233 SfxBindings
*pRet
= pImp
->pSubBindings
;
2236 while ( pRet
->pImp
->pSubBindings
)
2237 pRet
= pRet
->pImp
->pSubBindings
;
2243 void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow
* pWork
)
2245 pImp
->pWorkWin
= pWork
;
2248 SfxWorkWindow
* SfxBindings::GetWorkWindow_Impl() const
2250 return pImp
->pWorkWin
;
2253 void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem
* pControl
)
2255 if ( !pImp
->pUnoCtrlArr
)
2256 pImp
->pUnoCtrlArr
= new SfxUnoControllerArr_Impl
;
2257 pImp
->pUnoCtrlArr
->Insert( pControl
, pImp
->pUnoCtrlArr
->Count() );
2260 void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem
* pControl
)
2262 if ( pImp
->pUnoCtrlArr
)
2264 sal_uInt16 nPos
= pImp
->pUnoCtrlArr
->GetPos( pControl
);
2265 if ( nPos
!= 0xFFFF )
2267 pImp
->pUnoCtrlArr
->Remove( nPos
);
2272 if ( pImp
->pSubBindings
)
2273 pImp
->pSubBindings
->ReleaseUnoController_Impl( pControl
);
2276 void SfxBindings::InvalidateUnoControllers_Impl()
2278 if ( pImp
->pUnoCtrlArr
)
2280 sal_uInt16 nCount
= pImp
->pUnoCtrlArr
->Count();
2281 for ( sal_uInt16 n
=nCount
; n
>0; n
-- )
2283 SfxUnoControllerItem
*pCtrl
= (*pImp
->pUnoCtrlArr
)[n
-1];
2284 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XStatusListener
> xRef( (::cppu::OWeakObject
*)pCtrl
, ::com::sun::star::uno::UNO_QUERY
);
2285 pCtrl
->ReleaseDispatch();
2286 pCtrl
->GetNewDispatch();
2290 if ( pImp
->pSubBindings
)
2291 pImp
->pSubBindings
->InvalidateUnoControllers_Impl();
2294 sal_Bool
SfxBindings::IsInUpdate() const
2296 sal_Bool bInUpdate
= pImp
->bInUpdate
;
2297 if ( !bInUpdate
&& pImp
->pSubBindings
)
2298 bInUpdate
= pImp
->pSubBindings
->IsInUpdate();
2302 void SfxBindings::SetVisibleState( sal_uInt16 nId
, sal_Bool bShow
)
2304 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
2305 SfxStateCache
*pCache
= GetStateCache( nId
);
2307 pCache
->SetVisibleState( bShow
);
2310 void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> & rFrame
)
2312 if ( rFrame
.is() || !pDispatcher
)
2313 SetDispatchProvider_Impl( ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> ( rFrame
, ::com::sun::star::uno::UNO_QUERY
) );
2315 SetDispatchProvider_Impl( ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> (
2316 pDispatcher
->GetFrame()->GetFrame()->GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY
) );
2319 const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> SfxBindings::GetActiveFrame() const
2321 const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> xFrame( pImp
->xProv
, ::com::sun::star::uno::UNO_QUERY
);
2322 if ( xFrame
.is() || !pDispatcher
)
2325 return pDispatcher
->GetFrame()->GetFrame()->GetFrameInterface();
2328 void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> & rProv
)
2330 sal_Bool bInvalidate
= ( rProv
!= pImp
->xProv
);
2333 pImp
->xProv
= rProv
;
2334 InvalidateAll( sal_True
);
2335 InvalidateUnoControllers_Impl();
2338 if ( pImp
->pSubBindings
)
2339 pImp
->pSubBindings
->SetDispatchProvider_Impl( pImp
->xProv
);
2342 const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatchProvider
> & SfxBindings::GetDispatchProvider_Impl() const
2347 SystemWindow
* SfxBindings::GetSystemWindow() const
2349 SfxViewFrame
*pFrame
= pDispatcher
->GetFrame();
2350 while ( pFrame
->GetParentViewFrame_Impl() )
2351 pFrame
= pFrame
->GetParentViewFrame_Impl();
2352 SfxTopViewFrame
* pTop
= PTR_CAST( SfxTopViewFrame
, pFrame
->GetTopViewFrame() );
2353 return pTop
->GetTopFrame_Impl()->GetTopWindow_Impl();
2356 BOOL
SfxBindings::ExecuteCommand_Impl( const String
& rCommand
)
2358 ::com::sun::star::util::URL aURL
;
2359 aURL
.Complete
= rCommand
;
2360 Reference
< XURLTransformer
> xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY
);
2361 xTrans
->parseStrict( aURL
);
2362 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XDispatch
> xDisp
= pImp
->xProv
->queryDispatch( aURL
, ::rtl::OUString(), 0 );
2365 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
2367 ::rtl::OUString sAppName
;
2370 static ::rtl::OUString our_aModuleManagerName
= ::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager");
2371 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xServiceManager
=
2372 ::comphelper::getProcessServiceFactory();
2373 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModuleManager
> xModuleManager(
2374 xServiceManager
->createInstance(our_aModuleManagerName
)
2375 , ::com::sun::star::uno::UNO_QUERY_THROW
);
2376 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> xFrame(
2377 pDispatcher
->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY_THROW
);
2378 sAppName
= xModuleManager
->identify(xFrame
);
2379 } catch(::com::sun::star::uno::Exception
&) {}
2380 Sequence
<beans::PropertyValue
> source
;
2381 ::comphelper::UiEventsLogger::appendDispatchOrigin(source
, sAppName
, ::rtl::OUString::createFromAscii("SfxAsyncExec"));
2382 ::comphelper::UiEventsLogger::logDispatch(aURL
, source
);
2384 new SfxAsyncExec_Impl( aURL
, xDisp
);
2391 com::sun::star::uno::Reference
< com::sun::star::frame::XDispatchRecorder
> SfxBindings::GetRecorder() const
2393 return pImp
->xRecorder
;
2396 void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference
< com::sun::star::frame::XDispatchRecorder
>& rRecorder
)
2398 pImp
->xRecorder
= rRecorder
;
2401 void SfxBindings::ContextChanged_Impl()
2403 if ( !pImp
->bInUpdate
&& ( !pImp
->bContextChanged
|| !pImp
->bAllMsgDirty
) )
2405 InvalidateAll( TRUE
);
2409 uno::Reference
< frame::XDispatch
> SfxBindings::GetDispatch( const SfxSlot
* pSlot
, const util::URL
& aURL
, sal_Bool bMasterCommand
)
2411 uno::Reference
< frame::XDispatch
> xRet
;
2412 SfxStateCache
* pCache
= GetStateCache( pSlot
->nSlotId
);
2413 if ( pCache
&& !bMasterCommand
)
2414 xRet
= pCache
->GetInternalDispatch();
2417 // dispatches for slaves are unbound, they don't have a state
2418 SfxOfficeDispatch
* pDispatch
= bMasterCommand
?
2419 new SfxOfficeDispatch( pDispatcher
, pSlot
, aURL
) :
2420 new SfxOfficeDispatch( *this, pDispatcher
, pSlot
, aURL
);
2422 pDispatch
->SetMasterUnoCommand( bMasterCommand
);
2423 xRet
= uno::Reference
< frame::XDispatch
>( pDispatch
);
2425 pCache
= GetStateCache( pSlot
->nSlotId
);
2427 DBG_ASSERT( pCache
, "No cache for OfficeDispatch!" );
2428 if ( pCache
&& !bMasterCommand
)
2429 pCache
->SetInternalDispatch( xRet
);