Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / control / dispatch.cxx
blob3e10fff6be1f450e6d3ddbb93832f4be033b6ca5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
22 #include <com/sun/star/frame/XLayoutManager.hpp>
23 #include <svl/itempool.hxx>
24 #include <svl/itemiter.hxx>
25 #include <svl/whiter.hxx>
26 #include <svl/intitem.hxx>
27 #include <svl/eitem.hxx>
28 #include <svl/undo.hxx>
29 #include <vcl/wrkwin.hxx>
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <stdlib.h> // due to bsearch
33 #include <algorithm>
35 #include <svtools/helpopt.hxx>
37 // due to nAutoPageID
38 #include "appdata.hxx"
39 #include "sfx2/sfxhelp.hxx"
40 #include <sfx2/dispatch.hxx>
41 #include <sfx2/msg.hxx>
42 #include <sfx2/objface.hxx>
43 #include <sfx2/bindings.hxx>
44 #include <sfx2/request.hxx>
45 #include <sfx2/app.hxx>
46 #include <sfx2/hintpost.hxx>
47 #include "slotserv.hxx"
48 #include <sfx2/ipclient.hxx>
49 #include "sfxtypes.hxx"
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/viewsh.hxx>
52 #include <sfx2/childwin.hxx>
53 #include <sfx2/docfac.hxx>
54 #include <sfx2/msgpool.hxx>
55 #include <sfx2/module.hxx>
56 #include <sfx2/sfxuno.hxx>
57 #include <sfx2/docfile.hxx>
58 #include <sfx2/mnumgr.hxx>
59 #include "workwin.hxx"
60 #include <rtl/strbuf.hxx>
62 #include <deque>
63 #include <vector>
65 DBG_NAME(SfxDispatcherFlush)
66 DBG_NAME(SfxDispatcherFillState)
68 typedef std::vector<SfxRequest*> SfxRequestPtrArray;
70 struct SfxObjectBars_Impl
72 sal_uInt32 nResId; // Resource - and ConfigId of the Toolbox
73 sal_uInt16 nMode; // special visibility flags
74 String aName;
75 SfxInterface* pIFace;
77 SfxObjectBars_Impl() : nResId(0), nMode(0), pIFace(NULL) {}
80 //------------------------------------------------------------------
82 struct SfxDispatcher_Impl
84 //When the dispatched is locked, SfxRequests accumulate in aReqArr for
85 //later dispatch when unlocked via Post
87 //The pointers are typically deleted in Post, only if we never get around
88 //to posting them do we delete the unposted requests.
89 SfxRequestPtrArray aReqArr;
90 ~SfxDispatcher_Impl()
92 for (SfxRequestPtrArray::iterator aI = aReqArr.begin(), aEnd = aReqArr.end(); aI != aEnd; ++aI)
93 delete *aI;
95 const SfxSlotServer* pCachedServ1; // last called message
96 const SfxSlotServer* pCachedServ2; // penultimate called Message
97 SfxShellStack_Impl aStack; // active functionality
98 Timer aTimer; // for Flush
99 std::deque<SfxToDo_Impl> aToDoStack; // not processed Push/Pop
100 SfxViewFrame* pFrame; // NULL or associated Frame
101 SfxDispatcher* pParent; // AppDispatcher, NULL if possible
102 SfxHintPosterRef xPoster; // Execute asynchronous
103 sal_Bool bFlushing; // sal_True during Flush //?
104 sal_Bool bUpdated; // Update_Impl has run
105 sal_Bool bLocked; // No Execute
106 sal_Bool bInvalidateOnUnlock; // because someone asked
107 sal_Bool bActive; // not to be confused with set!
108 sal_Bool* pInCallAliveFlag; // view the Destructor Stack
109 SfxObjectBars_Impl aObjBars[SFX_OBJECTBAR_MAX];
110 SfxObjectBars_Impl aFixedObjBars[SFX_OBJECTBAR_MAX];
111 std::vector<sal_uInt32> aChildWins;
112 sal_uInt32 nEventId; // EventId UserEvent
113 sal_Bool bNoUI; // UI only from Parent Dispatcher
114 sal_Bool bReadOnly; // Document is ReadOnly
115 sal_Bool bQuiet; // Only use parent dispatcher
116 sal_Bool bModal; // Only slots from parent dispatcher
118 sal_Bool bFilterEnabling; // sal_True=filter enabled slots,
119 // 2==ReadOnlyDoc overturned
120 sal_uInt16 nFilterCount; // Number of SIDs in pFilterSIDs
121 const sal_uInt16* pFilterSIDs; // sorted Array of SIDs
122 sal_uInt32 nDisableFlags;
125 //------------------------------------------------------------------
127 #define SFX_FLUSH_TIMEOUT 50
129 //====================================================================
130 sal_Bool SfxDispatcher::IsLocked( sal_uInt16 ) const
132 /* [Description]
134 With this method it can be determined whether the SfxDispatcher is
135 locked or unlocked. A locked SfxDispatcher does not perform <SfxRequest>s
136 and no longer provides any status information. It behaves as if all the
137 slots are disabled.
139 The dispatcher is also marked as blocked, if all Dispatcher are locked
140 (<SfxApplication::LockDispatcher()>) or the associated top frame is in the
141 modal-mode and if the specified slot are handled as frame-specific
142 (ie, not served by the application).
146 return pImp->bLocked;
149 //--------------------------------------------------------------------
150 sal_Bool SfxDispatcher::IsAppDispatcher() const
152 /* [Description]
154 With this method it can be determined if the SfxDispacher is the
155 applications dispatcher.
157 [Return value]
159 sal_Bool sal_True it is the application dispatcher.
160 sal_Fals it is a SfxViewFrame dispatcher.
164 return !pImp->pFrame;
167 //--------------------------------------------------------------------
168 int SfxDispatcher::Call_Impl( SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, sal_Bool bRecord )
170 /* [Description]
172 Helper function to check whether a slot can be executed and
173 check the execution itself
177 SFX_STACK(SfxDispatcher::Call_Impl);
179 // The slot may be called (meaning enabled)
180 if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
182 if ( GetFrame() )
184 // Recording may start
185 com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame(
186 GetFrame()->GetFrame().GetFrameInterface(),
187 com::sun::star::uno::UNO_QUERY);
189 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
190 xFrame,
191 com::sun::star::uno::UNO_QUERY);
193 if ( xSet.is() )
195 com::sun::star::uno::Any aProp = xSet->getPropertyValue(OUString("DispatchRecorderSupplier"));
196 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
197 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
198 aProp >>= xSupplier;
199 if(xSupplier.is())
200 xRecorder = xSupplier->getDispatchRecorder();
202 if ( bRecord && xRecorder.is() && !rSlot.IsMode(SFX_SLOT_NORECORD) )
203 rReq.Record_Impl( rShell, rSlot, xRecorder, GetFrame() );
206 // Get all that is needed, because the slot may not have survived the
207 // Execute if it is a 'pseudo slot' for macros or verbs.
208 sal_Bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
210 // API-call parentheses and document-lock during the calls
212 // 'this' must respond in the Destructor
213 sal_Bool bThisDispatcherAlive = sal_True;
214 sal_Bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
215 pImp->pInCallAliveFlag = &bThisDispatcherAlive;
217 SfxExecFunc pFunc = rSlot.GetExecFnc();
218 rShell.CallExec( pFunc, rReq );
220 // If 'this' is still alive
221 if ( bThisDispatcherAlive )
222 pImp->pInCallAliveFlag = pOldInCallAliveFlag;
223 else
225 if ( pOldInCallAliveFlag )
227 // also protect nested stack frames
228 *pOldInCallAliveFlag = sal_False;
231 // do nothing after this object is dead
232 return rReq.IsDone();
236 if ( rReq.IsDone() )
238 SfxBindings *pBindings = GetBindings();
240 // When AutoUpdate update immediately; "Pseudoslots" must not be
241 // Autoupdate!
242 if ( bAutoUpdate && pBindings )
244 const SfxSlot* pSlave = rSlot.GetLinkedSlot();
245 if (pSlave)
247 // When enum slots take any bound slave slot
248 while (!pBindings->IsBound(pSlave->GetSlotId()) && pSlave != &rSlot )
249 pSlave = pSlave->GetLinkedSlot();
250 pBindings->Invalidate(pSlave->GetSlotId());
251 pBindings->Update(pSlave->GetSlotId());
253 else
255 pBindings->Invalidate(rSlot.GetSlotId());
256 pBindings->Update(rSlot.GetSlotId());
260 return sal_True;
264 return sal_False;
267 //====================================================================
268 void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
270 pImp = new SfxDispatcher_Impl;
271 bFlushed = sal_True;
273 pImp->pCachedServ1 = 0;
274 pImp->pCachedServ2 = 0;
275 pImp->bFlushing = sal_False;
276 pImp->bUpdated = sal_False;
277 pImp->bLocked = sal_False;
278 pImp->bActive = sal_False;
279 pImp->pParent = NULL;
280 pImp->bNoUI = sal_False;
281 pImp->bReadOnly = sal_False;
282 pImp->bQuiet = sal_False;
283 pImp->bModal = sal_False;
284 pImp->pInCallAliveFlag = 0;
285 pImp->bFilterEnabling = sal_False;
286 pImp->nFilterCount = 0;
287 pImp->pFilterSIDs = 0;
288 pImp->nDisableFlags = 0;
290 pImp->pParent = pParent;
292 pImp->bInvalidateOnUnlock = sal_False;
294 for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
295 pImp->aObjBars[n].nResId = 0;
297 GenLink aGenLink( LINK(this, SfxDispatcher, PostMsgHandler) );
299 pImp->xPoster = new SfxHintPoster(aGenLink);
301 pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
302 pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
305 SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
307 Construct_Impl( pParent );
308 pImp->pFrame = 0;
311 SfxDispatcher::SfxDispatcher( SfxViewFrame *pViewFrame )
313 /* [Description]
315 The constructor of the SfxDispatcher class places a stack of empty
316 <SfxShell> pointers. It is not initially locked and is considered flushed.
320 if ( pViewFrame )
322 SfxViewFrame *pFrame = pViewFrame->GetParentViewFrame();
323 if ( pFrame )
324 Construct_Impl( pFrame->GetDispatcher() );
325 else
326 Construct_Impl( 0 );
328 else
329 Construct_Impl( 0 );
330 pImp->pFrame = pViewFrame;
333 //====================================================================
334 SfxDispatcher::~SfxDispatcher()
336 /* [Description]
338 The destructor of the SfxDispatcher class should not be called when the
339 SfxDispatcher instance is active. It may, however, still be a <SfxShell>
340 pointer on the stack.
344 #ifdef DBG_UTIL
345 OStringBuffer sTemp(RTL_CONSTASCII_STRINGPARAM("Delete Dispatcher "));
346 sTemp.append(reinterpret_cast<sal_Int64>(this));
347 OSL_TRACE("%s", sTemp.getStr());
348 DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
349 #endif
351 // So that no timer by Reschedule in PlugComm strikes the LeaveRegistrations
352 pImp->aTimer.Stop();
353 pImp->xPoster->SetEventHdl( Link() );
355 // Notify the stack varialbles in Call_Impl
356 if ( pImp->pInCallAliveFlag )
357 *pImp->pInCallAliveFlag = sal_False;
359 // Get bindings and application
360 SfxApplication *pSfxApp = SFX_APP();
361 SfxBindings* pBindings = GetBindings();
363 // When not flushed, revive the bindings
364 if ( pBindings && !pSfxApp->IsDowning() && !bFlushed )
365 pBindings->DLEAVEREGISTRATIONS();
367 // may unregister the bindings
368 while ( pBindings )
370 if ( pBindings->GetDispatcher_Impl() == this)
371 pBindings->SetDispatcher(0);
372 pBindings = pBindings->GetSubBindings_Impl();
375 delete pImp;
378 //====================================================================
379 void SfxDispatcher::Pop
381 SfxShell& rShell, /* the stack to take the SfxShell instance. */
383 sal_uInt16 nMode /* SFX_SHELL_POP_UNTIL
384 Also all 'rShell' of SfxShells are taken from the
385 stack.
387 SFX_SHELL_POP_DELETE
388 All SfxShells actually taken from the stack
389 will be deleted.
391 SFX_SHELL_PUSH (InPlace use only)
392 The Shell is pushed. */
394 /* [Description]
396 With this method, one or more <SfxShell> are poped from the SfxDispatcher.
397 The SfxShell is marked for popping and a timer is set up. Only when the
398 timer has reached the end, the pop is actually performed
399 ( <SfxDispatcher::Flush()> ) and the <SfxBindings> is invalidated.
400 While the timer is running the opposing push and pop commands on one
401 SfxShell cancel each other out.
405 DBG_ASSERT( rShell.GetInterface(),
406 "pushing SfxShell without previous RegisterInterface()" );
408 bool bDelete = (nMode & SFX_SHELL_POP_DELETE) == SFX_SHELL_POP_DELETE;
409 bool bUntil = (nMode & SFX_SHELL_POP_UNTIL) == SFX_SHELL_POP_UNTIL;
410 bool bPush = (nMode & SFX_SHELL_PUSH) == SFX_SHELL_PUSH;
412 SfxApplication *pSfxApp = SFX_APP();
414 SAL_INFO(
415 "sfx2.control",
416 "-SfxDispatcher(" << this << (bPush ? ")::Push(" : ")::Pop(")
417 << (rShell.GetInterface()
418 ? rShell.GetInterface()->GetClassName() : SAL_STREAM(&rShell))
419 << (bDelete ? ") with delete" : ")")
420 << (bUntil ? " (up to)" : ""));
422 // same shell as on top of the to-do stack?
423 if(pImp->aToDoStack.size() && pImp->aToDoStack.front().pCluster == &rShell)
425 // cancel inverse actions
426 if ( pImp->aToDoStack.front().bPush != bPush )
427 pImp->aToDoStack.pop_front();
428 else
430 DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
431 DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
434 else
436 // Remember ::com::sun::star::chaos::Action
437 pImp->aToDoStack.push_front( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
438 if ( bFlushed )
440 OSL_TRACE("Unflushed dispatcher!");
441 bFlushed = sal_False;
442 pImp->bUpdated = sal_False;
444 // Put bindings to sleep
445 SfxBindings* pBindings = GetBindings();
446 if ( pBindings )
447 pBindings->DENTERREGISTRATIONS();
451 if(!pSfxApp->IsDowning() && !pImp->aToDoStack.empty())
453 // No immediate update is requested
454 pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
455 pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
456 pImp->aTimer.Start();
458 else
460 // but to do nothing
461 pImp->aTimer.Stop();
463 // Bindings may wake up again
464 if(pImp->aToDoStack.empty())
466 SfxBindings* pBindings = GetBindings();
467 if ( pBindings )
468 pBindings->DLEAVEREGISTRATIONS();
473 //--------------------------------------------------------------------
475 IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
477 /* [Description]
479 This handler is called after <SfxDispatcher::Invalidate()> or after
480 changes on the stack (<SfxDispatcher::Push()> and <SfxDispatcher::Pop())
482 It flushes the Stack, if it is dirty, thus it actually excecutes the
483 pending Push and Pop commands.
487 (void)pvoid; // unused
489 Flush();
490 Update_Impl();
491 SfxBindings* pBindings = GetBindings();
492 if ( pBindings )
493 pBindings->StartUpdate_Impl(sal_False);
494 return 0;
496 IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
498 //--------------------------------------------------------------------
499 sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDeep )
501 /* [Description]
503 With this method it can be tested whether the <SfxShell> rShell is on the
504 stack, when it was flushed. This way the SfxDispatcher is not actually
505 flushed.
507 This method is intended among other things to make assertions possible
508 without the side effect of having to flush the SfxDispathcer.
512 SFX_STACK(SfxDispatcher::CheckVirtualStack);
514 SfxShellStack_Impl aStack( pImp->aStack );
515 for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
517 if(i->bPush)
518 aStack.push_back(i->pCluster);
519 else
521 SfxShell* pPopped(NULL);
524 DBG_ASSERT( !aStack.empty(), "popping from empty stack" );
525 pPopped = aStack.back();
526 aStack.pop_back();
528 while(i->bUntil && pPopped != i->pCluster);
529 DBG_ASSERT(pPopped == i->pCluster, "popping unpushed SfxInterface");
533 sal_Bool bReturn;
534 if ( bDeep )
535 bReturn = std::find(aStack.begin(), aStack.end(), &rShell) != aStack.end();
536 else
537 bReturn = aStack.back() == &rShell;
538 return bReturn;
541 //--------------------------------------------------------------------
542 sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
544 /* [Description]
546 Determines the position of a given SfxShell in the stack of the dispatcher.
547 If possible this is flushed before.
549 [Return value]
551 sal_uInt16 == USRT_MAX
552 The SfxShell is not on this SfxDispatcher.
554 < USHRT_MAX
555 Position of the SfxShell on the Dispatcher
556 from the top count stating with 0.
560 SFX_STACK(SfxDispatcher::GetShellLevel);
561 Flush();
563 for ( sal_uInt16 n = 0; n < pImp->aStack.size(); ++n )
564 if ( *( pImp->aStack.rbegin() + n ) == &rShell )
565 return n;
566 if ( pImp->pParent )
568 sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
569 if ( nRet == USHRT_MAX )
570 return nRet;
571 return nRet + pImp->aStack.size();
574 return USHRT_MAX;
577 //--------------------------------------------------------------------
578 SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
580 /* [Description]
582 Returns a pointer to the <SfxShell> which is at the position nIdx
583 (from the top, last pushed is 0) on the stack.
585 Thus the SfxDispatcher is not flushed.
587 Is the stack not deep enough a NULL-Pointer is returned.
591 sal_uInt16 nShellCount = pImp->aStack.size();
592 if ( nIdx < nShellCount )
593 return *(pImp->aStack.rbegin() + nIdx);
594 else if ( pImp->pParent )
595 return pImp->pParent->GetShell( nIdx - nShellCount );
596 return 0;
599 //--------------------------------------------------------------------
600 SfxBindings* SfxDispatcher::GetBindings() const
602 /* [Description]
604 This method returns a pointer to the <SfxBinding> Instance on which the
605 SfxDispatcher is curretly bound. A SfxDispatcher is only bound to
606 the SfxBindings when it is <UI-aktiv>. If it is not UI-active,
607 a NULL-pointer is returned.
609 The returned pointer is only valid in the immediate context of the method
610 call.
614 if ( pImp->pFrame )
615 return &pImp->pFrame->GetBindings();
616 else
617 return NULL;
620 //--------------------------------------------------------------------
621 SfxViewFrame* SfxDispatcher::GetFrame() const
623 /* [Description]
625 Returns a pointer to the <SfxViewFrame> instance, which belongs to
626 this SfxDispatcher. If it is about the application dispatcher,
627 a NULL-pointer is returned.
631 return pImp->pFrame;
634 //--------------------------------------------------------------------
635 void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ )
637 /* [Description]
639 This method controls the activation of a dispatcher.
641 Since the application dispatcher is always active, either as a sub
642 dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
643 activated as a whole, instead only its individual <SfxShell>s at
644 <SfxDispatcher::Push(SfxShell&)>.
646 When activating a SfxDispatcher all of the SfxShells located on its stack
647 are called with the handler <SfxShell::Activate(sal_Bool)>, starting with
648 the lowest.
652 SFX_STACK(SfxDispatcher::DoActivate);
653 if ( bMDI )
655 #ifdef DBG_UTIL
656 OStringBuffer sTemp(
657 RTL_CONSTASCII_STRINGPARAM("Activate Dispatcher "));
658 sTemp.append(reinterpret_cast<sal_Int64>(this));
659 OSL_TRACE("%s", sTemp.getStr());
660 DBG_ASSERT( !pImp->bActive, "Activation error" );
661 #endif
662 pImp->bActive = sal_True;
663 pImp->bUpdated = sal_False;
664 SfxBindings* pBindings = GetBindings();
665 if ( pBindings )
667 pBindings->SetDispatcher(this);
668 pBindings->SetActiveFrame( pImp->pFrame->GetFrame().GetFrameInterface() );
671 else
673 #ifdef DBG_UTIL
674 OStringBuffer sTemp(
675 RTL_CONSTASCII_STRINGPARAM("Non-MDI-Activate Dispatcher"));
676 sTemp.append(reinterpret_cast<sal_Int64>(this));
677 OSL_TRACE("%s", sTemp.getStr());
678 #endif
681 if ( IsAppDispatcher() )
682 return;
684 for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
685 (*(pImp->aStack.rbegin() + i ))->DoActivate_Impl(pImp->pFrame, bMDI);
687 if ( bMDI && pImp->pFrame )
689 SfxBindings *pBind = GetBindings();
690 while ( pBind )
692 pBind->HidePopupCtrls_Impl( sal_False );
693 pBind = pBind->GetSubBindings_Impl();
696 pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( sal_False, sal_False, 1 );
699 if(!pImp->aToDoStack.empty())
701 // No immediate update is requested
702 pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
703 pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
704 pImp->aTimer.Start();
708 void SfxDispatcher::DoParentActivate_Impl()
710 for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
711 (*(pImp->aStack.rbegin() + i ))->ParentActivate();
714 //--------------------------------------------------------------------
715 void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew )
717 /* [Description]
719 This method controls the deactivation of a dispatcher.
721 Since the application dispatcher is always active, either as a sub
722 dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
723 deactivated as a whole, instead only its individual <SfxShell>s at
724 <SfxDispatcher::Pop(SfxShell&)>.
726 When deactivating a SfxDispatcher all of the SfxShells located on its stack
727 are called with the handler <SfxShell::Deactivate(sal_Bool)>, starting with
728 the lowest.
732 SFX_STACK(SfxDispatcher::DoDeactivate);
734 SfxApplication *pSfxApp = SFX_APP();
736 if ( bMDI )
738 OSL_TRACE(OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Deactivate Dispatcher")).append(reinterpret_cast<sal_Int64>(this)).getStr());
739 DBG_ASSERT( pImp->bActive, "Deactivate error" );
740 pImp->bActive = sal_False;
742 if ( pImp->pFrame && !(pImp->pFrame->GetObjectShell()->IsInPlaceActive() ) )
744 SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
745 if ( pWorkWin )
747 for (size_t n=0; n<pImp->aChildWins.size();)
749 SfxChildWindow *pWin = pWorkWin->GetChildWindow_Impl( (sal_uInt16) ( pImp->aChildWins[n] & 0xFFFF ) );
750 if (!pWin || (pWin && pWin->GetAlignment() == SFX_ALIGN_NOALIGNMENT))
751 pImp->aChildWins.erase(pImp->aChildWins.begin()+n);
752 else
753 n++;
758 else {
759 OSL_TRACE(OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Non-MDI-DeActivate Dispatcher")).append(reinterpret_cast<sal_Int64>(this)).getStr());
762 if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
763 return;
765 for ( sal_uInt16 i = 0; i < pImp->aStack.size(); ++i )
766 (*(pImp->aStack.rbegin() + i))->DoDeactivate_Impl(pImp->pFrame, bMDI);
768 sal_Bool bHidePopups = bMDI && pImp->pFrame;
769 if ( pNew && pImp->pFrame )
771 com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xOldFrame(
772 pNew->GetFrame().GetFrameInterface()->getCreator(), com::sun::star::uno::UNO_QUERY );
774 com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xMyFrame(
775 GetFrame()->GetFrame().GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
777 if ( xOldFrame == xMyFrame )
778 bHidePopups = sal_False;
781 if ( bHidePopups )
783 SfxBindings *pBind = GetBindings();
784 while ( pBind )
786 pBind->HidePopupCtrls_Impl( sal_True );
787 pBind = pBind->GetSubBindings_Impl();
790 pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( sal_True, sal_False, 1 );
793 Flush();
796 void SfxDispatcher::DoParentDeactivate_Impl()
798 for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
799 (*(pImp->aStack.rbegin() + i))->ParentDeactivate();
802 //--------------------------------------------------------------------
803 int SfxDispatcher::GetShellAndSlot_Impl
805 sal_uInt16 nSlot, // the searchable Slot-Id
806 SfxShell** ppShell, // the SfxShell, which are currently handled
807 // the nSlot
808 const SfxSlot** ppSlot, // the SfxSlot, which are currently handled
809 // the nSlot
810 sal_Bool bOwnShellsOnly,
811 sal_Bool bModal, // ModalMode
812 sal_Bool bRealSlot
815 /* [Description]
817 This method searches in SfxDispatcher after <SfxShell> , from the Slot Id
818 nSlot currently being handled. For this, the dispatcher is first flushed.
820 [Return value]
822 int sal_True
823 The SfxShell was found, ppShell and ppSlot are valid.
825 sal_False
826 The SfxShell was not found, ppShell and ppSlot are invalid.
830 SFX_STACK(SfxDispatcher::GetShellAndSlot_Impl);
832 Flush();
833 SfxSlotServer aSvr;
834 if ( _FindServer(nSlot, aSvr, bModal) )
836 if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.size() )
837 return sal_False;
839 *ppShell = GetShell(aSvr.GetShellLevel());
840 *ppSlot = aSvr.GetSlot();
841 if ( 0 == (*ppSlot)->GetExecFnc() && bRealSlot )
842 *ppSlot = (*ppShell)->GetInterface()->GetRealSlot(*ppSlot);
843 // Check only real slots as enum slots don't have an execute function!
844 if ( bRealSlot && ((0 == *ppSlot) || (0 == (*ppSlot)->GetExecFnc()) ))
845 return sal_False;
847 return sal_True;
850 return sal_False;
853 //--------------------------------------------------------------------
854 void SfxDispatcher::_Execute
856 SfxShell& rShell, // to the calling <SfxShell>
857 const SfxSlot& rSlot, // to the calling <SfxSlot>
858 SfxRequest& rReq, // function to be performed
859 // (Id and optional parameters)
860 SfxCallMode eCallMode // Synchronously, asynchronously or as shown in
861 // the slot
864 /* [Description]
866 This method performs a request for a cached <Slot-Server>.
870 DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
871 DBG_ASSERT( pImp->aToDoStack.empty(), "unprepared InPlace _Execute" );
873 if ( IsLocked( rSlot.GetSlotId() ) )
874 return;
876 if ( (eCallMode & SFX_CALLMODE_ASYNCHRON) ||
877 ( !(eCallMode & SFX_CALLMODE_SYNCHRON) &&
878 rSlot.IsMode(SFX_SLOT_ASYNCHRON) ) )
880 SfxDispatcher *pDispat = this;
881 while ( pDispat )
883 sal_uInt16 nShellCount = pDispat->pImp->aStack.size();
884 for ( sal_uInt16 n=0; n<nShellCount; n++ )
886 if ( &rShell == *(pDispat->pImp->aStack.rbegin() + n) )
888 if ( eCallMode & SFX_CALLMODE_RECORD )
889 rReq.AllowRecording( sal_True );
890 pDispat->pImp->xPoster->Post(new SfxRequest(rReq));
891 return;
895 pDispat = pDispat->pImp->pParent;
898 else
899 Call_Impl( rShell, rSlot, rReq, SFX_CALLMODE_RECORD==(eCallMode&SFX_CALLMODE_RECORD) );
902 //--------------------------------------------------------------------
903 void MappedPut_Impl( SfxAllItemSet &rSet, const SfxPoolItem &rItem )
905 /* [Description]
907 Helper function to put from rItem below the Which-ID in the pool of the
908 Item Sets rSet.
912 // Put with mapped Which-Id if possible
913 const SfxItemPool *pPool = rSet.GetPool();
914 sal_uInt16 nWhich = rItem.Which();
915 if ( pPool->IsSlot(nWhich) )
916 nWhich = pPool->GetWhich(nWhich);
917 rSet.Put( rItem, nWhich );
920 //--------------------------------------------------------------------
922 const SfxSlot* SfxDispatcher::GetSlot( const String& rCommand )
924 // Count the number of Shells on the linked Dispatcher
925 Flush();
926 sal_uInt16 nTotCount = pImp->aStack.size();
927 if ( pImp->pParent )
929 SfxDispatcher *pParent = pImp->pParent;
930 while ( pParent )
932 nTotCount = nTotCount + pParent->pImp->aStack.size();
933 pParent = pParent->pImp->pParent;
937 const SfxSlot *pSlot=NULL;
938 sal_uInt16 nFirstShell = 0;
939 for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
941 SfxShell *pObjShell = GetShell(i);
942 SfxInterface *pIFace = pObjShell->GetInterface();
943 pSlot = pIFace->GetSlot( rCommand );
944 if ( pSlot )
945 return pSlot;
948 return 0;
951 //--------------------------------------------------------------------
952 const SfxPoolItem* SfxDispatcher::Execute(
953 sal_uInt16 nSlot,
954 SfxCallMode nCall,
955 SfxItemSet* pArgs,
956 SfxItemSet* pInternalArgs,
957 sal_uInt16 nModi)
959 if ( IsLocked(nSlot) )
960 return 0;
962 SfxShell *pShell = 0;
963 const SfxSlot *pSlot = 0;
964 if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
965 SFX_CALLMODE_MODAL==(nCall&SFX_CALLMODE_MODAL) ) )
967 SfxAllItemSet aSet( pShell->GetPool() );
968 if ( pArgs )
970 SfxItemIter aIter(*pArgs);
971 for ( const SfxPoolItem *pArg = aIter.FirstItem();
972 pArg;
973 pArg = aIter.NextItem() )
974 MappedPut_Impl( aSet, *pArg );
976 SfxRequest aReq( nSlot, nCall, aSet );
977 if (pInternalArgs)
978 aReq.SetInternalArgs_Impl( *pInternalArgs );
979 aReq.SetModifier( nModi );
981 _Execute( *pShell, *pSlot, aReq, nCall );
982 return aReq.GetReturnValue();
984 return 0;
987 //--------------------------------------------------------------------
988 const SfxPoolItem* SfxDispatcher::Execute
990 sal_uInt16 nSlot, // the Id of the executing function
991 SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON
992 // or ..._SLOT
993 const SfxPoolItem **pArgs, // Zero teminated C-Array of Parameters
994 sal_uInt16 nModi,
995 const SfxPoolItem **pInternalArgs // Zero terminated C-Array of Parameters
998 /* [Description]
1000 Method to excecute a <SfxSlot>s over the Slot-Id.
1002 [Return value]
1004 const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
1005 though the Message-Loop, which contains the return
1006 value.
1008 Or a NULL-Pointer, when the function was not
1009 executed (for example canceled by the user).
1013 if ( IsLocked(nSlot) )
1014 return 0;
1016 SfxShell *pShell = 0;
1017 const SfxSlot *pSlot = 0;
1018 if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
1019 SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1021 SfxRequest* pReq;
1022 if ( pArgs && *pArgs )
1024 SfxAllItemSet aSet( pShell->GetPool() );
1025 for ( const SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
1026 MappedPut_Impl( aSet, **pArg );
1027 pReq = new SfxRequest( nSlot, eCall, aSet );
1029 else
1030 pReq = new SfxRequest( nSlot, eCall, pShell->GetPool() );
1031 pReq->SetModifier( nModi );
1032 if( pInternalArgs && *pInternalArgs)
1034 SfxAllItemSet aSet( SFX_APP()->GetPool() );
1035 for ( const SfxPoolItem **pArg = pInternalArgs; *pArg; ++pArg )
1036 aSet.Put( **pArg );
1037 pReq->SetInternalArgs_Impl( aSet );
1039 _Execute( *pShell, *pSlot, *pReq, eCall );
1040 const SfxPoolItem* pRet = pReq->GetReturnValue();
1041 delete pReq; return pRet;
1043 return 0;
1046 //--------------------------------------------------------------------
1047 const SfxPoolItem* SfxDispatcher::Execute
1049 sal_uInt16 nSlot, // the Id of the executing function
1050 SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON or ..._SLOT
1051 const SfxItemSet &rArgs // <SfxItemSet> with the parameters
1054 /* [Description]
1056 Method to excecute a <SfxSlot>s over the Slot-Id.
1058 [Return value]
1060 const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
1061 though the Message-Loop, which contains the return
1062 value.
1064 Or a NULL-Pointer, when the function was not
1065 executed (for example canceled by the user).
1069 return Execute( nSlot, eCall, 0, rArgs );
1072 //--------------------------------------------------------------------
1073 const SfxPoolItem* SfxDispatcher::Execute
1075 sal_uInt16 nSlot,
1076 SfxCallMode eCall,
1077 sal_uInt16 nModi,
1078 const SfxItemSet &rArgs
1081 if ( IsLocked(nSlot) )
1082 return 0;
1084 SfxShell *pShell = 0;
1085 const SfxSlot *pSlot = 0;
1086 if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
1087 SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1089 SfxAllItemSet aSet( pShell->GetPool() );
1090 SfxItemIter aIter(rArgs);
1091 for ( const SfxPoolItem *pArg = aIter.FirstItem();
1092 pArg;
1093 pArg = aIter.NextItem() )
1094 MappedPut_Impl( aSet, *pArg );
1095 SfxRequest aReq( nSlot, eCall, aSet );
1096 aReq.SetModifier( nModi );
1097 _Execute( *pShell, *pSlot, aReq, eCall );
1098 return aReq.GetReturnValue();
1100 return 0;
1103 //--------------------------------------------------------------------
1104 const SfxPoolItem* SfxDispatcher::Execute
1106 sal_uInt16 nSlot, // the Id of the executing function
1107 SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON or
1108 // ..._SLOT
1109 const SfxPoolItem* pArg1, // First parameter
1110 ... // Zero terminated list of parameters
1113 /* [Description]
1115 Method to excecute a <SfxSlot>s over the Slot-Id.
1117 [Note]
1119 The parameters are copied, can therefore be passed on as the address
1120 of stack objects.
1122 [Return value]
1124 const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
1125 though the Message-Loop, which contains the return
1126 value.
1128 Or a NULL-Pointer, when the function was not
1129 executed (for example canceled by the user).
1131 [Example]
1133 pDispatcher->Execute( SID_OPENDOCUMENT, SFX_CALLMODE_SYNCHRON,
1134 &SfxStringItem( SID_FILE_NAME, "\\tmp\\temp.sdd" ),
1135 &SfxStringItem( SID_FILTER_NAME, "StarDraw Presentation" ),
1136 &SfxBoolItem( SID_DOC_READONLY, sal_False ),
1137 0L );
1141 if ( IsLocked(nSlot) )
1142 return 0;
1144 SfxShell *pShell = 0;
1145 const SfxSlot *pSlot = 0;
1146 if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
1147 SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1149 SfxAllItemSet aSet( pShell->GetPool() );
1151 va_list pVarArgs;
1152 va_start( pVarArgs, pArg1 );
1153 for ( const SfxPoolItem *pArg = pArg1;
1154 pArg;
1155 pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
1156 MappedPut_Impl( aSet, *pArg );
1157 va_end(pVarArgs);
1159 SfxRequest aReq( nSlot, eCall, aSet );
1160 _Execute( *pShell, *pSlot, aReq, eCall );
1161 return aReq.GetReturnValue();
1163 return 0;
1166 //--------------------------------------------------------------------
1168 IMPL_LINK( SfxDispatcher, PostMsgHandler, SfxRequest*, pReq )
1170 /* [Description]
1172 Helper method to receive the asynchronously executed <SfxRequest>s.
1176 DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
1177 SFX_STACK(SfxDispatcher::PostMsgHandler);
1179 // Has also the Pool not yet died?
1180 if ( !pReq->IsCancelled() )
1182 if ( !IsLocked(pReq->GetSlot()) )
1184 Flush();
1185 SfxSlotServer aSvr;
1186 if ( _FindServer(pReq->GetSlot(), aSvr, sal_True ) ) // HACK(x), whatever that was supposed to mean
1188 const SfxSlot *pSlot = aSvr.GetSlot();
1189 SfxShell *pSh = GetShell(aSvr.GetShellLevel());
1191 DBG( SfxApplication *pSfxApp = SFX_APP() );
1192 DBG( pSfxApp->EnterAsynchronCall_Impl() );
1194 // When the pSlot is a "Pseudoslot" for macros or Verbs, it can
1195 // be destroyed in the Call_Impl, thus do not use it anymore!
1196 pReq->SetSynchronCall( sal_False );
1197 Call_Impl( *pSh, *pSlot, *pReq, pReq->AllowsRecording() ); //! why bRecord?
1198 DBG( pSfxApp->LeaveAsynchronCall_Impl() );
1201 else
1203 if ( pImp->bLocked )
1204 pImp->aReqArr.push_back(new SfxRequest(*pReq));
1205 else
1206 pImp->xPoster->Post(new SfxRequest(*pReq));
1210 delete pReq;
1211 return 0;
1213 //--------------------------------------------------------------------
1214 void SfxDispatcher::SetMenu_Impl()
1216 if ( pImp->pFrame )
1218 SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
1219 if ( pTop && pTop->GetBindings().GetDispatcher() == this )
1221 SfxFrame& rFrame = pTop->GetFrame();
1222 if ( rFrame.IsMenuBarOn_Impl() )
1224 com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
1225 if ( xPropSet.is() )
1227 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1228 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( OUString( "LayoutManager" ));
1229 aValue >>= xLayoutManager;
1230 if ( xLayoutManager.is() )
1232 OUString aMenuBarURL( "private:resource/menubar/menubar" );
1233 if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
1234 xLayoutManager->createElement( aMenuBarURL );
1242 //--------------------------------------------------------------------
1243 void SfxDispatcher::Update_Impl( sal_Bool bForce )
1245 SFX_STACK(SfxDispatcher::Update_Impl);
1247 Flush();
1249 if ( !pImp->pFrame )
1250 return;
1252 SFX_APP(); // -Wall is this required???
1253 SfxDispatcher *pDisp = this;
1254 sal_Bool bUpdate = bForce;
1255 while ( pDisp && pDisp->pImp->pFrame )
1257 SfxWorkWindow *pWork = pDisp->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1258 SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1259 if ( pAct == pDisp || pAct == this )
1261 if ( !bUpdate )
1262 bUpdate = !pDisp->pImp->bUpdated;
1263 pDisp->pImp->bUpdated = sal_True;
1265 else
1266 break;
1268 pDisp = pDisp->pImp->pParent;
1271 if ( !bUpdate || pImp->pFrame->GetFrame().IsClosing_Impl() )
1272 return;
1274 SfxViewFrame* pTop = pImp->pFrame ? pImp->pFrame->GetTopViewFrame() : NULL;
1275 sal_Bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
1277 if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
1278 // keep own tools internally for collecting
1279 GetBindings()->GetDispatcher()->pImp->bUpdated = sal_False;
1281 SfxBindings* pBindings = GetBindings();
1282 if ( pBindings )
1283 pBindings->DENTERREGISTRATIONS();
1285 com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame = pBindings->GetActiveFrame();
1286 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, com::sun::star::uno::UNO_QUERY );
1287 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1288 if ( xPropSet.is() )
1292 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( OUString( "LayoutManager" ) );
1293 aValue >>= xLayoutManager;
1295 catch (const com::sun::star::uno::Exception&)
1300 if ( xLayoutManager.is() )
1301 xLayoutManager->lock();
1303 sal_Bool bIsIPActive = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1304 SfxInPlaceClient *pClient = pImp->pFrame ? pImp->pFrame->GetViewShell()->GetUIActiveClient() : NULL;
1305 if ( bUIActive && /* !bIsIPActive && */ ( !pClient || !pClient->IsObjectUIActive() ) )
1306 SetMenu_Impl();
1308 SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1309 SfxWorkWindow *pTaskWin = pImp->pFrame->GetTopFrame().GetWorkWindow_Impl();
1310 pTaskWin->ResetStatusBar_Impl();
1312 SfxDispatcher *pDispat = this;
1313 while ( pDispat )
1315 SfxWorkWindow *pWork = pDispat->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1316 SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1317 if ( pAct == pDispat || pAct == this )
1319 pWork->ResetObjectBars_Impl();
1320 pWork->ResetChildWindows_Impl();
1323 pDispat = pDispat->pImp->pParent;
1326 sal_Bool bIsActive = sal_False;
1327 SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1328 pDispat = this;
1329 while ( pActDispat && !bIsActive )
1331 if ( pDispat == pActDispat )
1332 bIsActive = sal_True;
1333 pActDispat = pActDispat->pImp->pParent;
1336 _Update_Impl( bUIActive, !bIsIPActive, bIsIPActive, pTaskWin );
1337 if ( bUIActive || bIsActive )
1338 pWorkWin->UpdateObjectBars_Impl();
1340 if ( pBindings )
1341 pBindings->DLEAVEREGISTRATIONS();
1343 if ( xLayoutManager.is() )
1344 xLayoutManager->unlock();
1346 return;
1349 void SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp, sal_Bool bIsIPOwner, SfxWorkWindow *pTaskWin )
1351 SFX_APP();
1352 SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1353 sal_Bool bIsActive = sal_False;
1354 sal_Bool bIsTaskActive = sal_False;
1355 SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1356 SfxDispatcher *pDispat = this;
1357 while ( pActDispat && !bIsActive )
1359 if ( pDispat == pActDispat )
1360 bIsActive = sal_True;
1361 pActDispat = pActDispat->pImp->pParent;
1364 if ( pImp->pParent && !pImp->bQuiet /* && bUIActive */ )
1365 pImp->pParent->_Update_Impl( bUIActive, bIsMDIApp, bIsIPOwner, pTaskWin );
1367 for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1368 pImp->aObjBars[n].nResId = 0;
1369 pImp->aChildWins.clear();
1371 // bQuiet : own shells aren't considered for UI and SlotServer
1372 // bNoUI: own Shells aren't considered fors UI
1373 if ( pImp->bQuiet || pImp->bNoUI || (pImp->pFrame && pImp->pFrame->GetObjectShell()->IsPreview()) )
1374 return;
1376 sal_uInt32 nStatBarId=0;
1377 SfxShell *pStatusBarShell = NULL;
1379 SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() );
1380 sal_uInt16 nTotCount = pImp->aStack.size();
1381 for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
1383 SfxShell *pShell = GetShell( nShell-1 );
1384 SfxInterface *pIFace = pShell->GetInterface();
1386 // don't consider shells if "Hidden" oder "Quiet"
1387 sal_Bool bReadOnlyShell = IsReadOnlyShell_Impl( nShell-1 );
1388 sal_uInt16 nNo;
1389 for ( nNo = 0; pIFace && nNo<pIFace->GetObjectBarCount(); ++nNo )
1391 sal_uInt16 nPos = pIFace->GetObjectBarPos(nNo);
1392 if ( bReadOnlyShell && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
1393 continue;
1395 // check whether toolbar needs activation of a special feature
1396 sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
1397 if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1398 continue;
1400 // check for toolboxes that are exclusively for a viewer
1401 if ( pImp->pFrame)
1403 sal_Bool bViewerTbx = SFX_VISIBILITY_VIEWER == ( nPos & SFX_VISIBILITY_VIEWER );
1404 SfxObjectShell* pSh = pImp->pFrame->GetObjectShell();
1405 SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, sal_False );
1406 sal_Bool bIsViewer = pItem && pItem->GetValue();
1407 if ( bIsViewer != bViewerTbx )
1408 continue;
1411 // always register toolbars, allows to switch them on
1412 sal_Bool bVisible = pIFace->IsObjectBarVisible(nNo);
1413 if ( !bVisible )
1414 nPos &= SFX_POSITION_MASK;
1416 SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
1417 rBar.nMode = nPos;
1418 rBar.nResId = pIFace->GetObjectBarResId(nNo).GetId();
1419 const String *pName = pIFace->GetObjectBarName(nNo);
1420 if ( pName )
1421 rBar.aName = *pName;
1422 else
1423 rBar.aName.Erase();
1424 rBar.pIFace = pIFace;
1426 if ( bUIActive || bIsActive )
1428 pWorkWin->SetObjectBar_Impl(
1429 nPos, rBar.nResId, rBar.pIFace, &rBar.aName );
1432 if ( !bVisible )
1433 rBar.nResId = 0;
1436 for ( nNo=0; pIFace && nNo<pIFace->GetChildWindowCount(); nNo++ )
1438 sal_uInt32 nId = pIFace->GetChildWindowId(nNo);
1439 const SfxSlot *pSlot = pSlotPool->GetSlot( (sal_uInt16) nId );
1440 SAL_WARN_IF( !pSlot, "sfx2.control", "Childwindow slot missing: " << nId );
1441 if ( bReadOnlyShell )
1443 // only show ChildWindows if their slot is allowed for readonly documents
1444 if ( pSlot && !pSlot->IsMode( SFX_SLOT_READONLYDOC ) )
1445 continue;
1448 sal_uInt32 nFeature = pIFace->GetChildWindowFeature(nNo);
1449 if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1450 continue;
1452 // slot decides whether a ChildWindow is shown when document is OLE server or OLE client
1453 sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
1454 if( pSlot )
1456 if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
1458 if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
1459 nMode |= SFX_VISIBILITY_CLIENT;
1461 else
1463 if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
1464 nMode |= SFX_VISIBILITY_SERVER;
1468 if ( bUIActive || bIsActive )
1469 pWorkWin->SetChildWindowVisible_Impl( nId, sal_True, nMode );
1470 if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
1471 pImp->aChildWins.push_back( nId );
1474 if ( bIsMDIApp || bIsIPOwner )
1476 sal_uInt32 nId = pIFace->GetStatusBarResId().GetId();
1477 if ( nId )
1479 nStatBarId = nId;
1480 pStatusBarShell = pShell;
1485 for ( sal_uInt16 nPos=0; nPos<SFX_OBJECTBAR_MAX; nPos++ )
1487 SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos];
1488 if ( rFixed.nResId )
1490 SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos];
1491 rBar = rFixed;
1492 pWorkWin->SetObjectBar_Impl( rFixed.nMode,
1493 rFixed.nResId, rFixed.pIFace, &rFixed.aName );
1497 if ( pTaskWin && ( bIsMDIApp || bIsIPOwner ) )
1499 SfxDispatcher *pActDispatcher = pTaskWin->GetBindings().GetDispatcher_Impl();
1500 SfxDispatcher *pDispatcher = this;
1501 while ( pActDispatcher && !bIsTaskActive )
1503 if ( pDispatcher == pActDispatcher )
1504 bIsTaskActive = sal_True;
1505 pActDispatcher = pActDispatcher->pImp->pParent;
1508 if ( bIsTaskActive && nStatBarId && pImp->pFrame )
1510 // internal frames also may control statusbar
1511 SfxBindings& rBindings = pImp->pFrame->GetBindings();
1512 pImp->pFrame->GetFrame().GetWorkWindow_Impl()->SetStatusBar_Impl( nStatBarId, pStatusBarShell, rBindings );
1517 //--------------------------------------------------------------------
1518 void SfxDispatcher::FlushImpl()
1520 /* [Description]
1522 Helper method to execute the outstanding push and pop commands.
1526 DBG_PROFSTART(SfxDispatcherFlush);
1527 SFX_STACK(SfxDispatcher::FlushImpl);
1529 OSL_TRACE("Flushing dispatcher!");
1531 pImp->aTimer.Stop();
1533 if ( pImp->pParent )
1534 pImp->pParent->Flush();
1536 pImp->bFlushing = !pImp->bFlushing;
1537 if ( !pImp->bFlushing )
1539 pImp->bFlushing = sal_True;
1540 DBG_PROFSTOP(SfxDispatcherFlush);
1541 return;
1544 SfxApplication *pSfxApp = SFX_APP();
1546 // Re-build the true stack in the first round
1547 std::deque<SfxToDo_Impl> aToDoCopy;
1548 sal_Bool bModify = sal_False;
1549 for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
1551 bModify = sal_True;
1553 if(i->bPush)
1555 // Actually push
1556 DBG_ASSERT( std::find(pImp->aStack.begin(), pImp->aStack.end(), i->pCluster) == pImp->aStack.end(),
1557 "pushed SfxShell already on stack" );
1558 pImp->aStack.push_back(i->pCluster);
1559 i->pCluster->SetDisableFlags(pImp->nDisableFlags);
1561 // Mark the moved shell
1562 aToDoCopy.push_front(*i);
1564 else
1566 // Actually pop
1567 SfxShell* pPopped = 0;
1568 bool bFound = false;
1571 DBG_ASSERT( !pImp->aStack.empty(), "popping from empty stack" );
1572 pPopped = pImp->aStack.back();
1573 pImp->aStack.pop_back();
1574 pPopped->SetDisableFlags( 0 );
1575 bFound = (pPopped == i->pCluster);
1577 // Mark the moved Shell
1578 aToDoCopy.push_front(SfxToDo_Impl(sal_False, i->bDelete, sal_False, *pPopped));
1580 while(i->bUntil && !bFound);
1581 DBG_ASSERT( bFound, "wrong SfxShell popped" );
1584 pImp->aToDoStack.clear();
1586 // Invalidate bindings, if possible
1587 if ( !pSfxApp->IsDowning() )
1589 if ( bModify )
1591 pImp->pCachedServ1 = 0;
1592 pImp->pCachedServ2 = 0;
1595 InvalidateBindings_Impl( bModify );
1598 pImp->bFlushing = sal_False;
1599 pImp->bUpdated = sal_False; // not only when bModify, if Doc/Template-Config
1600 bFlushed = sal_True;
1601 OSL_TRACE("Successfully flushed dispatcher!");
1603 //fdo#70703 FlushImpl may call back into itself so use aToDoCopyStack to talk
1604 //to outer levels of ourself. If DoActivate_Impl/DoDeactivate_Impl deletes
1605 //an entry, then they will walk back up aToDoCopyStack and set outer
1606 //levels's entries to bDeleted
1607 aToDoCopyStack.push_back(aToDoCopy);
1608 std::deque<SfxToDo_Impl>& rToDoCopy = aToDoCopyStack.back();
1609 // Activate the Shells and possible delete them in the 2nd round
1610 for(std::deque<SfxToDo_Impl>::reverse_iterator i = rToDoCopy.rbegin(); i != rToDoCopy.rend(); ++i)
1612 if (i->bDeleted)
1613 continue;
1614 if (!pImp->bActive)
1615 continue;
1616 if (i->bPush)
1617 i->pCluster->DoActivate_Impl(pImp->pFrame, sal_True);
1618 else
1619 i->pCluster->DoDeactivate_Impl(pImp->pFrame, sal_True);
1622 aToDoCopy = aToDoCopyStack.back();
1623 aToDoCopyStack.pop_back();
1625 for(std::deque<SfxToDo_Impl>::reverse_iterator i = aToDoCopy.rbegin(); i != aToDoCopy.rend(); ++i)
1627 if (i->bDelete && !i->bDeleted)
1629 if (!aToDoCopyStack.empty())
1631 //fdo#70703 if there is an outer FlushImpl then inform it that
1632 //we have deleted this cluster
1633 for (std::deque< std::deque<SfxToDo_Impl> >::iterator aI = aToDoCopyStack.begin();
1634 aI != aToDoCopyStack.end(); ++aI)
1636 std::deque<SfxToDo_Impl> &v = *aI;
1637 for(std::deque<SfxToDo_Impl>::iterator aJ = v.begin(); aJ != v.end(); ++aJ)
1639 if (aJ->pCluster == i->pCluster)
1640 aJ->bDeleted = true;
1644 delete i->pCluster;
1647 sal_Bool bAwakeBindings = !aToDoCopy.empty();
1648 if( bAwakeBindings )
1649 aToDoCopy.clear();
1651 // If more changes have occurred on the stach when
1652 // Activate/Deactivate/Delete:
1653 if (!bFlushed)
1654 // If Push/Pop hs been called by someone, theb also EnterReg was called!
1655 FlushImpl();
1657 if( bAwakeBindings && GetBindings() )
1658 GetBindings()->DLEAVEREGISTRATIONS();
1659 DBG_PROFSTOP(SfxDispatcherFlush);
1661 for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1662 pImp->aFixedObjBars[n].nResId = 0;
1664 SAL_INFO("sfx2.control", "SfxDispatcher(" << this << ")::Flush() done");
1667 //--------------------------------------------------------------------
1668 void SfxDispatcher::SetSlotFilter
1670 // HACK(hier muss mal ein enum rein) ???
1671 sal_Bool bEnable, /* sal_True:
1672 only enable specified slots,
1673 disable all other
1675 sal_False:
1676 disable specified slots,
1677 first enable all other
1679 sal_uInt16 nCount, // Number of SIDs in the following Array
1680 const sal_uInt16* pSIDs // sorted Array of 'nCount' SIDs
1683 /* [Description]
1685 With this method a filter set, the target slots can be enabled or disabled.
1686 The passed array must be retained until the destructor or the next
1687 <SetSlotFilter()>, it is not deleted from the dispatcher, so it can thus be
1688 static.
1690 In read-only documents the quasi ReadOnlyDoc Flag of slots can be
1691 overturned by the use of 'bEnable == 2', so this will be displayed again.
1692 On the other slots it has no effect.
1694 [Example]
1696 Targeted disabling of Slots 1, 2 and 3:
1698 static sal_uInt16 const pSIDs[] = { 1, 2, 3 };
1699 pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
1701 only permit Slots 5, 6 and 7:
1703 static sal_uInt16 const pSIDs[] = { 5, 6, 7 };
1704 pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
1706 Turn-off Filter:
1708 pDisp->SetSlotFilter();
1712 #ifdef DBG_UTIL
1713 // Check Array
1714 for ( sal_uInt16 n = 1; n < nCount; ++n )
1715 DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sorted" );
1716 #endif
1718 if ( pImp->pFilterSIDs )
1719 pImp->pFilterSIDs = 0;
1721 pImp->bFilterEnabling = bEnable;
1722 pImp->nFilterCount = nCount;
1723 pImp->pFilterSIDs = pSIDs;
1725 GetBindings()->InvalidateAll(sal_True);
1728 //--------------------------------------------------------------------
1729 extern "C"
1730 #ifdef WNT
1731 int _cdecl
1732 #else
1734 #endif
1736 SfxCompareSIDs_Impl( const void* pSmaller, const void* pBigger )
1738 return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
1741 //--------------------------------------------------------------------
1742 sal_Bool SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
1744 /* [Description]
1746 Searches for 'nSID' in the Filter set by <SetSlotFilter()> and
1747 returns sal_True, if the SIDis allowed, or sal_False, if it is
1748 disabled by the Filter.
1750 [Return value]
1751 sal_Bool 0 => disabled
1752 1 => enabled
1753 2 => enabled even if ReadOnlyDoc
1757 // no filter?
1758 if ( 0 == pImp->nFilterCount )
1759 // => all SIDs allowed
1760 return sal_True;
1762 // search
1763 sal_Bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
1764 sizeof(sal_uInt16), SfxCompareSIDs_Impl );
1766 // even if ReadOnlyDoc
1767 if ( 2 == pImp->bFilterEnabling )
1768 return bFound ? 2 : 1;
1769 // Otherwise after Negative/Positive Filter
1770 return pImp->bFilterEnabling ? bFound : !bFound;
1773 //--------------------------------------------------------------------
1774 sal_Bool SfxDispatcher::_TryIntercept_Impl
1776 sal_uInt16 nSlot, // Slot-Id to search for
1777 SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
1778 sal_Bool bSelf
1781 // Maybe the parent is also belongs to a component
1782 SfxDispatcher *pParent = pImp->pParent;
1783 sal_uInt16 nLevels = pImp->aStack.size();
1784 while ( pParent && pParent->pImp->pFrame )
1786 if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
1788 // Components may be intercepted
1789 if ( pParent->_TryIntercept_Impl( nSlot, rServer, sal_True ) )
1791 // The own shells are added to the Shell Level
1792 rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
1793 return sal_True;
1795 else
1796 // No further Interception
1797 break;
1799 else
1800 nLevels = nLevels + pParent->pImp->aStack.size();
1802 pParent = pParent->pImp->pParent;
1805 if ( bSelf )
1807 // Query the ComponentViewShell
1808 Flush();
1809 SfxShell *pObjShell = GetShell(0);
1810 SfxInterface *pIFace = pObjShell->GetInterface();
1811 const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
1813 if ( pSlot )
1815 rServer.SetSlot(pSlot);
1816 rServer.SetShellLevel(0);
1817 return sal_True;
1821 return sal_False;
1824 sal_Bool SfxDispatcher::_FindServer
1826 sal_uInt16 nSlot, // Slot-Id to search for
1827 SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
1828 sal_Bool bModal // Dispite ModalMode
1831 /* [Description]
1833 This helper method searches for the <Slot-Server> which currently serves
1834 the nSlot. As the result, rServe is filled accordingly.
1836 If known the SfxInterface which is currently served by nSlot can be
1837 passed along.
1839 The SfxDispatcher is flushed while searching for nSlot.
1841 [Return value]
1844 sal_Bool sal_True
1845 The Slot was found, rServer is valid.
1847 sal_False
1848 The Slot is currently not served, rServer is invalid.
1852 SFX_STACK(SfxDispatcher::_FindServer);
1854 // Dispatcher locked? (nevertheless let SID_HELP_PI through)
1855 if ( IsLocked(nSlot) )
1857 pImp->bInvalidateOnUnlock = sal_True;
1858 return sal_False;
1861 // Count the number of Shells in the linked dispatchers.
1862 Flush();
1863 sal_uInt16 nTotCount = pImp->aStack.size();
1864 if ( pImp->pParent )
1866 SfxDispatcher *pParent = pImp->pParent;
1867 while ( pParent )
1869 nTotCount = nTotCount + pParent->pImp->aStack.size();
1870 pParent = pParent->pImp->pParent;
1874 // Verb-Slot?
1875 if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
1877 for ( sal_uInt16 nShell = 0;; ++nShell )
1879 SfxShell *pSh = GetShell(nShell);
1880 if ( pSh == NULL )
1881 return false;
1882 if ( pSh->ISA(SfxViewShell) )
1884 const SfxSlot* pSlot = pSh->GetVerbSlot_Impl(nSlot);
1885 if ( pSlot )
1887 rServer.SetShellLevel(nShell);
1888 rServer.SetSlot( pSlot );
1889 return true;
1895 // SID check against set filter
1896 sal_uInt16 nSlotEnableMode=0;
1897 if ( pImp->pFrame )
1899 nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
1900 if ( 0 == nSlotEnableMode )
1901 return sal_False;
1904 // In Quiet-Mode only Parent-Dispatcher
1905 if ( pImp->bQuiet )
1907 if ( pImp->pParent )
1909 sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
1910 rServer.SetShellLevel
1911 ( rServer.GetShellLevel() + pImp->aStack.size() );
1912 return bRet;
1914 else
1915 return sal_False;
1918 sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly );
1920 // search through all the shells of the chained dispatchers
1921 // from top to bottom
1922 sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.size() : 0;
1923 for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
1925 SfxShell *pObjShell = GetShell(i);
1926 SfxInterface *pIFace = pObjShell->GetInterface();
1927 const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
1929 if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
1930 return sal_False;
1932 if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
1933 return sal_False;
1935 if ( pSlot )
1937 // Slot belongs to Container?
1938 bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
1939 bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1941 // Shell belongs to Server?
1942 // AppDispatcher or IPFrame-Dispatcher
1943 bool bIsServerShell = !pImp->pFrame || bIsInPlace;
1945 // Of course ShellServer-Slots are also executable even when it is
1946 // excecuted on a container dispatcher without a IPClient.
1947 if ( !bIsServerShell )
1949 SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
1950 bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
1953 // Shell belongs to Container?
1954 // AppDispatcher or no IPFrameDispatcher
1955 bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
1956 // Shell and Slot match
1957 if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
1958 ( !bIsContainerSlot && bIsServerShell ) ) )
1959 pSlot = 0;
1962 if ( pSlot )
1964 rServer.SetSlot(pSlot);
1965 rServer.SetShellLevel(i);
1966 return sal_True;
1970 return sal_False;
1973 //--------------------------------------------------------------------
1974 sal_Bool SfxDispatcher::_FillState
1976 const SfxSlotServer& rSvr, // <Slot-Server> to query
1977 SfxItemSet& rState, // <SfxItemSet> to be filled
1978 const SfxSlot* pRealSlot // The actual Slot if possible
1981 /* [Description]
1983 Helper method to obtain the status of the <Slot-Server>s rSvr.
1984 The required slots IDs (partly converted to Which-IDs of the pool)
1985 must be present in rstate.
1987 The SfxDispatcher is flushed before the query.
1991 SFX_STACK(SfxDispatcher::_FillState);
1993 DBG_PROFSTART(SfxDispatcherFillState);
1995 const SfxSlot *pSlot = rSvr.GetSlot();
1996 if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
1998 pImp->bInvalidateOnUnlock = sal_True;
1999 DBG_PROFSTOP(SfxDispatcherFillState);
2000 return sal_False;
2003 if ( pSlot )
2005 DBG_ASSERT(bFlushed, "Dispatcher not flushed after retrieving slot servers!");
2006 if ( !bFlushed )
2007 return sal_False;
2009 // Determine the object and call the Message of this object
2010 SfxShell *pSh = GetShell(rSvr.GetShellLevel());
2011 DBG_ASSERT(pSh, "ObjektShell not found");
2013 SfxStateFunc pFunc;
2015 if (pRealSlot)
2016 pFunc = pRealSlot->GetStateFnc();
2017 else
2018 pFunc = pSlot->GetStateFnc();
2020 pSh->CallState( pFunc, rState );
2021 #ifdef DBG_UTIL
2022 // To examine the conformity of IDL (SlotMap) and current Items
2023 if ( DbgIsAssertWarning() && rState.Count() )
2025 SfxInterface *pIF = pSh->GetInterface();
2026 SfxItemIter aIter( rState );
2027 for ( const SfxPoolItem *pItem = aIter.FirstItem();
2028 pItem;
2029 pItem = aIter.NextItem() )
2031 if ( !IsInvalidItem(pItem) && !pItem->ISA(SfxVoidItem) )
2033 sal_uInt16 nSlotId = rState.GetPool()->GetSlotId(pItem->Which());
2034 if ( !pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()) )
2036 OStringBuffer aMsg(RTL_CONSTASCII_STRINGPARAM(
2037 "item-type unequal to IDL (=> no BASIC)"));
2038 aMsg.append(RTL_CONSTASCII_STRINGPARAM("\nwith SID: "));
2039 aMsg.append(static_cast<sal_Int32>(nSlotId));
2040 aMsg.append(RTL_CONSTASCII_STRINGPARAM("\nin "));
2041 aMsg.append(pIF->GetClassName());
2042 DbgOut(aMsg.getStr(), DBG_OUT_ERROR, __FILE__, __LINE__);
2047 #endif
2049 DBG_PROFSTOP(SfxDispatcherFillState);
2050 return sal_True;
2053 DBG_PROFSTOP(SfxDispatcherFillState);
2054 return sal_False;
2057 SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, const Point *pPos )
2059 SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
2060 sal_uInt16 nShLevel = 0;
2061 SfxShell *pSh;
2063 if ( rDisp.pImp->bQuiet )
2065 nConfigId = 0;
2066 nShLevel = rDisp.pImp->aStack.size();
2069 Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2070 for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2072 const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
2073 if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
2075 return SfxPopupMenuManager::Popup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2078 return 0;
2082 //----------------------------------------------------------------------
2083 void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, Window *pWin, const Point *pPos )
2085 SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
2086 sal_uInt16 nShLevel = 0;
2087 SfxShell *pSh;
2089 if ( rDisp.pImp->bQuiet )
2091 nConfigId = 0;
2092 nShLevel = rDisp.pImp->aStack.size();
2095 Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2096 for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2098 const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
2099 if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
2101 SfxPopupMenuManager::ExecutePopup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2102 return;
2107 //----------------------------------------------------------------------
2108 void SfxDispatcher::ExecutePopup( const ResId &rId, Window *pWin, const Point *pPos )
2110 Window *pWindow = pWin ? pWin : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2111 SfxPopupMenuManager::ExecutePopup( rId, GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2114 //--------------------------------------------------------------------
2115 void SfxDispatcher::Lock( sal_Bool bLock )
2117 /* [Description]
2119 With this method the SfxDispatcher can be locked and released. A locked
2120 SfxDispatcher does not perform <SfxRequest>s and does no longer provide
2121 status information. It behaves as if all the slots were disabled.
2125 SfxBindings* pBindings = GetBindings();
2126 if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
2128 if ( pBindings )
2129 pBindings->InvalidateAll(sal_True);
2130 pImp->bInvalidateOnUnlock = sal_False;
2132 else if ( pBindings )
2133 pBindings->InvalidateAll(sal_False);
2134 pImp->bLocked = bLock;
2135 if ( !bLock )
2137 for(size_t i = 0; i < pImp->aReqArr.size(); ++i)
2138 pImp->xPoster->Post(pImp->aReqArr[i]);
2139 pImp->aReqArr.clear();
2143 sal_uInt32 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
2145 return pImp->aObjBars[nPos].nResId;
2148 //-------------------------------------------------------------------------
2149 void SfxDispatcher::HideUI( sal_Bool bHide )
2151 sal_Bool bWasHidden = pImp->bNoUI;
2152 pImp->bNoUI = bHide;
2153 if ( pImp->pFrame )
2155 SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
2156 if ( pTop && pTop->GetBindings().GetDispatcher() == this )
2158 SfxFrame& rFrame = pTop->GetFrame();
2159 if ( rFrame.IsMenuBarOn_Impl() )
2161 com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
2162 if ( xPropSet.is() )
2164 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
2165 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( OUString( "LayoutManager" ));
2166 aValue >>= xLayoutManager;
2167 if ( xLayoutManager.is() )
2168 xLayoutManager->setVisible( !bHide );
2174 if ( bHide != bWasHidden )
2175 Update_Impl( sal_True );
2178 void SfxDispatcher::SetReadOnly_Impl( sal_Bool bOn )
2180 pImp->bReadOnly = bOn;
2183 sal_Bool SfxDispatcher::GetReadOnly_Impl() const
2185 return pImp->bReadOnly;
2188 //-------------------------------------------------------------------------
2189 void SfxDispatcher::SetQuietMode_Impl( sal_Bool bOn )
2191 /* [Description]
2193 With 'bOn' the Dispatcher is quasi dead and transfers everything to the
2194 Parent-Dispatcher.
2198 pImp->bQuiet = bOn;
2199 SfxBindings* pBindings = GetBindings();
2200 if ( pBindings )
2201 pBindings->InvalidateAll(sal_True);
2204 SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
2206 SfxShell *pShell = 0;
2207 const SfxSlot *pSlot = 0;
2208 if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
2210 rpState = pShell->GetSlotState(nSlot);
2211 if ( !rpState )
2212 return SFX_ITEM_DISABLED;
2213 else
2214 return SFX_ITEM_AVAILABLE;
2217 return SFX_ITEM_DISABLED;
2220 SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno::Any& rAny )
2222 SfxShell *pShell = 0;
2223 const SfxSlot *pSlot = 0;
2224 if ( GetShellAndSlot_Impl( nSID, &pShell, &pSlot, sal_False, sal_False ) )
2226 const SfxPoolItem* pItem( 0 );
2228 pItem = pShell->GetSlotState( nSID );
2229 if ( !pItem )
2230 return SFX_ITEM_DISABLED;
2231 else
2233 ::com::sun::star::uno::Any aState;
2234 if ( !pItem->ISA(SfxVoidItem) )
2236 sal_uInt16 nSubId( 0 );
2237 SfxItemPool& rPool = pShell->GetPool();
2238 sal_uInt16 nWhich = rPool.GetWhich( nSID );
2239 if ( rPool.GetMetric( nWhich ) == SFX_MAPUNIT_TWIP )
2240 nSubId |= CONVERT_TWIPS;
2241 pItem->QueryValue( aState, (sal_uInt8)nSubId );
2243 rAny = aState;
2245 return SFX_ITEM_AVAILABLE;
2249 return SFX_ITEM_DISABLED;
2252 sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
2254 sal_uInt16 nShellCount = pImp->aStack.size();
2255 if ( nShell < nShellCount )
2257 SfxShell* pShell = *( pImp->aStack.rbegin() + nShell );
2258 if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
2259 return sal_False;
2260 else
2261 return pImp->bReadOnly;
2263 else if ( pImp->pParent )
2264 return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
2265 return sal_True;
2268 void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
2270 Flush();
2272 sal_uInt16 nCount = pImp->aStack.size();
2273 for ( sal_uInt16 n=0; n<nCount; ++n )
2275 if ( pImp->aStack[n] == &rShell )
2277 pImp->aStack.erase( pImp->aStack.begin() + n );
2278 rShell.SetDisableFlags( 0 );
2279 rShell.DoDeactivate_Impl(pImp->pFrame, sal_True);
2280 break;
2284 if ( !SFX_APP()->IsDowning() )
2286 pImp->bUpdated = sal_False;
2287 pImp->pCachedServ1 = 0;
2288 pImp->pCachedServ2 = 0;
2289 InvalidateBindings_Impl(sal_True);
2293 void SfxDispatcher::InvalidateBindings_Impl( sal_Bool bModify )
2295 // App-Dispatcher?
2296 if ( IsAppDispatcher() )
2298 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst();
2299 pFrame;
2300 pFrame = SfxViewFrame::GetNext( *pFrame ) )
2301 pFrame->GetBindings().InvalidateAll(bModify);
2303 else
2305 SfxDispatcher *pDisp = GetBindings()->GetDispatcher_Impl();
2306 while ( pDisp )
2308 if ( pDisp == this )
2310 GetBindings()->InvalidateAll( bModify );
2311 break;
2314 pDisp = pDisp->pImp->pParent;
2319 sal_Bool SfxDispatcher::IsUpdated_Impl() const
2321 return pImp->bUpdated;
2324 void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
2326 pImp->nDisableFlags = nFlags;
2327 for ( SfxShellStack_Impl::const_reverse_iterator it = pImp->aStack.rbegin(); it != pImp->aStack.rend(); ++it )
2328 (*it)->SetDisableFlags( nFlags );
2331 sal_uInt32 SfxDispatcher::GetDisableFlags() const
2333 return pImp->nDisableFlags;
2336 SfxModule* SfxDispatcher::GetModule() const
2338 for ( sal_uInt16 nShell = 0;; ++nShell )
2340 SfxShell *pSh = GetShell(nShell);
2341 if ( pSh == NULL )
2342 return 0;
2343 if ( pSh->ISA(SfxModule) )
2344 return (SfxModule*) pSh;
2348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */