1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26
27 #include <hash_map>
28 #include <svl/itempool.hxx>
29 #include <svl/itemiter.hxx>
30 #include <svl/eitem.hxx>
31 #include <svl/aeitem.hxx>
32 #include <svl/intitem.hxx>
33 #include <svl/stritem.hxx>
34 #include <svl/visitem.hxx>
35 #include <com/sun/star/util/XURLTransformer.hpp>
36 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
37 #include <com/sun/star/frame/XDispatch.hpp>
38 #include <com/sun/star/frame/XDispatchProvider.hpp>
39 #include <com/sun/star/frame/XStatusListener.hpp>
40 #include <com/sun/star/frame/FrameSearchFlag.hpp>
41 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
42 #include <com/sun/star/frame/FeatureStateEvent.hpp>
43 #include <com/sun/star/frame/DispatchDescriptor.hpp>
44 #include <com/sun/star/frame/XController.hpp>
45 #include <comphelper/processfactory.hxx>
46 #include <svtools/itemdel.hxx>
47
48 #ifndef GCC
49 #endif
50
51 // wg. nInReschedule
52 #include "appdata.hxx"
53 #include <sfx2/bindings.hxx>
54 #include <sfx2/msg.hxx>
55 #include "statcach.hxx"
56 #include <sfx2/ctrlitem.hxx>
57 #include <sfx2/app.hxx>
58 #include <sfx2/dispatch.hxx>
59 #include <sfx2/request.hxx>
60 #include <sfx2/objface.hxx>
61 #include "sfxtypes.hxx"
62 #include "workwin.hxx"
63 #include <sfx2/unoctitm.hxx>
64 #include <sfx2/sfx.hrc>
65 #include <sfx2/sfxuno.hxx>
66 #include <sfx2/viewfrm.hxx>
67 #include <sfx2/objsh.hxx>
68 #include <sfx2/msgpool.hxx>
69
70 #include <comphelper/uieventslogger.hxx>
71 #include <com/sun/star/frame/XModuleManager.hpp>
72
73
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::util;
77
78 DBG_NAME(SfxBindingsMsgPos)
79 DBG_NAME(SfxBindingsUpdateServers)
80 DBG_NAME(SfxBindingsCreateSet)
81 DBG_NAME(SfxBindingsUpdateCtrl1)
82 DBG_NAME(SfxBindingsUpdateCtrl2)
83 DBG_NAME(SfxBindingsNextJob_Impl0)
84 DBG_NAME(SfxBindingsNextJob_Impl)
85 DBG_NAME(SfxBindingsUpdate_Impl)
86 DBG_NAME(SfxBindingsInvalidateAll)
87
88 //====================================================================
89
90 static sal_uInt16 nTimeOut = 300;
91
92 #define TIMEOUT_FIRST nTimeOut
93 #define TIMEOUT_UPDATING 20
94 #define TIMEOUT_IDLE 2500
95
96 static sal_uInt32 nCache1 = 0;
97 static sal_uInt32 nCache2 = 0;
98
99 typedef std::hash_map< sal_uInt16, bool > InvalidateSlotMap;
100
101 //====================================================================
102
103 DECL_PTRARRAY(SfxStateCacheArr_Impl, SfxStateCache*, 32, 16)
104
105 //====================================================================
106
107 class SfxAsyncExec_Impl
108 {
109 ::com::sun::star::util::URL aCommand;
110 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
111 Timer aTimer;
112
113 public:
114
SfxAsyncExec_Impl(const::com::sun::star::util::URL & rCmd,const::com::sun::star::uno::Reference<::com::sun::star::frame::XDispatch> & rDisp)115 SfxAsyncExec_Impl( const ::com::sun::star::util::URL& rCmd, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& rDisp )
116 : aCommand( rCmd )
117 , xDisp( rDisp )
118 {
119 aTimer.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl, TimerHdl) );
120 aTimer.SetTimeout( 0 );
121 aTimer.Start();
122 }
123
124 DECL_LINK( TimerHdl, Timer*);
125 };
126
IMPL_LINK(SfxAsyncExec_Impl,TimerHdl,Timer *,pTimer)127 IMPL_LINK(SfxAsyncExec_Impl, TimerHdl, Timer*, pTimer)
128 {
129 (void)pTimer; // unused
130 aTimer.Stop();
131
132 Sequence<beans::PropertyValue> aSeq;
133 xDisp->dispatch( aCommand, aSeq );
134
135 delete this;
136 return 0L;
137 }
138
139 class SfxBindings_Impl
140 {
141 public:
142 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchRecorder > xRecorder;
143 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv;
144 SfxUnoControllerArr_Impl*
145 pUnoCtrlArr;
146 SfxWorkWindow* pWorkWin;
147 SfxBindings* pSubBindings;
148 SfxBindings* pSuperBindings;
149 SfxStateCacheArr_Impl* pCaches; // je ein cache fuer jede gebundene
150 sal_uInt16 nCachedFunc1; // index der zuletzt gerufenen
151 sal_uInt16 nCachedFunc2; // index der vorletzt gerufenen
152 sal_uInt16 nMsgPos; // Message-Position, ab der zu aktualisieren ist
153 SfxPopupAction ePopupAction; // in DeleteFloatinWindow() abgefragt
154 sal_Bool bContextChanged;
155 sal_Bool bMsgDirty; // wurde ein MessageServer invalidiert?
156 sal_Bool bAllMsgDirty; // wurden die MessageServer invalidiert?
157 sal_Bool bAllDirty; // nach InvalidateAll
158 sal_Bool bCtrlReleased; // waehrend EnterRegistrations
159 AutoTimer aTimer; // fuer volatile Slots
160 sal_Bool bInUpdate; // fuer Assertions
161 sal_Bool bInNextJob; // fuer Assertions
162 sal_Bool bFirstRound; // Erste Runde im Update
163 sal_uInt16 nFirstShell; // Shell, die in erster Runde bevorzugt wird
164 sal_uInt16 nOwnRegLevel; // z"ahlt die echten Locks, ohne die der SuperBindings
165 InvalidateSlotMap m_aInvalidateSlots; // store slots which are invalidated while in update
166 };
167
168 //--------------------------------------------------------------------
169
170 struct SfxFoundCache_Impl
171 {
172 sal_uInt16 nSlotId; // die Slot-Id
173 sal_uInt16 nWhichId; // falls verf"ugbar die Which-Id, sonst nSlotId
174 const SfxSlot* pSlot; // Pointer auf den <Master-Slot>
175 SfxStateCache* pCache; // Pointer auf den StatusCache, ggf. 0
176
SfxFoundCache_ImplSfxFoundCache_Impl177 SfxFoundCache_Impl():
178 nSlotId(0),
179 nWhichId(0),
180 pSlot(0),
181 pCache(0)
182 {}
183
SfxFoundCache_ImplSfxFoundCache_Impl184 SfxFoundCache_Impl(SfxFoundCache_Impl&r):
185 nSlotId(r.nSlotId),
186 nWhichId(r.nWhichId),
187 pSlot(r.pSlot),
188 pCache(r.pCache)
189 {}
190
SfxFoundCache_ImplSfxFoundCache_Impl191 SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ):
192 nSlotId(nS),
193 nWhichId(nW),
194 pSlot(pS),
195 pCache(pC)
196 {}
197
operator <SfxFoundCache_Impl198 int operator<( const SfxFoundCache_Impl &r ) const
199 { return nWhichId < r.nWhichId; }
200
operator ==SfxFoundCache_Impl201 int operator==( const SfxFoundCache_Impl &r ) const
202 { return nWhichId== r.nWhichId; }
203 };
204
205 //--------------------------------------------------------------------------
206
207 SV_DECL_PTRARR_SORT_DEL(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*, 16, 16 )
208 SV_IMPL_OP_PTRARR_SORT(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*);
209
210 //==========================================================================
211
SfxBindings()212 SfxBindings::SfxBindings()
213 : pImp(new SfxBindings_Impl),
214 pDispatcher(0),
215 nRegLevel(1) // geht erst auf 0, wenn Dispatcher gesetzt
216 {
217 pImp->nMsgPos = 0;
218 pImp->bAllMsgDirty = sal_True;
219 pImp->bContextChanged = sal_False;
220 pImp->bMsgDirty = sal_True;
221 pImp->bAllDirty = sal_True;
222 pImp->ePopupAction = SFX_POPUP_DELETE;
223 pImp->nCachedFunc1 = 0;
224 pImp->nCachedFunc2 = 0;
225 pImp->bCtrlReleased = sal_False;
226 pImp->bFirstRound = sal_False;
227 pImp->bInNextJob = sal_False;
228 pImp->bInUpdate = sal_False;
229 pImp->pSubBindings = NULL;
230 pImp->pSuperBindings = NULL;
231 pImp->pWorkWin = NULL;
232 pImp->pUnoCtrlArr = NULL;
233 pImp->nOwnRegLevel = nRegLevel;
234
235 // all caches are valid (no pending invalidate-job)
236 // create the list of caches
237 pImp->pCaches = new SfxStateCacheArr_Impl;
238 pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob_Impl) );
239 }
240
241 //====================================================================
242
~SfxBindings()243 SfxBindings::~SfxBindings()
244
245 /* [Beschreibung]
246
247 Destruktor der Klasse SfxBindings. Die eine, f"ur jede <SfxApplication>
248 existierende Instanz wird von der <SfxApplication> nach Ausf"urhung
249 von <SfxApplication::Exit()> automatisch zerst"ort.
250
251 Noch existierende <SfxControllerItem> Instanzen, die bei dieser
252 SfxBindings Instanz angemeldet sind, werden im Destruktor
253 automatisch zerst"ort. Dies sind i.d.R. Floating-Toolboxen, Value-Sets
254 etc. Arrays von SfxControllerItems d"urfen zu diesem Zeitpunkt nicht
255 mehr exisitieren.
256 */
257
258 {
259 // Die SubBindings sollen ja nicht gelocked werden !
260 pImp->pSubBindings = NULL;
261
262 ENTERREGISTRATIONS();
263
264 pImp->aTimer.Stop();
265 DeleteControllers_Impl();
266
267 // Caches selbst l"oschen
268 sal_uInt16 nCount = pImp->pCaches->Count();
269 for ( sal_uInt16 nCache = 0; nCache < nCount; ++nCache )
270 delete pImp->pCaches->GetObject(nCache);
271
272 DELETEZ( pImp->pWorkWin );
273
274 delete pImp->pCaches;
275 delete pImp;
276 }
277
278 //--------------------------------------------------------------------
279
DeleteControllers_Impl()280 void SfxBindings::DeleteControllers_Impl()
281 {
282 // in der ersten Runde den SfxPopupWindows l"oschen
283 sal_uInt16 nCount = pImp->pCaches->Count();
284 sal_uInt16 nCache;
285 for ( nCache = 0; nCache < nCount; ++nCache )
286 {
287 // merken wo man ist
288 SfxStateCache *pCache = pImp->pCaches->GetObject(nCache);
289 sal_uInt16 nSlotId = pCache->GetId();
290
291 // SfxPopupWindow l"oschen lassen
292 pCache->DeleteFloatingWindows();
293
294 // da der Cache verkleinert worden sein kann, wiederaufsetzen
295 sal_uInt16 nNewCount = pImp->pCaches->Count();
296 if ( nNewCount < nCount )
297 {
298 nCache = GetSlotPos(nSlotId);
299 if ( nCache >= nNewCount ||
300 nSlotId != pImp->pCaches->GetObject(nCache)->GetId() )
301 --nCache;
302 nCount = nNewCount;
303 }
304 }
305
306 // alle Caches l"oschen
307 for ( nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
308 {
309 // Cache via ::com::sun::star::sdbcx::Index besorgen
310 SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
311
312 // alle Controller in dem Cache unbinden
313 SfxControllerItem *pNext;
314 for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
315 pCtrl; pCtrl = pNext )
316 {
317 pNext = pCtrl->GetItemLink();
318 pCtrl->UnBind();
319 }
320
321 if ( pCache->GetInternalController() )
322 pCache->GetInternalController()->UnBind();
323
324 // Cache l"oschen
325 if( nCache-1 < pImp->pCaches->Count() )
326 delete (*pImp->pCaches)[nCache-1];
327 pImp->pCaches->Remove(nCache-1, 1);
328 }
329
330 if( pImp->pUnoCtrlArr )
331 {
332 sal_uInt16 nCtrlCount = pImp->pUnoCtrlArr->Count();
333 for ( sal_uInt16 n=nCtrlCount; n>0; n-- )
334 {
335 SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
336 pCtrl->ReleaseBindings();
337 }
338
339 DBG_ASSERT( !pImp->pUnoCtrlArr->Count(), "UnoControllerItems nicht entfernt!" );
340 DELETEZ( pImp->pUnoCtrlArr );
341 }
342 }
343
344 //--------------------------------------------------------------------
345
GetPopupAction_Impl() const346 SfxPopupAction SfxBindings::GetPopupAction_Impl() const
347 {
348 return pImp->ePopupAction;
349 }
350
351
352 //--------------------------------------------------------------------
353
HidePopups(bool bHide)354 void SfxBindings::HidePopups( bool bHide )
355 {
356 // SfxPopupWindows hiden
357 HidePopupCtrls_Impl( bHide );
358 SfxBindings *pSub = pImp->pSubBindings;
359 while ( pSub )
360 {
361 pImp->pSubBindings->HidePopupCtrls_Impl( bHide );
362 pSub = pSub->pImp->pSubBindings;
363 }
364
365 // SfxChildWindows hiden
366 DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" );
367 if ( pImp->pWorkWin )
368 pImp->pWorkWin->HidePopups_Impl( bHide, sal_True );
369 }
370
HidePopupCtrls_Impl(FASTBOOL bHide)371 void SfxBindings::HidePopupCtrls_Impl( FASTBOOL bHide )
372 {
373 if ( bHide )
374 {
375 // SfxPopupWindows hiden
376 pImp->ePopupAction = SFX_POPUP_HIDE;
377 }
378 else
379 {
380 // SfxPopupWindows showen
381 pImp->ePopupAction = SFX_POPUP_SHOW;
382 }
383
384 for ( sal_uInt16 nCache = 0; nCache < pImp->pCaches->Count(); ++nCache )
385 pImp->pCaches->GetObject(nCache)->DeleteFloatingWindows();
386 pImp->ePopupAction = SFX_POPUP_DELETE;
387 }
388
389 //--------------------------------------------------------------------
390
Update_Impl(SfxStateCache * pCache)391 void SfxBindings::Update_Impl
392 (
393 SfxStateCache* pCache // der upzudatende SfxStatusCache
394 )
395 {
396 if( pCache->GetDispatch().is() && pCache->GetItemLink() )
397 {
398 pCache->SetCachedState(sal_True);
399 if ( !pCache->GetInternalController() )
400 return;
401 }
402
403 if ( !pDispatcher )
404 return;
405 DBG_PROFSTART(SfxBindingsUpdate_Impl);
406
407 // alle mit derselben Statusmethode zusammensammeln, die dirty sind
408 SfxDispatcher &rDispat = *pDispatcher;
409 const SfxSlot *pRealSlot = 0;
410 const SfxSlotServer* pMsgServer = 0;
411 SfxFoundCacheArr_Impl aFound;
412 SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound );
413 sal_Bool bUpdated = sal_False;
414 if ( pSet )
415 {
416 // Status erfragen
417 if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) )
418 {
419 // Status posten
420 const SfxInterface *pInterface =
421 rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface();
422 for ( sal_uInt16 nPos = 0; nPos < aFound.Count(); ++nPos )
423 {
424 const SfxFoundCache_Impl *pFound = aFound[nPos];
425 sal_uInt16 nWhich = pFound->nWhichId;
426 const SfxPoolItem *pItem = 0;
427 SfxItemState eState = pSet->GetItemState(nWhich, sal_True, &pItem);
428 if ( eState == SFX_ITEM_DEFAULT && SfxItemPool::IsWhich(nWhich) )
429 pItem = &pSet->Get(nWhich);
430 UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState );
431 }
432 bUpdated = sal_True;
433 }
434
435 delete pSet;
436 }
437
438 if ( !bUpdated && pCache )
439 {
440 // Wenn pCache == NULL und kein SlotServer ( z.B. weil Dispatcher gelockt! ),
441 // darf nat"urlich kein Update versucht werden
442 SfxFoundCache_Impl aFoundCache(
443 pCache->GetId(), 0,
444 pRealSlot, pCache );
445 UpdateControllers_Impl( 0, &aFoundCache, 0, SFX_ITEM_DISABLED);
446 }
447
448 DBG_PROFSTOP(SfxBindingsUpdate_Impl);
449 }
450
451 //--------------------------------------------------------------------
452
InvalidateSlotsInMap_Impl()453 void SfxBindings::InvalidateSlotsInMap_Impl()
454 {
455 InvalidateSlotMap::const_iterator pIter = pImp->m_aInvalidateSlots.begin();
456 while ( pIter != pImp->m_aInvalidateSlots.end() )
457 {
458 Invalidate( pIter->first );
459 ++pIter;
460 }
461 pImp->m_aInvalidateSlots.clear();
462 }
463
464 //--------------------------------------------------------------------
465
AddSlotToInvalidateSlotsMap_Impl(sal_uInt16 nId)466 void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( sal_uInt16 nId )
467 {
468 pImp->m_aInvalidateSlots[nId] = sal_True;
469 }
470
471 //--------------------------------------------------------------------
472
Update(sal_uInt16 nId)473 void SfxBindings::Update
474 (
475 sal_uInt16 nId // die gebundene und upzudatende Slot-Id
476 )
477 {
478 DBG_MEMTEST();
479 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
480
481 //!!TLX: Fuehrte zu Vorlagenkatalogstillstand
482 // if ( nRegLevel )
483 // return;
484
485 if ( pDispatcher )
486 pDispatcher->Flush();
487
488 if ( pImp->pSubBindings )
489 pImp->pSubBindings->Update( nId );
490
491 SfxStateCache* pCache = GetStateCache( nId );
492 if ( pCache )
493 {
494 pImp->bInUpdate = sal_True;
495 if ( pImp->bMsgDirty )
496 {
497 UpdateSlotServer_Impl();
498 pCache = GetStateCache( nId );
499 }
500
501 if (pCache)
502 {
503 sal_Bool bInternalUpdate = sal_True;
504 if( pCache->GetDispatch().is() && pCache->GetItemLink() )
505 {
506 pCache->SetCachedState(sal_True);
507 bInternalUpdate = ( pCache->GetInternalController() != 0 );
508 }
509
510 if ( bInternalUpdate )
511 {
512 // Status erfragen
513 const SfxSlotServer* pMsgServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
514 if ( !pCache->IsControllerDirty() &&
515 ( !pMsgServer ||
516 !pMsgServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) )
517 {
518 pImp->bInUpdate = sal_False;
519 InvalidateSlotsInMap_Impl();
520 return;
521 }
522 if (!pMsgServer)
523 {
524 pCache->SetState(SFX_ITEM_DISABLED, 0);
525 pImp->bInUpdate = sal_False;
526 InvalidateSlotsInMap_Impl();
527 return;
528 }
529
530 Update_Impl(pCache);
531 }
532
533 pImp->bAllDirty = sal_False;
534 }
535
536 pImp->bInUpdate = sal_False;
537 InvalidateSlotsInMap_Impl();
538 }
539 }
540
541 //--------------------------------------------------------------------
542
Update()543 void SfxBindings::Update()
544 {
545 DBG_MEMTEST();
546 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
547
548 if ( pImp->pSubBindings )
549 pImp->pSubBindings->Update();
550
551 if ( pDispatcher )
552 {
553 if ( nRegLevel )
554 return;
555
556 pImp->bInUpdate = sal_True;
557 pDispatcher->Flush();
558 pDispatcher->Update_Impl();
559 while ( !NextJob_Impl(0) )
560 ; // loop
561 pImp->bInUpdate = sal_False;
562 InvalidateSlotsInMap_Impl();
563 }
564 }
565
566 //--------------------------------------------------------------------
567
SetState(const SfxItemSet & rSet)568 void SfxBindings::SetState
569 (
570 const SfxItemSet& rSet // zu setzende Status-Werte
571 )
572 {
573 // wenn gelockt, dann nur invalidieren
574 if ( nRegLevel )
575 {
576 SfxItemIter aIter(rSet);
577 for ( const SfxPoolItem *pItem = aIter.FirstItem();
578 pItem;
579 pItem = aIter.NextItem() )
580 Invalidate( pItem->Which() );
581 }
582 else
583 {
584 // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
585 if ( pImp->bMsgDirty )
586 UpdateSlotServer_Impl();
587
588 // "uber das ItemSet iterieren, falls Slot gebunden, updaten
589 //! Bug: WhichIter verwenden und ggf. VoidItems hochschicken
590 SfxItemIter aIter(rSet);
591 for ( const SfxPoolItem *pItem = aIter.FirstItem();
592 pItem;
593 pItem = aIter.NextItem() )
594 {
595 SfxStateCache* pCache =
596 GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) );
597 if ( pCache )
598 {
599 // Status updaten
600 if ( !pCache->IsControllerDirty() )
601 pCache->Invalidate(sal_False);
602 pCache->SetState( SFX_ITEM_AVAILABLE, pItem );
603
604 //! nicht implementiert: Updates von EnumSlots via MasterSlots
605 }
606 }
607 }
608 }
609
610 //--------------------------------------------------------------------
611
SetState(const SfxPoolItem & rItem)612 void SfxBindings::SetState
613 (
614 const SfxPoolItem& rItem // zu setzender Status-Wert
615 )
616 {
617 if ( nRegLevel )
618 {
619 Invalidate( rItem.Which() );
620 }
621 else
622 {
623 // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
624 if ( pImp->bMsgDirty )
625 UpdateSlotServer_Impl();
626
627 // falls der Slot gebunden ist, updaten
628 DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
629 "cannot set items with which-id" );
630 SfxStateCache* pCache = GetStateCache( rItem.Which() );
631 if ( pCache )
632 {
633 // Status updaten
634 if ( !pCache->IsControllerDirty() )
635 pCache->Invalidate(sal_False);
636 pCache->SetState( SFX_ITEM_AVAILABLE, &rItem );
637
638 //! nicht implementiert: Updates von EnumSlots via MasterSlots
639 }
640 }
641 }
642
643
644 //--------------------------------------------------------------------
645
GetAnyStateCache_Impl(sal_uInt16 nId)646 SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId )
647 {
648 SfxStateCache* pCache = GetStateCache( nId );
649 if ( !pCache && pImp->pSubBindings )
650 return pImp->pSubBindings->GetAnyStateCache_Impl( nId );
651 return pCache;
652 }
653
GetStateCache(sal_uInt16 nId,sal_uInt16 * pPos)654 SfxStateCache* SfxBindings::GetStateCache
655 (
656 sal_uInt16 nId /* Slot-Id, deren SfxStatusCache gefunden
657 werden soll */,
658 sal_uInt16* pPos /* 0 bzw. Position, ab der die Bindings
659 bin"ar durchsucht werden sollen. Liefert
660 die Position zur"uck, an der nId gefunden
661 wurde, bzw. an der es einfef"ugt werden
662 w"urde. */
663 )
664 {
665 DBG_MEMTEST();
666 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
667 // is the specified function bound?
668 const sal_uInt16 nStart = ( pPos ? *pPos : 0 );
669 const sal_uInt16 nPos = GetSlotPos( nId, nStart );
670
671 if ( nPos < pImp->pCaches->Count() &&
672 (*pImp->pCaches)[nPos]->GetId() == nId )
673 {
674 if ( pPos )
675 *pPos = nPos;
676 return (*pImp->pCaches)[nPos];
677 }
678 return 0;
679 }
680
681 //--------------------------------------------------------------------
682
InvalidateAll(sal_Bool bWithMsg)683 void SfxBindings::InvalidateAll
684 (
685 sal_Bool bWithMsg /* sal_True
686 Slot-Server als ung"ultig markieren
687
688 sal_False
689 Slot-Server bleiben g"ultig */
690 )
691 {
692 DBG_PROFSTART(SfxBindingsInvalidateAll);
693 DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
694
695 DBG_MEMTEST();
696
697 if ( pImp->pSubBindings )
698 pImp->pSubBindings->InvalidateAll( bWithMsg );
699
700 // ist schon alles dirty gesetzt oder downing => nicht zu tun
701 if ( !pDispatcher ||
702 ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) ||
703 SFX_APP()->IsDowning() )
704 {
705 DBG_PROFSTOP(SfxBindingsInvalidateAll);
706 return;
707 }
708
709 pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg;
710 pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg;
711 pImp->bAllDirty = sal_True;
712
713 for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
714 pImp->pCaches->GetObject(n)->Invalidate(bWithMsg);
715 /*
716 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
717 ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
718
719 if ( bWithMsg && xFrame.is() )
720 xFrame->contextChanged();
721 */
722 pImp->nMsgPos = 0;
723 if ( !nRegLevel )
724 {
725 pImp->aTimer.Stop();
726 pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
727 pImp->aTimer.Start();
728 // pImp->bFirstRound = sal_True;
729 // pImp->nFirstShell = 0;
730 }
731
732 DBG_PROFSTOP(SfxBindingsInvalidateAll);
733 }
734
735 //--------------------------------------------------------------------
736
Invalidate(const sal_uInt16 * pIds)737 void SfxBindings::Invalidate
738 (
739 const sal_uInt16* pIds /* numerisch sortiertes 0-terminiertes Array
740 von Slot-Ids (einzel, nicht als Paare!) */
741 )
742 {
743 DBG_PROFSTART(SfxBindingsInvalidateAll);
744 // DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
745
746 DBG_MEMTEST();
747
748 if ( pImp->bInUpdate )
749 {
750 sal_Int32 i = 0;
751 while ( pIds[i] != 0 )
752 AddSlotToInvalidateSlotsMap_Impl( pIds[i++] );
753
754 if ( pImp->pSubBindings )
755 pImp->pSubBindings->Invalidate( pIds );
756 return;
757 }
758
759 if ( pImp->pSubBindings )
760 pImp->pSubBindings->Invalidate( pIds );
761
762 // ist schon alles dirty gesetzt oder downing => nicht zu tun
763 if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
764 return;
765
766 // in immer kleiner werdenden Berichen bin"ar suchen
767 for ( sal_uInt16 n = GetSlotPos(*pIds);
768 *pIds && n < pImp->pCaches->Count();
769 n = GetSlotPos(*pIds, n) )
770 {
771 // falls SID "uberhaupt gebunden ist, den Cache invalidieren
772 SfxStateCache *pCache = pImp->pCaches->GetObject(n);
773 if ( pCache->GetId() == *pIds )
774 pCache->Invalidate(sal_False);
775
776 // n"achste SID
777 if ( !*++pIds )
778 break;
779 DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" );
780 }
781
782 // falls nicht gelockt, Update-Timer starten
783 pImp->nMsgPos = 0;
784 if ( !nRegLevel )
785 {
786 pImp->aTimer.Stop();
787 pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
788 pImp->aTimer.Start();
789 // pImp->bFirstRound = sal_True;
790 // pImp->nFirstShell = 0;
791 }
792
793 DBG_PROFSTOP(SfxBindingsInvalidateAll);
794 }
795
796 //--------------------------------------------------------------------
797
InvalidateShell(const SfxShell & rSh,sal_Bool bDeep)798 void SfxBindings::InvalidateShell
799 (
800 const SfxShell& rSh /* Die <SfxShell>, deren Slot-Ids
801 invalidiert werden sollen. */,
802
803 sal_Bool bDeep /* sal_True
804 auch die, von der SfxShell
805 ererbten Slot-Ids werden invalidert
806
807 sal_False
808 die ererbten und nicht "uberladenen
809 Slot-Ids werden invalidiert */
810 //! MI: z. Zt. immer bDeep
811 )
812 {
813 DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
814
815 if ( pImp->pSubBindings )
816 pImp->pSubBindings->InvalidateShell( rSh, bDeep );
817
818 if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
819 return;
820
821 DBG_PROFSTART(SfxBindingsInvalidateAll);
822 DBG_MEMTEST();
823
824 // Jetzt schon flushen, wird in GetShellLevel(rSh) sowieso gemacht; wichtig,
825 // damit pImp->bAll(Msg)Dirty korrekt gesetzt ist
826 pDispatcher->Flush();
827
828 if ( !pDispatcher ||
829 ( pImp->bAllDirty && pImp->bAllMsgDirty ) ||
830 SFX_APP()->IsDowning() )
831 {
832 // Wenn sowieso demn"achst alle Server geholt werden
833 return;
834 }
835
836 // Level finden
837 sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh);
838 if ( nLevel != USHRT_MAX )
839 {
840 for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
841 {
842 SfxStateCache *pCache = pImp->pCaches->GetObject(n);
843 const SfxSlotServer *pMsgServer =
844 pCache->GetSlotServer(*pDispatcher, pImp->xProv);
845 if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel )
846 pCache->Invalidate(sal_False);
847 }
848 pImp->nMsgPos = 0;
849 if ( !nRegLevel )
850 {
851 pImp->aTimer.Stop();
852 pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
853 pImp->aTimer.Start();
854 pImp->bFirstRound = sal_True;
855 pImp->nFirstShell = nLevel;
856 }
857 }
858
859 DBG_PROFSTOP(SfxBindingsInvalidateAll);
860 }
861
862 //--------------------------------------------------------------------
863
Invalidate(sal_uInt16 nId)864 void SfxBindings::Invalidate
865 (
866 sal_uInt16 nId // zu invalidierende Slot-Id
867 )
868 {
869 DBG_MEMTEST();
870 // DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
871
872 if ( pImp->bInUpdate )
873 {
874 AddSlotToInvalidateSlotsMap_Impl( nId );
875 if ( pImp->pSubBindings )
876 pImp->pSubBindings->Invalidate( nId );
877 return;
878 }
879
880 if ( pImp->pSubBindings )
881 pImp->pSubBindings->Invalidate( nId );
882
883 if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
884 return;
885
886 SfxStateCache* pCache = GetStateCache(nId);
887 if ( pCache )
888 {
889 pCache->Invalidate(sal_False);
890 pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
891 if ( !nRegLevel )
892 {
893 pImp->aTimer.Stop();
894 pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
895 pImp->aTimer.Start();
896 }
897 }
898 }
899
900 //--------------------------------------------------------------------
901
Invalidate(sal_uInt16 nId,sal_Bool bWithItem,sal_Bool bWithMsg)902 void SfxBindings::Invalidate
903 (
904 sal_uInt16 nId, // zu invalidierende Slot-Id
905 sal_Bool bWithItem, // StateCache clearen ?
906 sal_Bool bWithMsg // SlotServer neu holen ?
907 )
908 {
909 DBG_MEMTEST();
910 DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
911
912 if ( pImp->pSubBindings )
913 pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
914
915 if ( SFX_APP()->IsDowning() )
916 return;
917
918 SfxStateCache* pCache = GetStateCache(nId);
919 if ( pCache )
920 {
921 if ( bWithItem )
922 pCache->ClearCache();
923 pCache->Invalidate(bWithMsg);
924
925 if ( !pDispatcher || pImp->bAllDirty )
926 return;
927
928 pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
929 if ( !nRegLevel )
930 {
931 pImp->aTimer.Stop();
932 pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
933 pImp->aTimer.Start();
934 }
935 }
936 }
937
938 //--------------------------------------------------------------------
939
IsBound(sal_uInt16 nSlotId,sal_uInt16 nStartSearchAt)940 sal_Bool SfxBindings::IsBound( sal_uInt16 nSlotId, sal_uInt16 nStartSearchAt )
941 {
942 DBG_MEMTEST();
943 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
944 return GetStateCache(nSlotId, &nStartSearchAt ) != 0;
945 }
946
947 //--------------------------------------------------------------------
948
GetSlotPos(sal_uInt16 nId,sal_uInt16 nStartSearchAt)949 sal_uInt16 SfxBindings::GetSlotPos( sal_uInt16 nId, sal_uInt16 nStartSearchAt )
950 {
951 DBG_MEMTEST();
952 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
953 DBG_PROFSTART(SfxBindingsMsgPos);
954
955 // answer immediately if a function-seek comes repeated
956 if ( pImp->nCachedFunc1 < pImp->pCaches->Count() &&
957 (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId )
958 {
959 ++nCache1;
960 DBG_PROFSTOP(SfxBindingsMsgPos);
961 return pImp->nCachedFunc1;
962 }
963 if ( pImp->nCachedFunc2 < pImp->pCaches->Count() &&
964 (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId )
965 {
966 ++nCache2;
967
968 // swap the caches
969 sal_uInt16 nTemp = pImp->nCachedFunc1;
970 pImp->nCachedFunc1 = pImp->nCachedFunc2;
971 pImp->nCachedFunc2 = nTemp;
972 DBG_PROFSTOP(SfxBindingsMsgPos);
973 return pImp->nCachedFunc1;
974 }
975
976 // binary search, if not found, seek to target-position
977 if ( pImp->pCaches->Count() <= nStartSearchAt )
978 {
979 DBG_PROFSTOP(SfxBindingsMsgPos);
980 return 0;
981 }
982 if ( pImp->pCaches->Count() == (nStartSearchAt+1) )
983 {
984 DBG_PROFSTOP(SfxBindingsMsgPos);
985 return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1;
986 }
987 sal_uInt16 nLow = nStartSearchAt;
988 sal_uInt16 nMid = 0;
989 sal_uInt16 nHigh = 0;
990 sal_Bool bFound = sal_False;
991 nHigh = pImp->pCaches->Count() - 1;
992 while ( !bFound && nLow <= nHigh )
993 {
994 nMid = (nLow + nHigh) >> 1;
995 DBG_ASSERT( nMid < pImp->pCaches->Count(), "bsearch ist buggy" );
996 int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() );
997 if ( nDiff < 0)
998 { if ( nMid == 0 )
999 break;
1000 nHigh = nMid - 1;
1001 }
1002 else if ( nDiff > 0 )
1003 { nLow = nMid + 1;
1004 if ( nLow == 0 )
1005 break;
1006 }
1007 else
1008 bFound = sal_True;
1009 }
1010 sal_uInt16 nPos = bFound ? nMid : nLow;
1011 DBG_ASSERT( nPos <= pImp->pCaches->Count(), "" );
1012 DBG_ASSERT( nPos == pImp->pCaches->Count() ||
1013 nId <= (*pImp->pCaches)[nPos]->GetId(), "" );
1014 DBG_ASSERT( nPos == nStartSearchAt ||
1015 nId > (*pImp->pCaches)[nPos-1]->GetId(), "" );
1016 DBG_ASSERT( ( (nPos+1) >= pImp->pCaches->Count() ) ||
1017 nId < (*pImp->pCaches)[nPos+1]->GetId(), "" );
1018 pImp->nCachedFunc2 = pImp->nCachedFunc1;
1019 pImp->nCachedFunc1 = nPos;
1020 DBG_PROFSTOP(SfxBindingsMsgPos);
1021 return nPos;
1022 }
1023 //--------------------------------------------------------------------
RegisterInternal_Impl(SfxControllerItem & rItem)1024 void SfxBindings::RegisterInternal_Impl( SfxControllerItem& rItem )
1025 {
1026 Register_Impl( rItem, sal_True );
1027
1028 }
1029
Register(SfxControllerItem & rItem)1030 void SfxBindings::Register( SfxControllerItem& rItem )
1031 {
1032 Register_Impl( rItem, sal_False );
1033 }
1034
Register_Impl(SfxControllerItem & rItem,sal_Bool bInternal)1035 void SfxBindings::Register_Impl( SfxControllerItem& rItem, sal_Bool bInternal )
1036 {
1037 DBG_MEMTEST();
1038 // DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
1039 DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" );
1040
1041 // insert new cache if it does not already exist
1042 sal_uInt16 nId = rItem.GetId();
1043 sal_uInt16 nPos = GetSlotPos(nId);
1044 if ( nPos >= pImp->pCaches->Count() ||
1045 (*pImp->pCaches)[nPos]->GetId() != nId )
1046 {
1047 SfxStateCache* pCache = new SfxStateCache(nId);
1048 pImp->pCaches->Insert( nPos, pCache );
1049 DBG_ASSERT( nPos == 0 ||
1050 (*pImp->pCaches)[nPos]->GetId() >
1051 (*pImp->pCaches)[nPos-1]->GetId(), "" );
1052 DBG_ASSERT( (nPos == pImp->pCaches->Count()-1) ||
1053 (*pImp->pCaches)[nPos]->GetId() <
1054 (*pImp->pCaches)[nPos+1]->GetId(), "" );
1055 pImp->bMsgDirty = sal_True;
1056 }
1057
1058 // enqueue the new binding
1059 if ( bInternal )
1060 {
1061 (*pImp->pCaches)[nPos]->SetInternalController( &rItem );
1062 }
1063 else
1064 {
1065 SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem);
1066 rItem.ChangeItemLink(pOldItem);
1067 }
1068 }
1069
1070 //--------------------------------------------------------------------
1071
Release(SfxControllerItem & rItem)1072 void SfxBindings::Release( SfxControllerItem& rItem )
1073 {
1074 DBG_MEMTEST();
1075 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1076 //! DBG_ASSERT( nRegLevel > 0, "release without EnterRegistrations" );
1077 DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" );
1078 ENTERREGISTRATIONS();
1079
1080 // find the bound function
1081 sal_uInt16 nId = rItem.GetId();
1082 sal_uInt16 nPos = GetSlotPos(nId);
1083 SfxStateCache* pCache = (*pImp->pCaches)[nPos];
1084 if ( pCache->GetId() == nId )
1085 {
1086 if ( pCache->GetInternalController() == &rItem )
1087 {
1088 pCache->ReleaseInternalController();
1089 }
1090 else
1091 {
1092 // is this the first binding in the list?
1093 SfxControllerItem* pItem = pCache->GetItemLink();
1094 if ( pItem == &rItem )
1095 pCache->ChangeItemLink( rItem.GetItemLink() );
1096 else
1097 {
1098 // search the binding in the list
1099 while ( pItem && pItem->GetItemLink() != &rItem )
1100 pItem = pItem->GetItemLink();
1101
1102 // unlink it if it was found
1103 if ( pItem )
1104 pItem->ChangeItemLink( rItem.GetItemLink() );
1105 }
1106 }
1107
1108 // was this the last controller?
1109 if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
1110 {
1111 #ifdef slow
1112 // remove the BoundFunc
1113 delete (*pImp->pCaches)[nPos];
1114 pImp->pCaches->Remove(nPos, 1);
1115 #endif
1116 pImp->bCtrlReleased = sal_True;
1117 }
1118 }
1119
1120 LEAVEREGISTRATIONS();
1121 }
1122
1123 //--------------------------------------------------------------------
ExecuteSynchron(sal_uInt16 nId,const SfxPoolItem ** ppItems,sal_uInt16 nModi,const SfxPoolItem ** ppInternalArgs)1124 const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi,
1125 const SfxPoolItem **ppInternalArgs )
1126 {
1127 DBG_MEMTEST();
1128 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1129
1130 if( !nId || !pDispatcher )
1131 return NULL;
1132
1133 return Execute_Impl( nId, ppItems, nModi, SFX_CALLMODE_SYNCHRON, ppInternalArgs );
1134 }
1135
Execute(sal_uInt16 nId,const SfxPoolItem ** ppItems,sal_uInt16 nModi,SfxCallMode nCallMode,const SfxPoolItem ** ppInternalArgs)1136 sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
1137 const SfxPoolItem **ppInternalArgs )
1138 {
1139 DBG_MEMTEST();
1140 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1141
1142 if( !nId || !pDispatcher )
1143 return sal_False;
1144
1145 const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs );
1146 return ( pRet != 0 );
1147 }
1148
ExecuteGlobal_Impl(sal_uInt16 nId)1149 void SfxBindings::ExecuteGlobal_Impl( sal_uInt16 nId )
1150 {
1151 if( nId && pDispatcher )
1152 Execute_Impl( nId, NULL, 0, SFX_CALLMODE_ASYNCHRON, NULL, sal_True );
1153 }
1154
Execute_Impl(sal_uInt16 nId,const SfxPoolItem ** ppItems,sal_uInt16 nModi,SfxCallMode nCallMode,const SfxPoolItem ** ppInternalArgs,sal_Bool bGlobalOnly)1155 const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
1156 const SfxPoolItem **ppInternalArgs, sal_Bool bGlobalOnly )
1157 {
1158 SfxStateCache *pCache = GetStateCache( nId );
1159 if ( !pCache )
1160 {
1161 SfxBindings *pBind = pImp->pSubBindings;
1162 while ( pBind )
1163 {
1164 if ( pBind->GetStateCache( nId ) )
1165 return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly );
1166 pBind = pBind->pImp->pSubBindings;
1167 };
1168 }
1169
1170 SfxDispatcher &rDispatcher = *pDispatcher;
1171 rDispatcher.Flush();
1172 rDispatcher.GetFrame(); // -Wall is this required???
1173
1174 // get SlotServer (Slot+ShellLevel) and Shell from cache
1175 sal_Bool bDeleteCache = sal_False;
1176 if ( !pCache )
1177 {
1178 // Execution of non cached slots (Accelerators don't use Controllers)
1179 // slot is uncached, use SlotCache to handle external dispatch providers
1180 pCache = new SfxStateCache( nId );
1181 pCache->GetSlotServer( rDispatcher, pImp->xProv );
1182 bDeleteCache = sal_True;
1183 }
1184
1185 if ( pCache && pCache->GetDispatch().is() )
1186 {
1187 DBG_ASSERT( !ppInternalArgs, "Internal args get lost when dispatched!" );
1188
1189 SfxItemPool &rPool = GetDispatcher()->GetFrame()->GetObjectShell()->GetPool();
1190 SfxRequest aReq( nId, nCallMode, rPool );
1191 aReq.SetModifier( nModi );
1192 if( ppItems )
1193 while( *ppItems )
1194 aReq.AppendItem( **ppItems++ );
1195
1196 // cache binds to an external dispatch provider
1197 pCache->Dispatch( aReq.GetArgs(), nCallMode == SFX_CALLMODE_SYNCHRON );
1198 if ( bDeleteCache )
1199 DELETEZ( pCache );
1200 SfxPoolItem *pVoid = new SfxVoidItem( nId );
1201 DeleteItemOnIdle( pVoid );
1202 return pVoid;
1203 }
1204
1205 // slot is handled internally by SfxDispatcher
1206 if ( pImp->bMsgDirty )
1207 UpdateSlotServer_Impl();
1208
1209 SfxShell *pShell=0;
1210 const SfxSlot *pSlot=0;
1211
1212 // if slot was uncached, we should have created a cache in this method!
1213 DBG_ASSERT( pCache, "This code needs a cache!");
1214 const SfxSlotServer* pServer = pCache ? pCache->GetSlotServer( rDispatcher, pImp->xProv ) : 0;
1215 if ( !pServer )
1216 {
1217 return NULL;
1218 }
1219 else
1220 {
1221 pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
1222 pSlot = pServer->GetSlot();
1223 }
1224
1225 if ( bGlobalOnly )
1226 if ( !pShell->ISA(SfxModule) && !pShell->ISA(SfxApplication) && !pShell->ISA(SfxViewFrame) )
1227 return NULL;
1228
1229 SfxItemPool &rPool = pShell->GetPool();
1230 SfxRequest aReq( nId, nCallMode, rPool );
1231 aReq.SetModifier( nModi );
1232 if( ppItems )
1233 while( *ppItems )
1234 aReq.AppendItem( **ppItems++ );
1235 if ( ppInternalArgs )
1236 {
1237 SfxAllItemSet aSet( rPool );
1238 for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
1239 aSet.Put( **pArg );
1240 aReq.SetInternalArgs_Impl( aSet );
1241 }
1242
1243 Execute_Impl( aReq, pSlot, pShell );
1244
1245 const SfxPoolItem* pRet = aReq.GetReturnValue();
1246 if ( !pRet )
1247 {
1248 SfxPoolItem *pVoid = new SfxVoidItem( nId );
1249 DeleteItemOnIdle( pVoid );
1250 pRet = pVoid;
1251 }
1252
1253 if ( bDeleteCache )
1254 delete pCache;
1255
1256 return pRet;
1257 }
1258
Execute_Impl(SfxRequest & aReq,const SfxSlot * pSlot,SfxShell * pShell)1259 void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell )
1260 {
1261 SfxItemPool &rPool = pShell->GetPool();
1262
1263 if ( SFX_KIND_ENUM == pSlot->GetKind() )
1264 {
1265 // bei Enum-Slots muss der Master mit dem Wert des Enums executet werden
1266 const SfxSlot *pRealSlot = pShell->GetInterface()->GetRealSlot(pSlot);
1267 const sal_uInt16 nSlotId = pRealSlot->GetSlotId();
1268 aReq.SetSlot( nSlotId );
1269 aReq.AppendItem( SfxAllEnumItem( rPool.GetWhich(nSlotId), pSlot->GetValue() ) );
1270 pDispatcher->_Execute( *pShell, *pRealSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1271 }
1272 else if ( SFX_KIND_ATTR == pSlot->GetKind() )
1273 {
1274 // bei Attr-Slots muss der Which-Wert gemapped werden
1275 const sal_uInt16 nSlotId = pSlot->GetSlotId();
1276 aReq.SetSlot( nSlotId );
1277 if ( pSlot->IsMode(SFX_SLOT_TOGGLE) )
1278 {
1279 // an togglebare-Attribs (Bools) wird der Wert angeheangt
1280 sal_uInt16 nWhich = pSlot->GetWhich(rPool);
1281 SfxItemSet aSet(rPool, nWhich, nWhich, 0);
1282 SfxStateFunc aFunc = pSlot->GetStateFnc();
1283 pShell->CallState( aFunc, aSet );
1284 const SfxPoolItem *pOldItem;
1285 SfxItemState eState = aSet.GetItemState(nWhich, sal_True, &pOldItem);
1286 if ( eState == SFX_ITEM_DISABLED )
1287 return;
1288
1289 if ( SFX_ITEM_AVAILABLE == eState && SfxItemPool::IsWhich(nWhich) )
1290 pOldItem = &aSet.Get(nWhich);
1291
1292 if ( SFX_ITEM_SET == eState ||
1293 ( SFX_ITEM_AVAILABLE == eState &&
1294 SfxItemPool::IsWhich(nWhich) &&
1295 pOldItem ) )
1296 {
1297 if ( pOldItem->ISA(SfxBoolItem) )
1298 {
1299 // wir koennen Bools toggeln
1300 sal_Bool bOldValue = ((const SfxBoolItem *)pOldItem)->GetValue();
1301 SfxBoolItem *pNewItem = (SfxBoolItem*) (pOldItem->Clone());
1302 pNewItem->SetValue( !bOldValue );
1303 aReq.AppendItem( *pNewItem );
1304 delete pNewItem;
1305 }
1306 else if ( pOldItem->ISA(SfxEnumItemInterface) &&
1307 ((SfxEnumItemInterface *)pOldItem)->HasBoolValue())
1308 {
1309 // und Enums mit Bool-Interface
1310 SfxEnumItemInterface *pNewItem =
1311 (SfxEnumItemInterface*) (pOldItem->Clone());
1312 pNewItem->SetBoolValue(!((SfxEnumItemInterface *)pOldItem)->GetBoolValue());
1313 aReq.AppendItem( *pNewItem );
1314 delete pNewItem;
1315 }
1316 else {
1317 DBG_ERROR( "Toggle only for Enums and Bools allowed" );
1318 }
1319 }
1320 else if ( SFX_ITEM_DONTCARE == eState )
1321 {
1322 // ein Status-Item per Factory erzeugen
1323 SfxPoolItem *pNewItem = pSlot->GetType()->CreateItem();
1324 DBG_ASSERT( pNewItem, "Toggle an Slot ohne ItemFactory" );
1325 pNewItem->SetWhich( nWhich );
1326
1327 if ( pNewItem->ISA(SfxBoolItem) )
1328 {
1329 // wir koennen Bools toggeln
1330 ((SfxBoolItem*)pNewItem)->SetValue( sal_True );
1331 aReq.AppendItem( *pNewItem );
1332 }
1333 else if ( pNewItem->ISA(SfxEnumItemInterface) &&
1334 ((SfxEnumItemInterface *)pNewItem)->HasBoolValue())
1335 {
1336 // und Enums mit Bool-Interface
1337 ((SfxEnumItemInterface*)pNewItem)->SetBoolValue(sal_True);
1338 aReq.AppendItem( *pNewItem );
1339 }
1340 else {
1341 DBG_ERROR( "Toggle only for Enums and Bools allowed" );
1342 }
1343 delete pNewItem;
1344 }
1345 else {
1346 DBG_ERROR( "suspicious Toggle-Slot" );
1347 }
1348 }
1349
1350 pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1351 }
1352 else
1353 pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1354 }
1355
1356 //--------------------------------------------------------------------
1357
UpdateSlotServer_Impl()1358 void SfxBindings::UpdateSlotServer_Impl()
1359 {
1360 DBG_PROFSTART(SfxBindingsUpdateServers);
1361 DBG_MEMTEST();
1362 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1363
1364 // synchronisieren
1365 pDispatcher->Flush();
1366 // pDispatcher->Update_Impl();
1367
1368 if ( pImp->bAllMsgDirty )
1369 {
1370 if ( !nRegLevel )
1371 {
1372 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
1373 ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1374 //if ( xFrame.is() )
1375 // xFrame->contextChanged();
1376 pImp->bContextChanged = sal_False;
1377 }
1378 else
1379 pImp->bContextChanged = sal_True;
1380 }
1381
1382 const sal_uInt16 nCount = pImp->pCaches->Count();
1383 for(sal_uInt16 i = 0; i < nCount; ++i)
1384 {
1385 SfxStateCache *pCache = pImp->pCaches->GetObject(i);
1386 pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1387 }
1388 pImp->bMsgDirty = pImp->bAllMsgDirty = sal_False;
1389
1390 Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) );
1391
1392 DBG_PROFSTOP(SfxBindingsUpdateServers);
1393 }
1394
1395 //--------------------------------------------------------------------
1396
1397 #ifdef WNT
CmpUS_Impl(const void * p1,const void * p2)1398 int __cdecl CmpUS_Impl(const void *p1, const void *p2)
1399 #else
1400 int CmpUS_Impl(const void *p1, const void *p2)
1401 #endif
1402
1403 /* [Beschreibung]
1404
1405 Interne Vergleichsfunktion fuer qsort.
1406 */
1407
1408 {
1409 return *(sal_uInt16 *)p1 - *(sal_uInt16 *)p2;
1410 }
1411
1412 //--------------------------------------------------------------------
1413
CreateSet_Impl(SfxStateCache * & pCache,const SfxSlot * & pRealSlot,const SfxSlotServer ** pMsgServer,SfxFoundCacheArr_Impl & rFound)1414 SfxItemSet* SfxBindings::CreateSet_Impl
1415 (
1416 SfxStateCache*& pCache, // in: Status-Cache von nId
1417 const SfxSlot*& pRealSlot, // out: RealSlot zu nId
1418 const SfxSlotServer** pMsgServer, // out: Slot-Server zu nId
1419 SfxFoundCacheArr_Impl& rFound // out: Liste der Caches der Siblings
1420 )
1421 {
1422 DBG_MEMTEST();
1423 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1424
1425 DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl mit dirty MessageServer" );
1426
1427 const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1428 if(!pMsgSvr || !pDispatcher)
1429 return 0;
1430
1431 DBG_PROFSTART(SfxBindingsCreateSet);
1432 pRealSlot = 0;
1433 *pMsgServer = pMsgSvr;
1434
1435 sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
1436 SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
1437 if ( !pShell ) // seltener GPF beim Browsen durch Update aus Inet-Notify
1438 return 0;
1439
1440 SfxItemPool &rPool = pShell->GetPool();
1441
1442 // hole die Status-Methode, von der pCache bedient wird
1443 SfxStateFunc pFnc = 0;
1444 const SfxInterface *pInterface = pShell->GetInterface();
1445 if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() )
1446 {
1447 pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot());
1448 pCache = GetStateCache( pRealSlot->GetSlotId() );
1449 // DBG_ASSERT( pCache, "Kein Slotcache fuer den Masterslot gefunden!" );
1450 }
1451 else
1452 pRealSlot = pMsgSvr->GetSlot();
1453
1454 //
1455 // Achtung: pCache darf auch NULL sein !!!
1456 //
1457
1458 pFnc = pRealSlot->GetStateFnc();
1459
1460 // der RealSlot ist immer drin
1461 const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
1462 pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache );
1463 rFound.Insert( pFound );
1464
1465 sal_uInt16 nSlot = pRealSlot->GetSlotId();
1466 if ( !(nSlot >= SID_VERB_START && nSlot <= SID_VERB_END) )
1467 {
1468 pInterface = pInterface->GetRealInterfaceForSlot( pRealSlot );
1469 DBG_ASSERT (pInterface,"Slot in angegebener Shell nicht gefunden!");
1470 }
1471
1472 // Durchsuche die Bindings nach den von derselben Funktion bedienten Slots.
1473 // Daf"ur kommen nur Slots in Frage, die es im gefundenen Interface gibt.
1474
1475 // Die Position des Statecaches im StateCache-Array
1476 sal_uInt16 nCachePos = pImp->nMsgPos;
1477 const SfxSlot *pSibling = pRealSlot->GetNextSlot();
1478
1479 // Die Slots eines Interfaces sind im Kreis verkettet
1480 while ( pSibling > pRealSlot )
1481 {
1482 SfxStateFunc pSiblingFnc=0;
1483 SfxStateCache *pSiblingCache =
1484 GetStateCache( pSibling->GetSlotId(), &nCachePos );
1485
1486 // Ist der Slot "uberhaupt gecached ?
1487 if ( pSiblingCache )
1488 {
1489 const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv);
1490 if ( pServ && pServ->GetShellLevel() == nShellLevel )
1491 pSiblingFnc = pServ->GetSlot()->GetStateFnc();
1492 }
1493
1494 // Mu\s der Slot "uberhaupt upgedatet werden ?
1495 bool bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
1496
1497 // Bugfix #26161#: Es reicht nicht, nach der selben Shell zu fragen !!
1498 bool bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
1499
1500 // Wenn der Slot ein nicht-dirty MasterSlot ist, dann ist vielleicht
1501 // einer seiner Slaves dirty ? Dann wird der Masterslot doch eingef"ugt.
1502 if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() )
1503 {
1504 // auch Slave-Slots auf Binding pru"fen
1505 const SfxSlot* pFirstSlave = pSibling->GetLinkedSlot();
1506 for ( const SfxSlot *pSlaveSlot = pFirstSlave;
1507 !bInsert;
1508 pSlaveSlot = pSlaveSlot->GetNextSlot())
1509 {
1510 // Die Slaves zeigen auf ihren Master
1511 DBG_ASSERT(pSlaveSlot->GetLinkedSlot() == pSibling,
1512 "Falsche Master/Slave-Beziehung!");
1513
1514 sal_uInt16 nCurMsgPos = pImp->nMsgPos;
1515 const SfxStateCache *pSlaveCache =
1516 GetStateCache( pSlaveSlot->GetSlotId(), &nCurMsgPos );
1517
1518 // Ist der Slave-Slot gecached und dirty ?
1519 bInsert = pSlaveCache && pSlaveCache->IsControllerDirty();
1520
1521 // Slaves sind untereinander im Kreis verkettet
1522 if (pSlaveSlot->GetNextSlot() == pFirstSlave)
1523 break;
1524 }
1525 }
1526
1527 if ( bInsert && bSameMethod )
1528 {
1529 const SfxFoundCache_Impl *pFoundCache = new SfxFoundCache_Impl(
1530 pSibling->GetSlotId(), pSibling->GetWhich(rPool),
1531 pSibling, pSiblingCache );
1532
1533 rFound.Insert( pFoundCache );
1534 }
1535
1536 pSibling = pSibling->GetNextSlot();
1537 }
1538
1539 // aus den Ranges ein Set erzeugen
1540 sal_uInt16 *pRanges = new sal_uInt16[rFound.Count() * 2 + 1];
1541 int j = 0;
1542 sal_uInt16 i = 0;
1543 while ( i < rFound.Count() )
1544 {
1545 pRanges[j++] = rFound[i]->nWhichId;
1546 // aufeinanderfolgende Zahlen
1547 for ( ; i < rFound.Count()-1; ++i )
1548 if ( rFound[i]->nWhichId+1 != rFound[i+1]->nWhichId )
1549 break;
1550 pRanges[j++] = rFound[i++]->nWhichId;
1551 }
1552 pRanges[j] = 0; // terminierende NULL
1553 SfxItemSet *pSet = new SfxItemSet(rPool, pRanges);
1554 delete [] pRanges;
1555 DBG_PROFSTOP(SfxBindingsCreateSet);
1556 return pSet;
1557 }
1558
1559 //--------------------------------------------------------------------
1560
UpdateControllers_Impl(const SfxInterface * pIF,const SfxFoundCache_Impl * pFound,const SfxPoolItem * pItem,SfxItemState eState)1561 void SfxBindings::UpdateControllers_Impl
1562 (
1563 const SfxInterface* pIF, // das diese Id momentan bedienende Interface
1564 const SfxFoundCache_Impl* pFound, // Cache, Slot, Which etc.
1565 const SfxPoolItem* pItem, // item to send to controller
1566 SfxItemState eState // state of item
1567 )
1568 {
1569 DBG_ASSERT( !pFound->pSlot || SFX_KIND_ENUM != pFound->pSlot->GetKind(),
1570 "direct update of enum slot isn't allowed" );
1571 DBG_PROFSTART(SfxBindingsUpdateCtrl1);
1572
1573 SfxStateCache* pCache = pFound->pCache;
1574 const SfxSlot* pSlot = pFound->pSlot;
1575 DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" );
1576
1577 // insofern gebunden, die Controller f"uer den Slot selbst updaten
1578 if ( pCache && pCache->IsControllerDirty() )
1579 {
1580 if ( SFX_ITEM_DONTCARE == eState )
1581 {
1582 // uneindeuting
1583 pCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
1584 }
1585 else if ( SFX_ITEM_DEFAULT == eState &&
1586 pFound->nWhichId > SFX_WHICH_MAX )
1587 {
1588 // kein Status oder Default aber ohne Pool
1589 SfxVoidItem aVoid(0);
1590 pCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
1591 }
1592 else if ( SFX_ITEM_DISABLED == eState )
1593 pCache->SetState(SFX_ITEM_DISABLED, 0);
1594 else
1595 pCache->SetState(SFX_ITEM_AVAILABLE, pItem);
1596 }
1597
1598 DBG_PROFSTOP(SfxBindingsUpdateCtrl1);
1599
1600 // insofern vorhanden und gebunden, die Controller f"uer Slave-Slots
1601 // (Enum-Werte) des Slots updaten
1602 DBG_PROFSTART(SfxBindingsUpdateCtrl2);
1603 DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem ||
1604 pItem->ISA(SfxEnumItemInterface),
1605 "master slot with non-enum-type found" );
1606 const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0;
1607 if ( pIF && pFirstSlave)
1608 {
1609 // Items auf EnumItem casten
1610 const SfxEnumItemInterface *pEnumItem =
1611 PTR_CAST(SfxEnumItemInterface,pItem);
1612 if ( eState == SFX_ITEM_AVAILABLE && !pEnumItem )
1613 eState = SFX_ITEM_DONTCARE;
1614 else
1615 eState = SfxControllerItem::GetItemState( pEnumItem );
1616
1617 // "uber alle Slaves-Slots iterieren
1618 for ( const SfxSlot *pSlave = pFirstSlave; pSlave; pSlave = pSlave->GetNextSlot() )
1619 {
1620 DBG_ASSERT(pSlave, "Falsche SlaveSlot-Verkettung!");
1621 DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed");
1622 DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"falscher MasterSlot!");
1623
1624 // ist die Funktion gebunden?
1625 SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() );
1626 if ( pEnumCache )
1627 {
1628 pEnumCache->Invalidate(sal_False);
1629
1630 HACK(CONTROL/SELECT Kram)
1631 if ( eState == SFX_ITEM_DONTCARE && pFound->nWhichId == 10144 )
1632 {
1633 SfxVoidItem aVoid(0);
1634 pEnumCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
1635
1636 if (pSlave->GetNextSlot() == pFirstSlave)
1637 break;
1638
1639 continue;
1640 }
1641
1642 if ( SFX_ITEM_DISABLED == eState || !pEnumItem->IsEnabled( pSlave->GetSlotId()) )
1643 {
1644 // disabled
1645 pEnumCache->SetState(SFX_ITEM_DISABLED, 0);
1646 }
1647 else if ( SFX_ITEM_AVAILABLE == eState )
1648 {
1649 // enum-Wert ermitteln
1650 sal_uInt16 nValue = pEnumItem->GetEnumValue();
1651 SfxBoolItem aBool( pFound->nWhichId, pSlave->GetValue() == nValue );
1652 pEnumCache->SetState(SFX_ITEM_AVAILABLE, &aBool);
1653 }
1654 else
1655 {
1656 // uneindeuting
1657 pEnumCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
1658 }
1659 }
1660
1661 if (pSlave->GetNextSlot() == pFirstSlave)
1662 break;
1663 }
1664 }
1665
1666 DBG_PROFSTOP(SfxBindingsUpdateCtrl2);
1667 }
1668
1669
1670 //--------------------------------------------------------------------
1671
IMPL_LINK(SfxBindings,NextJob_Impl,Timer *,pTimer)1672 IMPL_LINK( SfxBindings, NextJob_Impl, Timer *, pTimer )
1673 {
1674 #ifdef DBG_UTIL
1675 // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT or another MS library
1676 // try to get them here
1677 try
1678 {
1679 #endif
1680 const unsigned MAX_INPUT_DELAY = 200;
1681
1682 DBG_MEMTEST();
1683 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1684
1685 DBG_PROFSTART(SfxBindingsNextJob_Impl0);
1686
1687 if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY && pTimer )
1688 {
1689 pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
1690 return sal_True;
1691 }
1692
1693 SfxApplication *pSfxApp = SFX_APP();
1694
1695 if( pDispatcher )
1696 pDispatcher->Update_Impl();
1697
1698 // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
1699 SfxViewFrame* pFrame = pDispatcher->GetFrame();
1700 //<!--Modified by PengYunQuan for Validity Cell Range Picker
1701 //if ( (pFrame && pFrame->GetObjectShell()->IsInModalMode()) || pSfxApp->IsDowning() || !pImp->pCaches->Count() )
1702 if ( (pFrame && !pFrame->GetObjectShell()->AcceptStateUpdate()) || pSfxApp->IsDowning() || !pImp->pCaches->Count() )
1703 //-->Modified by PengYunQuan for Validity Cell Range Picker
1704 {
1705 DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1706 return sal_True;
1707 }
1708 if ( !pDispatcher || !pDispatcher->IsFlushed() )
1709 {
1710 DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1711 return sal_True;
1712 }
1713
1714 // gfs. alle Server aktualisieren / geschieht in eigener Zeitscheibe
1715 if ( pImp->bMsgDirty )
1716 {
1717 UpdateSlotServer_Impl();
1718 DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1719 return sal_False;
1720 }
1721
1722 DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1723 DBG_PROFSTART(SfxBindingsNextJob_Impl);
1724 pImp->bAllDirty = sal_False;
1725 pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
1726
1727 // at least 10 loops and further if more jobs are available but no input
1728 bool bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule;
1729 sal_uInt16 nLoops = 10;
1730 pImp->bInNextJob = sal_True;
1731 const sal_uInt16 nCount = pImp->pCaches->Count();
1732 while ( pImp->nMsgPos < nCount )
1733 {
1734 // iterate through the bound functions
1735 sal_Bool bJobDone = sal_False;
1736 while ( !bJobDone )
1737 {
1738 SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos];
1739 DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
1740 sal_Bool bWasDirty = pCache->IsControllerDirty();
1741 if ( bWasDirty )
1742 {
1743 /*
1744 sal_Bool bSkip = sal_False;
1745 if ( pImp->bFirstRound )
1746 {
1747 // Falls beim Update eine Shell vorgezogen werden soll,
1748 // kommt in einer ersten Update-Runde nur diese dran
1749 const SfxSlotServer *pMsgServer =
1750 pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1751 if ( pMsgServer &&
1752 pMsgServer->GetShellLevel() != pImp->nFirstShell )
1753 bSkip = sal_True;
1754 }
1755
1756 if ( !bSkip )
1757 {
1758 */
1759 Update_Impl( pCache );
1760 DBG_ASSERT( nCount == pImp->pCaches->Count(),
1761 "Reschedule in StateChanged => buff" );
1762 // }
1763 }
1764
1765 // skip to next function binding
1766 ++pImp->nMsgPos;
1767
1768 // keep job if it is not completed, but any input is available
1769 bJobDone = pImp->nMsgPos >= nCount;
1770 if ( bJobDone && pImp->bFirstRound )
1771 {
1772 // Update der bevorzugten Shell ist gelaufen, nun d"urfen
1773 // auch die anderen
1774 bJobDone = sal_False;
1775 pImp->bFirstRound = sal_False;
1776 pImp->nMsgPos = 0;
1777 }
1778
1779 if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
1780 {
1781 DBG_PROFSTOP(SfxBindingsNextJob_Impl);
1782 pImp->bInNextJob = sal_False;
1783 return sal_False;
1784 }
1785 }
1786 }
1787
1788 pImp->nMsgPos = 0;
1789
1790 // check for volatile slots
1791 bool bVolatileSlotsPresent = false;
1792 for ( sal_uInt16 n = 0; n < nCount; ++n )
1793 {
1794 SfxStateCache* pCache = (*pImp->pCaches)[n];
1795 const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1796 if ( pSlotServer && pSlotServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) )
1797 {
1798 pCache->Invalidate(sal_False);
1799 bVolatileSlotsPresent = true;
1800 }
1801 }
1802
1803 if (bVolatileSlotsPresent)
1804 pImp->aTimer.SetTimeout(TIMEOUT_IDLE);
1805 else
1806 pImp->aTimer.Stop();
1807
1808 // Update-Runde ist beendet
1809 pImp->bInNextJob = sal_False;
1810 Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE));
1811 DBG_PROFSTOP(SfxBindingsNextJob_Impl);
1812 return sal_True;
1813 #ifdef DBG_UTIL
1814 }
1815 catch (...)
1816 {
1817 DBG_ERROR("C++ exception caught!");
1818 pImp->bInNextJob = sal_False;
1819 }
1820
1821 return sal_False;
1822 #endif
1823 }
1824
1825 //--------------------------------------------------------------------
1826
EnterRegistrations(const char * pFile,int nLine)1827 sal_uInt16 SfxBindings::EnterRegistrations(const char *pFile, int nLine)
1828 {
1829 (void)pFile;
1830 (void)nLine;
1831 DBG_MEMTEST();
1832 #ifdef DBG_UTIL
1833 ByteString aMsg;
1834 aMsg.Fill( Min(nRegLevel, sal_uInt16(8) ) );
1835 aMsg += "this = ";
1836 aMsg += ByteString::CreateFromInt32((long)this);
1837 aMsg += " Level = ";
1838 aMsg += ByteString::CreateFromInt32(nRegLevel);
1839 aMsg += " SfxBindings::EnterRegistrations ";
1840 if(pFile) {
1841 aMsg += "File: ";
1842 aMsg += pFile;
1843 aMsg += " Line: ";
1844 aMsg += ByteString::CreateFromInt32(nLine);
1845 }
1846 // FILE* pLog = fopen( "c:\\bindings.log", "a+w" );
1847 // fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog );
1848 // fclose( pLog );
1849 DbgTrace( aMsg.GetBuffer() );
1850 #endif
1851
1852 // Wenn Bindings gelockt werden, auch SubBindings locken
1853 if ( pImp->pSubBindings )
1854 {
1855 pImp->pSubBindings->ENTERREGISTRATIONS();
1856
1857 // Dieses EnterRegistrations ist f"ur die SubBindings kein "echtes"
1858 pImp->pSubBindings->pImp->nOwnRegLevel--;
1859
1860 // Bindings synchronisieren
1861 pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel + 1;
1862 }
1863
1864 pImp->nOwnRegLevel++;
1865
1866 // check if this is the outer most level
1867 if ( ++nRegLevel == 1 )
1868 {
1869 // stop background-processing
1870 pImp->aTimer.Stop();
1871
1872 // flush the cache
1873 pImp->nCachedFunc1 = 0;
1874 pImp->nCachedFunc2 = 0;
1875
1876 // merken, ob ganze Caches verschwunden sind
1877 pImp->bCtrlReleased = sal_False;
1878 }
1879
1880 return nRegLevel;
1881 }
1882 //--------------------------------------------------------------------
1883
LeaveRegistrations(sal_uInt16 nLevel,const char * pFile,int nLine)1884 void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel, const char *pFile, int nLine )
1885 {
1886 (void)nLevel; // unused variable
1887 (void)pFile;
1888 (void)nLine;
1889 DBG_MEMTEST();
1890 DBG_ASSERT( nRegLevel, "Leave without Enter" );
1891 DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" );
1892
1893 // Nur wenn die SubBindings noch von den SuperBindings gelockt sind, diesen Lock entfernen
1894 // ( d.h. wenn es mehr Locks als "echte" Locks dort gibt )
1895 if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel )
1896 {
1897 // Bindings synchronisieren
1898 pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel;
1899
1900 // Dieses LeaveRegistrations ist f"ur die SubBindings kein "echtes"
1901 pImp->pSubBindings->pImp->nOwnRegLevel++;
1902 pImp->pSubBindings->LEAVEREGISTRATIONS();
1903 }
1904
1905 pImp->nOwnRegLevel--;
1906
1907 // check if this is the outer most level
1908 if ( --nRegLevel == 0 && !SFX_APP()->IsDowning() )
1909 {
1910 if ( pImp->bContextChanged )
1911 {
1912 pImp->bContextChanged = sal_False;
1913 /*
1914 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
1915 ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1916 if ( xFrame.is() )
1917 xFrame->contextChanged();*/
1918 }
1919
1920 #ifndef slow
1921 SfxViewFrame* pFrame = pDispatcher->GetFrame();
1922
1923 // ggf unbenutzte Caches entfernen bzw. PlugInInfo aufbereiten
1924 if ( pImp->bCtrlReleased )
1925 {
1926 for ( sal_uInt16 nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
1927 {
1928 // Cache via ::com::sun::star::sdbcx::Index besorgen
1929 SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
1930
1931 // kein Controller mehr interessiert
1932 if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
1933 {
1934 // Cache entfernen. Safety: first remove and then delete
1935 SfxStateCache* pSfxStateCache = (*pImp->pCaches)[nCache-1];
1936 pImp->pCaches->Remove(nCache-1, 1);
1937 delete pSfxStateCache;
1938 }
1939 else
1940 {
1941 // neue Controller mit den alten Items benachrichtigen
1942 //!pCache->SetCachedState();
1943 }
1944 }
1945 }
1946 #endif
1947 // restart background-processing
1948 pImp->nMsgPos = 0;
1949 if ( !pFrame || !pFrame->GetObjectShell() )
1950 return;
1951 if ( pImp->pCaches && pImp->pCaches->Count() )
1952 {
1953 pImp->aTimer.Stop();
1954 pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
1955 pImp->aTimer.Start();
1956 // pImp->bFirstRound = sal_True;
1957 }
1958 }
1959
1960 #ifdef DBG_UTIL
1961 ByteString aMsg;
1962 aMsg.Fill( Min(nRegLevel, sal_uInt16(8)) );
1963 aMsg += "this = ";
1964 aMsg += ByteString::CreateFromInt32((long)this);
1965 aMsg += " Level = ";
1966 aMsg += ByteString::CreateFromInt32(nRegLevel);
1967 aMsg += " SfxBindings::LeaveRegistrations ";
1968 if(pFile) {
1969 aMsg += "File: ";
1970 aMsg += pFile;
1971 aMsg += " Line: ";
1972 aMsg += ByteString::CreateFromInt32(nLine);
1973 }
1974 // FILE* pLog = fopen( "c:\\bindings.log", "a+w" );
1975 // fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog );
1976 // fclose( pLog );
1977 DbgTrace( aMsg.GetBuffer() );
1978 #endif
1979 }
1980
1981 //--------------------------------------------------------------------
1982
GetSlot(sal_uInt16 nSlotId)1983 const SfxSlot* SfxBindings::GetSlot(sal_uInt16 nSlotId)
1984 {
1985 DBG_MEMTEST();
1986 DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1987
1988 // syncronisieren
1989 pDispatcher->Flush();
1990 if ( pImp->bMsgDirty )
1991 UpdateSlotServer_Impl();
1992
1993 // get the cache for the specified function; return if not bound
1994 SfxStateCache* pCache = GetStateCache(nSlotId);
1995 return pCache && pCache->GetSlotServer(*pDispatcher, pImp->xProv)?
1996 pCache->GetSlotServer(*pDispatcher, pImp->xProv)->GetSlot(): 0;
1997 }
1998
1999 //--------------------------------------------------------------------
2000
SetDispatcher(SfxDispatcher * pDisp)2001 void SfxBindings::SetDispatcher( SfxDispatcher *pDisp )
2002 {
2003 SfxDispatcher *pOldDispat = pDispatcher;
2004 if ( pDisp != pDispatcher )
2005 {
2006 if ( pOldDispat )
2007 {
2008 SfxBindings* pBind = pOldDispat->GetBindings();
2009 while ( pBind )
2010 {
2011 if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp )
2012 pBind->SetSubBindings_Impl( NULL );
2013 pBind = pBind->pImp->pSubBindings;
2014 }
2015 }
2016
2017 pDispatcher = pDisp;
2018
2019 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv;
2020 if ( pDisp )
2021 xProv = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider >
2022 ( pDisp->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
2023
2024 SetDispatchProvider_Impl( xProv );
2025 InvalidateAll( sal_True );
2026 InvalidateUnoControllers_Impl();
2027
2028 if ( pDispatcher && !pOldDispat )
2029 {
2030 if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
2031 {
2032 DBG_ERROR( "SubBindings vor Aktivieren schon gesetzt!" );
2033 pImp->pSubBindings->ENTERREGISTRATIONS();
2034 }
2035 LEAVEREGISTRATIONS();
2036 }
2037 else if( !pDispatcher )
2038 {
2039 ENTERREGISTRATIONS();
2040 if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
2041 {
2042 DBG_ERROR( "SubBindings im Deaktivieren immer noch gesetzt!" );
2043 pImp->pSubBindings->LEAVEREGISTRATIONS();
2044 }
2045 }
2046
2047 Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2048
2049 if ( pDisp )
2050 {
2051 SfxBindings* pBind = pDisp->GetBindings();
2052 while ( pBind && pBind != this )
2053 {
2054 if ( !pBind->pImp->pSubBindings )
2055 {
2056 pBind->SetSubBindings_Impl( this );
2057 break;
2058 }
2059
2060 pBind = pBind->pImp->pSubBindings;
2061 }
2062 }
2063 }
2064 }
2065
2066 //--------------------------------------------------------------------
2067
ClearCache_Impl(sal_uInt16 nSlotId)2068 void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId )
2069 {
2070 GetStateCache(nSlotId)->ClearCache();
2071 }
2072
2073 //--------------------------------------------------------------------
StartUpdate_Impl(sal_Bool bComplete)2074 void SfxBindings::StartUpdate_Impl( sal_Bool bComplete )
2075 {
2076 if ( pImp->pSubBindings )
2077 pImp->pSubBindings->StartUpdate_Impl( bComplete );
2078
2079 if ( !bComplete )
2080 // Update darf unterbrochen werden
2081 NextJob_Impl(&pImp->aTimer);
2082 else
2083 // alle Slots am St"uck updaten
2084 NextJob_Impl(0);
2085 }
2086
2087 //-------------------------------------------------------------------------
2088
QueryState(sal_uInt16 nSlot,SfxPoolItem * & rpState)2089 SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, SfxPoolItem* &rpState )
2090 {
2091 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
2092 SfxStateCache *pCache = GetStateCache( nSlot );
2093 if ( pCache )
2094 xDisp = pCache->GetDispatch();
2095 if ( xDisp.is() || !pCache )
2096 {
2097 const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pDispatcher->GetFrame() ).GetSlot( nSlot );
2098 if ( !pSlot || !pSlot->pUnoName )
2099 return SFX_ITEM_DISABLED;
2100
2101 ::com::sun::star::util::URL aURL;
2102 ::rtl::OUString aCmd( DEFINE_CONST_UNICODE(".uno:"));
2103 aURL.Protocol = aCmd;
2104 aURL.Path = ::rtl::OUString::createFromAscii(pSlot->GetUnoName());
2105 aCmd += aURL.Path;
2106 aURL.Complete = aCmd;
2107 aURL.Main = aCmd;
2108
2109 if ( !xDisp.is() )
2110 xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
2111
2112 if ( xDisp.is() )
2113 {
2114 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
2115 SfxOfficeDispatch* pDisp = NULL;
2116 if ( xTunnel.is() )
2117 {
2118 sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
2119 pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation ));
2120 }
2121
2122 if ( !pDisp )
2123 {
2124 sal_Bool bDeleteCache = sal_False;
2125 if ( !pCache )
2126 {
2127 pCache = new SfxStateCache( nSlot );
2128 pCache->GetSlotServer( *GetDispatcher_Impl(), pImp->xProv );
2129 bDeleteCache = sal_True;
2130 }
2131
2132 SfxItemState eState = SFX_ITEM_SET;
2133 SfxPoolItem *pItem=NULL;
2134 BindDispatch_Impl *pBind = new BindDispatch_Impl( xDisp, aURL, pCache, pSlot );
2135 pBind->acquire();
2136 xDisp->addStatusListener( pBind, aURL );
2137 if ( !pBind->GetStatus().IsEnabled )
2138 {
2139 eState = SFX_ITEM_DISABLED;
2140 }
2141 else
2142 {
2143 ::com::sun::star::uno::Any aAny = pBind->GetStatus().State;
2144 ::com::sun::star::uno::Type pType = aAny.getValueType();
2145
2146 if ( pType == ::getBooleanCppuType() )
2147 {
2148 sal_Bool bTemp = false;
2149 aAny >>= bTemp ;
2150 pItem = new SfxBoolItem( nSlot, bTemp );
2151 }
2152 else if ( pType == ::getCppuType((const sal_uInt16*)0) )
2153 {
2154 sal_uInt16 nTemp = 0;
2155 aAny >>= nTemp ;
2156 pItem = new SfxUInt16Item( nSlot, nTemp );
2157 }
2158 else if ( pType == ::getCppuType((const sal_uInt32*)0) )
2159 {
2160 sal_uInt32 nTemp = 0;
2161 aAny >>= nTemp ;
2162 pItem = new SfxUInt32Item( nSlot, nTemp );
2163 }
2164 else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
2165 {
2166 ::rtl::OUString sTemp ;
2167 aAny >>= sTemp ;
2168 pItem = new SfxStringItem( nSlot, sTemp );
2169 }
2170 else
2171 pItem = new SfxVoidItem( nSlot );
2172 }
2173
2174 xDisp->removeStatusListener( pBind, aURL );
2175 pBind->Release();
2176 rpState = pItem;
2177 if ( bDeleteCache )
2178 DELETEZ( pCache );
2179 return eState;
2180 }
2181 }
2182 }
2183
2184 // Dann am Dispatcher testen; da die von dort zur"uckgegebenen Items immer
2185 // DELETE_ON_IDLE sind, mu\s eine Kopie davon gezogen werden, um einen
2186 // Eigent"umer"ubergang zu erm"oglichen
2187 const SfxPoolItem *pItem = NULL;
2188 SfxItemState eState = pDispatcher->QueryState( nSlot, pItem );
2189 if ( eState == SFX_ITEM_SET )
2190 {
2191 DBG_ASSERT( pItem, "SFX_ITEM_SET aber kein Item!" );
2192 if ( pItem )
2193 rpState = pItem->Clone();
2194 }
2195 else if ( eState == SFX_ITEM_AVAILABLE && pItem )
2196 {
2197 rpState = pItem->Clone();
2198 }
2199
2200 return eState;
2201 }
2202
SetSubBindings_Impl(SfxBindings * pSub)2203 void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub )
2204 {
2205 if ( pImp->pSubBindings )
2206 {
2207 pImp->pSubBindings->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () );
2208 pImp->pSubBindings->pImp->pSuperBindings = NULL;
2209 }
2210
2211 pImp->pSubBindings = pSub;
2212
2213 if ( pSub )
2214 {
2215 pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
2216 pSub->pImp->pSuperBindings = this;
2217 }
2218 }
2219
GetSubBindings_Impl(sal_Bool bTop) const2220 SfxBindings* SfxBindings::GetSubBindings_Impl( sal_Bool bTop ) const
2221 {
2222 SfxBindings *pRet = pImp->pSubBindings;
2223 if ( bTop )
2224 {
2225 while ( pRet->pImp->pSubBindings )
2226 pRet = pRet->pImp->pSubBindings;
2227 }
2228
2229 return pRet;
2230 }
2231
SetWorkWindow_Impl(SfxWorkWindow * pWork)2232 void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork )
2233 {
2234 pImp->pWorkWin = pWork;
2235 }
2236
GetWorkWindow_Impl() const2237 SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const
2238 {
2239 return pImp->pWorkWin;
2240 }
2241
RegisterUnoController_Impl(SfxUnoControllerItem * pControl)2242 void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl )
2243 {
2244 if ( !pImp->pUnoCtrlArr )
2245 pImp->pUnoCtrlArr = new SfxUnoControllerArr_Impl;
2246 pImp->pUnoCtrlArr->Insert( pControl, pImp->pUnoCtrlArr->Count() );
2247 }
2248
ReleaseUnoController_Impl(SfxUnoControllerItem * pControl)2249 void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl )
2250 {
2251 if ( pImp->pUnoCtrlArr )
2252 {
2253 sal_uInt16 nPos = pImp->pUnoCtrlArr->GetPos( pControl );
2254 if ( nPos != 0xFFFF )
2255 {
2256 pImp->pUnoCtrlArr->Remove( nPos );
2257 return;
2258 }
2259 }
2260
2261 if ( pImp->pSubBindings )
2262 pImp->pSubBindings->ReleaseUnoController_Impl( pControl );
2263 }
2264
InvalidateUnoControllers_Impl()2265 void SfxBindings::InvalidateUnoControllers_Impl()
2266 {
2267 if ( pImp->pUnoCtrlArr )
2268 {
2269 sal_uInt16 nCount = pImp->pUnoCtrlArr->Count();
2270 for ( sal_uInt16 n=nCount; n>0; n-- )
2271 {
2272 SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
2273 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > xRef( (::cppu::OWeakObject*)pCtrl, ::com::sun::star::uno::UNO_QUERY );
2274 pCtrl->ReleaseDispatch();
2275 pCtrl->GetNewDispatch();
2276 }
2277 }
2278
2279 if ( pImp->pSubBindings )
2280 pImp->pSubBindings->InvalidateUnoControllers_Impl();
2281 }
2282
IsInUpdate() const2283 sal_Bool SfxBindings::IsInUpdate() const
2284 {
2285 sal_Bool bInUpdate = pImp->bInUpdate;
2286 if ( !bInUpdate && pImp->pSubBindings )
2287 bInUpdate = pImp->pSubBindings->IsInUpdate();
2288 return bInUpdate;
2289 }
2290
SetVisibleState(sal_uInt16 nId,sal_Bool bShow)2291 void SfxBindings::SetVisibleState( sal_uInt16 nId, sal_Bool bShow )
2292 {
2293 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
2294 SfxStateCache *pCache = GetStateCache( nId );
2295 if ( pCache )
2296 pCache->SetVisibleState( bShow );
2297 }
2298
SetActiveFrame(const::com::sun::star::uno::Reference<::com::sun::star::frame::XFrame> & rFrame)2299 void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
2300 {
2301 if ( rFrame.is() || !pDispatcher )
2302 SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) );
2303 else
2304 SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > (
2305 pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ) );
2306 }
2307
GetActiveFrame() const2308 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxBindings::GetActiveFrame() const
2309 {
2310 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( pImp->xProv, ::com::sun::star::uno::UNO_QUERY );
2311 if ( xFrame.is() || !pDispatcher )
2312 return xFrame;
2313 else
2314 return pDispatcher->GetFrame()->GetFrame().GetFrameInterface();
2315 }
2316
SetDispatchProvider_Impl(const::com::sun::star::uno::Reference<::com::sun::star::frame::XDispatchProvider> & rProv)2317 void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv )
2318 {
2319 sal_Bool bInvalidate = ( rProv != pImp->xProv );
2320 if ( bInvalidate )
2321 {
2322 pImp->xProv = rProv;
2323 InvalidateAll( sal_True );
2324 InvalidateUnoControllers_Impl();
2325 }
2326
2327 if ( pImp->pSubBindings )
2328 pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
2329 }
2330
GetDispatchProvider_Impl() const2331 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & SfxBindings::GetDispatchProvider_Impl() const
2332 {
2333 return pImp->xProv;
2334 }
2335
GetSystemWindow() const2336 SystemWindow* SfxBindings::GetSystemWindow() const
2337 {
2338 SfxViewFrame *pFrame = pDispatcher->GetFrame();
2339 while ( pFrame->GetParentViewFrame_Impl() )
2340 pFrame = pFrame->GetParentViewFrame_Impl();
2341 SfxViewFrame* pTop = pFrame->GetTopViewFrame();
2342 return pTop->GetFrame().GetTopWindow_Impl();
2343 }
2344
ExecuteCommand_Impl(const String & rCommand)2345 sal_Bool SfxBindings::ExecuteCommand_Impl( const String& rCommand )
2346 {
2347 ::com::sun::star::util::URL aURL;
2348 aURL.Complete = rCommand;
2349 Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
2350 xTrans->parseStrict( aURL );
2351 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
2352 if ( xDisp.is() )
2353 {
2354 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
2355 {
2356 ::rtl::OUString sAppName;
2357 try
2358 {
2359 static ::rtl::OUString our_aModuleManagerName = ::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager");
2360 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager =
2361 ::comphelper::getProcessServiceFactory();
2362 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > xModuleManager(
2363 xServiceManager->createInstance(our_aModuleManagerName)
2364 , ::com::sun::star::uno::UNO_QUERY_THROW);
2365 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame(
2366 pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY_THROW);
2367 sAppName = xModuleManager->identify(xFrame);
2368 } catch(::com::sun::star::uno::Exception&) {}
2369 Sequence<beans::PropertyValue> source;
2370 ::comphelper::UiEventsLogger::appendDispatchOrigin(source, sAppName, ::rtl::OUString::createFromAscii("SfxAsyncExec"));
2371 ::comphelper::UiEventsLogger::logDispatch(aURL, source);
2372 }
2373 new SfxAsyncExec_Impl( aURL, xDisp );
2374 return sal_True;
2375 }
2376
2377 return sal_False;
2378 }
2379
GetRecorder() const2380 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxBindings::GetRecorder() const
2381 {
2382 return pImp->xRecorder;
2383 }
2384
SetRecorder_Impl(com::sun::star::uno::Reference<com::sun::star::frame::XDispatchRecorder> & rRecorder)2385 void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder >& rRecorder )
2386 {
2387 pImp->xRecorder = rRecorder;
2388 }
2389
ContextChanged_Impl()2390 void SfxBindings::ContextChanged_Impl()
2391 {
2392 if ( !pImp->bInUpdate && ( !pImp->bContextChanged || !pImp->bAllMsgDirty ) )
2393 {
2394 InvalidateAll( sal_True );
2395 }
2396 }
2397
GetDispatch(const SfxSlot * pSlot,const util::URL & aURL,sal_Bool bMasterCommand)2398 uno::Reference < frame::XDispatch > SfxBindings::GetDispatch( const SfxSlot* pSlot, const util::URL& aURL, sal_Bool bMasterCommand )
2399 {
2400 uno::Reference < frame::XDispatch > xRet;
2401 SfxStateCache* pCache = GetStateCache( pSlot->nSlotId );
2402 if ( pCache && !bMasterCommand )
2403 xRet = pCache->GetInternalDispatch();
2404 if ( !xRet.is() )
2405 {
2406 // dispatches for slaves are unbound, they don't have a state
2407 SfxOfficeDispatch* pDispatch = bMasterCommand ?
2408 new SfxOfficeDispatch( pDispatcher, pSlot, aURL ) :
2409 new SfxOfficeDispatch( *this, pDispatcher, pSlot, aURL );
2410
2411 pDispatch->SetMasterUnoCommand( bMasterCommand );
2412 xRet = uno::Reference < frame::XDispatch >( pDispatch );
2413 if ( !pCache )
2414 pCache = GetStateCache( pSlot->nSlotId );
2415
2416 DBG_ASSERT( pCache, "No cache for OfficeDispatch!" );
2417 if ( pCache && !bMasterCommand )
2418 pCache->SetInternalDispatch( xRet );
2419 }
2420
2421 return xRet;
2422 }
2423