bump product version to 4.2.0.1
[LibreOffice.git] / sfx2 / source / control / dispatch.cxx
blob934a6cbb6699e767a6a6c1e7d0eab9bf75ce29c9
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 <config_features.h>
22 #include <algorithm>
23 #include <deque>
24 #include <vector>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
32 #include <com/sun/star/frame/XLayoutManager.hpp>
34 #include <rtl/strbuf.hxx>
35 #include <sfx2/app.hxx>
36 #include <sfx2/bindings.hxx>
37 #include <sfx2/childwin.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <sfx2/docfac.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <sfx2/hintpost.hxx>
42 #include <sfx2/ipclient.hxx>
43 #include <sfx2/mnumgr.hxx>
44 #include <sfx2/module.hxx>
45 #include <sfx2/msg.hxx>
46 #include <sfx2/msgpool.hxx>
47 #include <sfx2/objface.hxx>
48 #include <sfx2/request.hxx>
49 #include <sfx2/sfxhelp.hxx>
50 #include <sfx2/sfxuno.hxx>
51 #include <sfx2/viewfrm.hxx>
52 #include <sfx2/viewsh.hxx>
53 #include <svl/eitem.hxx>
54 #include <svl/intitem.hxx>
55 #include <svl/itemiter.hxx>
56 #include <svl/itempool.hxx>
57 #include <svl/undo.hxx>
58 #include <svl/whiter.hxx>
59 #include <svtools/helpopt.hxx>
60 #include <vcl/wrkwin.hxx>
62 #include <appdata.hxx>
63 #include <sfxtypes.hxx>
64 #include <slotserv.hxx>
65 #include <workwin.hxx>
67 DBG_NAME(SfxDispatcherFlush)
68 DBG_NAME(SfxDispatcherFillState)
70 typedef std::vector<SfxRequest*> SfxRequestPtrArray;
72 struct SfxObjectBars_Impl
74 sal_uInt32 nResId; // Resource - and ConfigId of the Toolbox
75 sal_uInt16 nMode; // special visibility flags
76 OUString aName;
77 SfxInterface* pIFace;
79 SfxObjectBars_Impl() : nResId(0), nMode(0), pIFace(NULL) {}
82 //------------------------------------------------------------------
84 struct SfxDispatcher_Impl
86 //When the dispatched is locked, SfxRequests accumulate in aReqArr for
87 //later dispatch when unlocked via Post
89 //The pointers are typically deleted in Post, only if we never get around
90 //to posting them do we delete the unposted requests.
91 SfxRequestPtrArray aReqArr;
92 ~SfxDispatcher_Impl()
94 for (SfxRequestPtrArray::iterator aI = aReqArr.begin(), aEnd = aReqArr.end(); aI != aEnd; ++aI)
95 delete *aI;
97 const SfxSlotServer* pCachedServ1; // last called message
98 const SfxSlotServer* pCachedServ2; // penultimate called Message
99 SfxShellStack_Impl aStack; // active functionality
100 Timer aTimer; // for Flush
101 std::deque<SfxToDo_Impl> aToDoStack; // not processed Push/Pop
102 SfxViewFrame* pFrame; // NULL or associated Frame
103 SfxDispatcher* pParent; // AppDispatcher, NULL if possible
104 SfxHintPosterRef xPoster; // Execute asynchronous
105 sal_Bool bFlushing; // sal_True during Flush //?
106 sal_Bool bUpdated; // Update_Impl has run
107 sal_Bool bLocked; // No Execute
108 sal_Bool bInvalidateOnUnlock; // because someone asked
109 sal_Bool bActive; // not to be confused with set!
110 sal_Bool* pInCallAliveFlag; // view the Destructor Stack
111 SfxObjectBars_Impl aObjBars[SFX_OBJECTBAR_MAX];
112 SfxObjectBars_Impl aFixedObjBars[SFX_OBJECTBAR_MAX];
113 std::vector<sal_uInt32> aChildWins;
114 sal_uInt32 nEventId; // EventId UserEvent
115 sal_Bool bNoUI; // UI only from Parent Dispatcher
116 sal_Bool bReadOnly; // Document is ReadOnly
117 sal_Bool bQuiet; // Only use parent dispatcher
118 sal_Bool bModal; // Only slots from parent dispatcher
120 sal_Bool bFilterEnabling; // sal_True=filter enabled slots,
121 // 2==ReadOnlyDoc overturned
122 sal_uInt16 nFilterCount; // Number of SIDs in pFilterSIDs
123 const sal_uInt16* pFilterSIDs; // sorted Array of SIDs
124 sal_uInt32 nDisableFlags;
127 //------------------------------------------------------------------
129 #define SFX_FLUSH_TIMEOUT 50
131 //====================================================================
132 sal_Bool SfxDispatcher::IsLocked( sal_uInt16 ) const
134 /* [Description]
136 With this method it can be determined whether the SfxDispatcher is
137 locked or unlocked. A locked SfxDispatcher does not perform <SfxRequest>s
138 and no longer provides any status information. It behaves as if all the
139 slots are disabled.
141 The dispatcher is also marked as blocked, if all Dispatcher are locked
142 (<SfxApplication::LockDispatcher()>) or the associated top frame is in the
143 modal-mode and if the specified slot are handled as frame-specific
144 (ie, not served by the application).
148 return pImp->bLocked;
151 //--------------------------------------------------------------------
152 sal_Bool SfxDispatcher::IsAppDispatcher() const
154 /* [Description]
156 With this method it can be determined if the SfxDispacher is the
157 applications dispatcher.
159 [Return value]
161 sal_Bool sal_True it is the application dispatcher.
162 sal_Fals it is a SfxViewFrame dispatcher.
166 return !pImp->pFrame;
169 //--------------------------------------------------------------------
170 int SfxDispatcher::Call_Impl( SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, sal_Bool bRecord )
172 /* [Description]
174 Helper function to check whether a slot can be executed and
175 check the execution itself
179 SFX_STACK(SfxDispatcher::Call_Impl);
181 // The slot may be called (meaning enabled)
182 if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
184 if ( GetFrame() )
186 // Recording may start
187 com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame(
188 GetFrame()->GetFrame().GetFrameInterface(),
189 com::sun::star::uno::UNO_QUERY);
191 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
192 xFrame,
193 com::sun::star::uno::UNO_QUERY);
195 if ( xSet.is() )
197 com::sun::star::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
198 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
199 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
200 aProp >>= xSupplier;
201 if(xSupplier.is())
202 xRecorder = xSupplier->getDispatchRecorder();
204 if ( bRecord && xRecorder.is() && !rSlot.IsMode(SFX_SLOT_NORECORD) )
205 rReq.Record_Impl( rShell, rSlot, xRecorder, GetFrame() );
208 // Get all that is needed, because the slot may not have survived the
209 // Execute if it is a 'pseudo slot' for macros or verbs.
210 sal_Bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
212 // API-call parentheses and document-lock during the calls
214 // 'this' must respond in the Destructor
215 sal_Bool bThisDispatcherAlive = sal_True;
216 sal_Bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
217 pImp->pInCallAliveFlag = &bThisDispatcherAlive;
219 SfxExecFunc pFunc = rSlot.GetExecFnc();
220 rShell.CallExec( pFunc, rReq );
222 // If 'this' is still alive
223 if ( bThisDispatcherAlive )
224 pImp->pInCallAliveFlag = pOldInCallAliveFlag;
225 else
227 if ( pOldInCallAliveFlag )
229 // also protect nested stack frames
230 *pOldInCallAliveFlag = sal_False;
233 // do nothing after this object is dead
234 return rReq.IsDone();
238 if ( rReq.IsDone() )
240 SfxBindings *pBindings = GetBindings();
242 // When AutoUpdate update immediately; "Pseudoslots" must not be
243 // Autoupdate!
244 if ( bAutoUpdate && pBindings )
246 const SfxSlot* pSlave = rSlot.GetLinkedSlot();
247 if (pSlave)
249 // When enum slots take any bound slave slot
250 while (!pBindings->IsBound(pSlave->GetSlotId()) && pSlave != &rSlot )
251 pSlave = pSlave->GetLinkedSlot();
252 pBindings->Invalidate(pSlave->GetSlotId());
253 pBindings->Update(pSlave->GetSlotId());
255 else
257 pBindings->Invalidate(rSlot.GetSlotId());
258 pBindings->Update(rSlot.GetSlotId());
262 return sal_True;
266 return sal_False;
269 //====================================================================
270 void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
272 pImp = new SfxDispatcher_Impl;
273 bFlushed = sal_True;
275 pImp->pCachedServ1 = 0;
276 pImp->pCachedServ2 = 0;
277 pImp->bFlushing = sal_False;
278 pImp->bUpdated = sal_False;
279 pImp->bLocked = sal_False;
280 pImp->bActive = sal_False;
281 pImp->pParent = NULL;
282 pImp->bNoUI = sal_False;
283 pImp->bReadOnly = sal_False;
284 pImp->bQuiet = sal_False;
285 pImp->bModal = sal_False;
286 pImp->pInCallAliveFlag = 0;
287 pImp->bFilterEnabling = sal_False;
288 pImp->nFilterCount = 0;
289 pImp->pFilterSIDs = 0;
290 pImp->nDisableFlags = 0;
292 pImp->pParent = pParent;
294 pImp->bInvalidateOnUnlock = sal_False;
296 for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
297 pImp->aObjBars[n].nResId = 0;
299 GenLink aGenLink( LINK(this, SfxDispatcher, PostMsgHandler) );
301 pImp->xPoster = new SfxHintPoster(aGenLink);
303 pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
304 pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
307 SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
309 Construct_Impl( pParent );
310 pImp->pFrame = 0;
313 SfxDispatcher::SfxDispatcher( SfxViewFrame *pViewFrame )
315 /* [Description]
317 The constructor of the SfxDispatcher class places a stack of empty
318 <SfxShell> pointers. It is not initially locked and is considered flushed.
322 if ( pViewFrame )
324 SfxViewFrame *pFrame = pViewFrame->GetParentViewFrame();
325 if ( pFrame )
326 Construct_Impl( pFrame->GetDispatcher() );
327 else
328 Construct_Impl( 0 );
330 else
331 Construct_Impl( 0 );
332 pImp->pFrame = pViewFrame;
335 //====================================================================
336 SfxDispatcher::~SfxDispatcher()
338 /* [Description]
340 The destructor of the SfxDispatcher class should not be called when the
341 SfxDispatcher instance is active. It may, however, still be a <SfxShell>
342 pointer on the stack.
346 #ifdef DBG_UTIL
347 OStringBuffer sTemp("Delete Dispatcher ");
348 sTemp.append(reinterpret_cast<sal_Int64>(this));
349 OSL_TRACE("%s", sTemp.getStr());
350 DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
351 #endif
353 // So that no timer by Reschedule in PlugComm strikes the LeaveRegistrations
354 pImp->aTimer.Stop();
355 pImp->xPoster->SetEventHdl( Link() );
357 // Notify the stack varialbles in Call_Impl
358 if ( pImp->pInCallAliveFlag )
359 *pImp->pInCallAliveFlag = sal_False;
361 // Get bindings and application
362 SfxApplication *pSfxApp = SFX_APP();
363 SfxBindings* pBindings = GetBindings();
365 // When not flushed, revive the bindings
366 if ( pBindings && !pSfxApp->IsDowning() && !bFlushed )
367 pBindings->DLEAVEREGISTRATIONS();
369 // may unregister the bindings
370 while ( pBindings )
372 if ( pBindings->GetDispatcher_Impl() == this)
373 pBindings->SetDispatcher(0);
374 pBindings = pBindings->GetSubBindings_Impl();
377 delete pImp;
380 //====================================================================
381 void SfxDispatcher::Pop
383 SfxShell& rShell, /* the stack to take the SfxShell instance. */
385 sal_uInt16 nMode /* SFX_SHELL_POP_UNTIL
386 Also all 'rShell' of SfxShells are taken from the
387 stack.
389 SFX_SHELL_POP_DELETE
390 All SfxShells actually taken from the stack
391 will be deleted.
393 SFX_SHELL_PUSH (InPlace use only)
394 The Shell is pushed. */
396 /* [Description]
398 With this method, one or more <SfxShell> are poped from the SfxDispatcher.
399 The SfxShell is marked for popping and a timer is set up. Only when the
400 timer has reached the end, the pop is actually performed
401 ( <SfxDispatcher::Flush()> ) and the <SfxBindings> is invalidated.
402 While the timer is running the opposing push and pop commands on one
403 SfxShell cancel each other out.
407 DBG_ASSERT( rShell.GetInterface(),
408 "pushing SfxShell without previous RegisterInterface()" );
410 bool bDelete = (nMode & SFX_SHELL_POP_DELETE) == SFX_SHELL_POP_DELETE;
411 bool bUntil = (nMode & SFX_SHELL_POP_UNTIL) == SFX_SHELL_POP_UNTIL;
412 bool bPush = (nMode & SFX_SHELL_PUSH) == SFX_SHELL_PUSH;
414 SfxApplication *pSfxApp = SFX_APP();
416 SAL_INFO(
417 "sfx.control",
418 "-SfxDispatcher(" << this << (bPush ? ")::Push(" : ")::Pop(")
419 << (rShell.GetInterface()
420 ? rShell.GetInterface()->GetClassName() : SAL_STREAM(&rShell))
421 << (bDelete ? ") with delete" : ")")
422 << (bUntil ? " (up to)" : ""));
424 // same shell as on top of the to-do stack?
425 if(pImp->aToDoStack.size() && pImp->aToDoStack.front().pCluster == &rShell)
427 // cancel inverse actions
428 if ( pImp->aToDoStack.front().bPush != bPush )
429 pImp->aToDoStack.pop_front();
430 else
432 DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
433 DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
436 else
438 // Remember ::com::sun::star::chaos::Action
439 pImp->aToDoStack.push_front( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
440 if ( bFlushed )
442 OSL_TRACE("Unflushed dispatcher!");
443 bFlushed = sal_False;
444 pImp->bUpdated = sal_False;
446 // Put bindings to sleep
447 SfxBindings* pBindings = GetBindings();
448 if ( pBindings )
449 pBindings->DENTERREGISTRATIONS();
453 if(!pSfxApp->IsDowning() && !pImp->aToDoStack.empty())
455 // No immediate update is requested
456 pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
457 pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
458 pImp->aTimer.Start();
460 else
462 // but to do nothing
463 pImp->aTimer.Stop();
465 // Bindings may wake up again
466 if(pImp->aToDoStack.empty())
468 SfxBindings* pBindings = GetBindings();
469 if ( pBindings )
470 pBindings->DLEAVEREGISTRATIONS();
475 //--------------------------------------------------------------------
477 IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
479 /* [Description]
481 This handler is called after <SfxDispatcher::Invalidate()> or after
482 changes on the stack (<SfxDispatcher::Push()> and <SfxDispatcher::Pop())
484 It flushes the Stack, if it is dirty, thus it actually excecutes the
485 pending Push and Pop commands.
489 (void)pvoid; // unused
491 Flush();
492 Update_Impl();
493 SfxBindings* pBindings = GetBindings();
494 if ( pBindings )
495 pBindings->StartUpdate_Impl(sal_False);
496 return 0;
498 IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
500 //--------------------------------------------------------------------
501 sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDeep )
503 /* [Description]
505 With this method it can be tested whether the <SfxShell> rShell is on the
506 stack, when it was flushed. This way the SfxDispatcher is not actually
507 flushed.
509 This method is intended among other things to make assertions possible
510 without the side effect of having to flush the SfxDispathcer.
514 SFX_STACK(SfxDispatcher::CheckVirtualStack);
516 SfxShellStack_Impl aStack( pImp->aStack );
517 for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
519 if(i->bPush)
520 aStack.push_back(i->pCluster);
521 else
523 SfxShell* pPopped(NULL);
526 DBG_ASSERT( !aStack.empty(), "popping from empty stack" );
527 pPopped = aStack.back();
528 aStack.pop_back();
530 while(i->bUntil && pPopped != i->pCluster);
531 DBG_ASSERT(pPopped == i->pCluster, "popping unpushed SfxInterface");
535 sal_Bool bReturn;
536 if ( bDeep )
537 bReturn = std::find(aStack.begin(), aStack.end(), &rShell) != aStack.end();
538 else
539 bReturn = aStack.back() == &rShell;
540 return bReturn;
543 //--------------------------------------------------------------------
544 sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
546 /* [Description]
548 Determines the position of a given SfxShell in the stack of the dispatcher.
549 If possible this is flushed before.
551 [Return value]
553 sal_uInt16 == USRT_MAX
554 The SfxShell is not on this SfxDispatcher.
556 < USHRT_MAX
557 Position of the SfxShell on the Dispatcher
558 from the top count stating with 0.
562 SFX_STACK(SfxDispatcher::GetShellLevel);
563 Flush();
565 for ( sal_uInt16 n = 0; n < pImp->aStack.size(); ++n )
566 if ( *( pImp->aStack.rbegin() + n ) == &rShell )
567 return n;
568 if ( pImp->pParent )
570 sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
571 if ( nRet == USHRT_MAX )
572 return nRet;
573 return nRet + pImp->aStack.size();
576 return USHRT_MAX;
579 //--------------------------------------------------------------------
580 SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
582 /* [Description]
584 Returns a pointer to the <SfxShell> which is at the position nIdx
585 (from the top, last pushed is 0) on the stack.
587 Thus the SfxDispatcher is not flushed.
589 Is the stack not deep enough a NULL-Pointer is returned.
593 sal_uInt16 nShellCount = pImp->aStack.size();
594 if ( nIdx < nShellCount )
595 return *(pImp->aStack.rbegin() + nIdx);
596 else if ( pImp->pParent )
597 return pImp->pParent->GetShell( nIdx - nShellCount );
598 return 0;
601 //--------------------------------------------------------------------
602 SfxBindings* SfxDispatcher::GetBindings() const
604 /* [Description]
606 This method returns a pointer to the <SfxBinding> Instance on which the
607 SfxDispatcher is curretly bound. A SfxDispatcher is only bound to
608 the SfxBindings when it is <UI-aktiv>. If it is not UI-active,
609 a NULL-pointer is returned.
611 The returned pointer is only valid in the immediate context of the method
612 call.
616 if ( pImp->pFrame )
617 return &pImp->pFrame->GetBindings();
618 else
619 return NULL;
622 //--------------------------------------------------------------------
623 SfxViewFrame* SfxDispatcher::GetFrame() const
625 /* [Description]
627 Returns a pointer to the <SfxViewFrame> instance, which belongs to
628 this SfxDispatcher. If it is about the application dispatcher,
629 a NULL-pointer is returned.
633 return pImp->pFrame;
636 //--------------------------------------------------------------------
637 void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ )
639 /* [Description]
641 This method controls the activation of a dispatcher.
643 Since the application dispatcher is always active, either as a sub
644 dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
645 activated as a whole, instead only its individual <SfxShell>s at
646 <SfxDispatcher::Push(SfxShell&)>.
648 When activating a SfxDispatcher all of the SfxShells located on its stack
649 are called with the handler <SfxShell::Activate(sal_Bool)>, starting with
650 the lowest.
654 SFX_STACK(SfxDispatcher::DoActivate);
655 if ( bMDI )
657 #ifdef DBG_UTIL
658 OStringBuffer sTemp("Activate Dispatcher ");
659 sTemp.append(reinterpret_cast<sal_Int64>(this));
660 OSL_TRACE("%s", sTemp.getStr());
661 DBG_ASSERT( !pImp->bActive, "Activation error" );
662 #endif
663 pImp->bActive = sal_True;
664 pImp->bUpdated = sal_False;
665 SfxBindings* pBindings = GetBindings();
666 if ( pBindings )
668 pBindings->SetDispatcher(this);
669 pBindings->SetActiveFrame( pImp->pFrame->GetFrame().GetFrameInterface() );
672 else
674 #ifdef DBG_UTIL
675 OStringBuffer sTemp("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("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("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 OUString& 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 HAVE_FEATURE_DESKTOP
1217 if ( pImp->pFrame )
1219 SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
1220 if ( pTop && pTop->GetBindings().GetDispatcher() == this )
1222 SfxFrame& rFrame = pTop->GetFrame();
1223 if ( rFrame.IsMenuBarOn_Impl() )
1225 com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
1226 if ( xPropSet.is() )
1228 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1229 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1230 aValue >>= xLayoutManager;
1231 if ( xLayoutManager.is() )
1233 OUString aMenuBarURL( "private:resource/menubar/menubar" );
1234 if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
1235 xLayoutManager->createElement( aMenuBarURL );
1241 #endif
1244 //--------------------------------------------------------------------
1245 void SfxDispatcher::Update_Impl( sal_Bool bForce )
1247 SFX_STACK(SfxDispatcher::Update_Impl);
1249 Flush();
1251 if ( !pImp->pFrame )
1252 return;
1254 SFX_APP(); // -Wall is this required???
1255 SfxDispatcher *pDisp = this;
1256 sal_Bool bUpdate = bForce;
1257 while ( pDisp && pDisp->pImp->pFrame )
1259 SfxWorkWindow *pWork = pDisp->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1260 SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1261 if ( pAct == pDisp || pAct == this )
1263 if ( !bUpdate )
1264 bUpdate = !pDisp->pImp->bUpdated;
1265 pDisp->pImp->bUpdated = sal_True;
1267 else
1268 break;
1270 pDisp = pDisp->pImp->pParent;
1273 if ( !bUpdate || pImp->pFrame->GetFrame().IsClosing_Impl() )
1274 return;
1276 SfxViewFrame* pTop = pImp->pFrame ? pImp->pFrame->GetTopViewFrame() : NULL;
1277 sal_Bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
1279 if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
1280 // keep own tools internally for collecting
1281 GetBindings()->GetDispatcher()->pImp->bUpdated = sal_False;
1283 SfxBindings* pBindings = GetBindings();
1284 if ( pBindings )
1285 pBindings->DENTERREGISTRATIONS();
1287 com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame = pBindings->GetActiveFrame();
1288 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, com::sun::star::uno::UNO_QUERY );
1289 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1290 if ( xPropSet.is() )
1294 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1295 aValue >>= xLayoutManager;
1297 catch (const com::sun::star::uno::Exception&)
1302 if ( xLayoutManager.is() )
1303 xLayoutManager->lock();
1305 sal_Bool bIsIPActive = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1306 SfxInPlaceClient *pClient = pImp->pFrame ? pImp->pFrame->GetViewShell()->GetUIActiveClient() : NULL;
1307 if ( bUIActive && /* !bIsIPActive && */ ( !pClient || !pClient->IsObjectUIActive() ) )
1308 SetMenu_Impl();
1310 SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1311 SfxWorkWindow *pTaskWin = pImp->pFrame->GetTopFrame().GetWorkWindow_Impl();
1312 pTaskWin->ResetStatusBar_Impl();
1314 SfxDispatcher *pDispat = this;
1315 while ( pDispat )
1317 SfxWorkWindow *pWork = pDispat->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1318 SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1319 if ( pAct == pDispat || pAct == this )
1321 pWork->ResetObjectBars_Impl();
1322 pWork->ResetChildWindows_Impl();
1325 pDispat = pDispat->pImp->pParent;
1328 sal_Bool bIsActive = sal_False;
1329 SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1330 pDispat = this;
1331 while ( pActDispat && !bIsActive )
1333 if ( pDispat == pActDispat )
1334 bIsActive = sal_True;
1335 pActDispat = pActDispat->pImp->pParent;
1338 _Update_Impl( bUIActive, !bIsIPActive, bIsIPActive, pTaskWin );
1339 if ( bUIActive || bIsActive )
1340 pWorkWin->UpdateObjectBars_Impl();
1342 if ( pBindings )
1343 pBindings->DLEAVEREGISTRATIONS();
1345 if ( xLayoutManager.is() )
1346 xLayoutManager->unlock();
1348 return;
1351 void SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp, sal_Bool bIsIPOwner, SfxWorkWindow *pTaskWin )
1353 SFX_APP();
1354 SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1355 sal_Bool bIsActive = sal_False;
1356 sal_Bool bIsTaskActive = sal_False;
1357 SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1358 SfxDispatcher *pDispat = this;
1359 while ( pActDispat && !bIsActive )
1361 if ( pDispat == pActDispat )
1362 bIsActive = sal_True;
1363 pActDispat = pActDispat->pImp->pParent;
1366 if ( pImp->pParent && !pImp->bQuiet /* && bUIActive */ )
1367 pImp->pParent->_Update_Impl( bUIActive, bIsMDIApp, bIsIPOwner, pTaskWin );
1369 for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1370 pImp->aObjBars[n].nResId = 0;
1371 pImp->aChildWins.clear();
1373 // bQuiet : own shells aren't considered for UI and SlotServer
1374 // bNoUI: own Shells aren't considered fors UI
1375 if ( pImp->bQuiet || pImp->bNoUI || (pImp->pFrame && pImp->pFrame->GetObjectShell()->IsPreview()) )
1376 return;
1378 sal_uInt32 nStatBarId=0;
1379 SfxShell *pStatusBarShell = NULL;
1381 SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() );
1382 sal_uInt16 nTotCount = pImp->aStack.size();
1383 for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
1385 SfxShell *pShell = GetShell( nShell-1 );
1386 SfxInterface *pIFace = pShell->GetInterface();
1388 // don't consider shells if "Hidden" oder "Quiet"
1389 sal_Bool bReadOnlyShell = IsReadOnlyShell_Impl( nShell-1 );
1390 sal_uInt16 nNo;
1391 for ( nNo = 0; pIFace && nNo<pIFace->GetObjectBarCount(); ++nNo )
1393 sal_uInt16 nPos = pIFace->GetObjectBarPos(nNo);
1394 if ( bReadOnlyShell && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
1395 continue;
1397 // check whether toolbar needs activation of a special feature
1398 sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
1399 if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1400 continue;
1402 // check for toolboxes that are exclusively for a viewer
1403 if ( pImp->pFrame)
1405 sal_Bool bViewerTbx = SFX_VISIBILITY_VIEWER == ( nPos & SFX_VISIBILITY_VIEWER );
1406 SfxObjectShell* pSh = pImp->pFrame->GetObjectShell();
1407 SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, sal_False );
1408 sal_Bool bIsViewer = pItem && pItem->GetValue();
1409 if ( bIsViewer != bViewerTbx )
1410 continue;
1413 // always register toolbars, allows to switch them on
1414 sal_Bool bVisible = pIFace->IsObjectBarVisible(nNo);
1415 if ( !bVisible )
1416 nPos &= SFX_POSITION_MASK;
1418 SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
1419 rBar.nMode = nPos;
1420 rBar.nResId = pIFace->GetObjectBarResId(nNo).GetId();
1421 const OUString *pName = pIFace->GetObjectBarName(nNo);
1422 if ( pName )
1423 rBar.aName = *pName;
1424 else
1425 rBar.aName = "";
1426 rBar.pIFace = pIFace;
1428 if ( bUIActive || bIsActive )
1430 pWorkWin->SetObjectBar_Impl(
1431 nPos, rBar.nResId, rBar.pIFace, &rBar.aName );
1434 if ( !bVisible )
1435 rBar.nResId = 0;
1438 for ( nNo=0; pIFace && nNo<pIFace->GetChildWindowCount(); nNo++ )
1440 sal_uInt32 nId = pIFace->GetChildWindowId(nNo);
1441 const SfxSlot *pSlot = pSlotPool->GetSlot( (sal_uInt16) nId );
1442 SAL_WARN_IF( !pSlot, "sfx.control", "Childwindow slot missing: " << nId );
1443 if ( bReadOnlyShell )
1445 // only show ChildWindows if their slot is allowed for readonly documents
1446 if ( pSlot && !pSlot->IsMode( SFX_SLOT_READONLYDOC ) )
1447 continue;
1450 sal_uInt32 nFeature = pIFace->GetChildWindowFeature(nNo);
1451 if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1452 continue;
1454 // slot decides whether a ChildWindow is shown when document is OLE server or OLE client
1455 sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
1456 if( pSlot )
1458 if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
1460 if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
1461 nMode |= SFX_VISIBILITY_CLIENT;
1463 else
1465 if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
1466 nMode |= SFX_VISIBILITY_SERVER;
1470 if ( bUIActive || bIsActive )
1471 pWorkWin->SetChildWindowVisible_Impl( nId, sal_True, nMode );
1472 if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
1473 pImp->aChildWins.push_back( nId );
1476 if ( bIsMDIApp || bIsIPOwner )
1478 sal_uInt32 nId = pIFace->GetStatusBarResId().GetId();
1479 if ( nId )
1481 nStatBarId = nId;
1482 pStatusBarShell = pShell;
1487 for ( sal_uInt16 nPos=0; nPos<SFX_OBJECTBAR_MAX; nPos++ )
1489 SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos];
1490 if ( rFixed.nResId )
1492 SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos];
1493 rBar = rFixed;
1494 pWorkWin->SetObjectBar_Impl( rFixed.nMode,
1495 rFixed.nResId, rFixed.pIFace, &rFixed.aName );
1499 if ( pTaskWin && ( bIsMDIApp || bIsIPOwner ) )
1501 SfxDispatcher *pActDispatcher = pTaskWin->GetBindings().GetDispatcher_Impl();
1502 SfxDispatcher *pDispatcher = this;
1503 while ( pActDispatcher && !bIsTaskActive )
1505 if ( pDispatcher == pActDispatcher )
1506 bIsTaskActive = sal_True;
1507 pActDispatcher = pActDispatcher->pImp->pParent;
1510 if ( bIsTaskActive && nStatBarId && pImp->pFrame )
1512 // internal frames also may control statusbar
1513 SfxBindings& rBindings = pImp->pFrame->GetBindings();
1514 pImp->pFrame->GetFrame().GetWorkWindow_Impl()->SetStatusBar_Impl( nStatBarId, pStatusBarShell, rBindings );
1519 //--------------------------------------------------------------------
1520 void SfxDispatcher::FlushImpl()
1522 /* [Description]
1524 Helper method to execute the outstanding push and pop commands.
1528 DBG_PROFSTART(SfxDispatcherFlush);
1529 SFX_STACK(SfxDispatcher::FlushImpl);
1531 OSL_TRACE("Flushing dispatcher!");
1533 pImp->aTimer.Stop();
1535 if ( pImp->pParent )
1536 pImp->pParent->Flush();
1538 pImp->bFlushing = !pImp->bFlushing;
1539 if ( !pImp->bFlushing )
1541 pImp->bFlushing = sal_True;
1542 DBG_PROFSTOP(SfxDispatcherFlush);
1543 return;
1546 SfxApplication *pSfxApp = SFX_APP();
1548 // Re-build the true stack in the first round
1549 std::deque<SfxToDo_Impl> aToDoCopy;
1550 sal_Bool bModify = sal_False;
1551 for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
1553 bModify = sal_True;
1555 if(i->bPush)
1557 // Actually push
1558 DBG_ASSERT( std::find(pImp->aStack.begin(), pImp->aStack.end(), i->pCluster) == pImp->aStack.end(),
1559 "pushed SfxShell already on stack" );
1560 pImp->aStack.push_back(i->pCluster);
1561 i->pCluster->SetDisableFlags(pImp->nDisableFlags);
1563 // Mark the moved shell
1564 aToDoCopy.push_front(*i);
1566 else
1568 // Actually pop
1569 SfxShell* pPopped = 0;
1570 bool bFound = false;
1573 DBG_ASSERT( !pImp->aStack.empty(), "popping from empty stack" );
1574 pPopped = pImp->aStack.back();
1575 pImp->aStack.pop_back();
1576 pPopped->SetDisableFlags( 0 );
1577 bFound = (pPopped == i->pCluster);
1579 // Mark the moved Shell
1580 aToDoCopy.push_front(SfxToDo_Impl(sal_False, i->bDelete, sal_False, *pPopped));
1582 while(i->bUntil && !bFound);
1583 DBG_ASSERT( bFound, "wrong SfxShell popped" );
1586 pImp->aToDoStack.clear();
1588 // Invalidate bindings, if possible
1589 if ( !pSfxApp->IsDowning() )
1591 if ( bModify )
1593 pImp->pCachedServ1 = 0;
1594 pImp->pCachedServ2 = 0;
1597 InvalidateBindings_Impl( bModify );
1600 pImp->bFlushing = sal_False;
1601 pImp->bUpdated = sal_False; // not only when bModify, if Doc/Template-Config
1602 bFlushed = sal_True;
1603 OSL_TRACE("Successfully flushed dispatcher!");
1605 //fdo#70703 FlushImpl may call back into itself so use aToDoCopyStack to talk
1606 //to outer levels of ourself. If DoActivate_Impl/DoDeactivate_Impl deletes
1607 //an entry, then they will walk back up aToDoCopyStack and set outer
1608 //levels's entries to bDeleted
1609 aToDoCopyStack.push_back(aToDoCopy);
1610 std::deque<SfxToDo_Impl>& rToDoCopy = aToDoCopyStack.back();
1611 // Activate the Shells and possible delete them in the 2nd round
1612 for(std::deque<SfxToDo_Impl>::reverse_iterator i = rToDoCopy.rbegin(); i != rToDoCopy.rend(); ++i)
1614 if (i->bDeleted)
1615 continue;
1616 if (!pImp->bActive)
1617 continue;
1618 if (i->bPush)
1619 i->pCluster->DoActivate_Impl(pImp->pFrame, sal_True);
1620 else
1621 i->pCluster->DoDeactivate_Impl(pImp->pFrame, sal_True);
1624 aToDoCopy = aToDoCopyStack.back();
1625 aToDoCopyStack.pop_back();
1627 for(std::deque<SfxToDo_Impl>::reverse_iterator i = aToDoCopy.rbegin(); i != aToDoCopy.rend(); ++i)
1629 if (i->bDelete && !i->bDeleted)
1631 if (!aToDoCopyStack.empty())
1633 //fdo#70703 if there is an outer FlushImpl then inform it that
1634 //we have deleted this cluster
1635 for (std::deque< std::deque<SfxToDo_Impl> >::iterator aI = aToDoCopyStack.begin();
1636 aI != aToDoCopyStack.end(); ++aI)
1638 std::deque<SfxToDo_Impl> &v = *aI;
1639 for(std::deque<SfxToDo_Impl>::iterator aJ = v.begin(); aJ != v.end(); ++aJ)
1641 if (aJ->pCluster == i->pCluster)
1642 aJ->bDeleted = true;
1646 delete i->pCluster;
1649 sal_Bool bAwakeBindings = !aToDoCopy.empty();
1650 if( bAwakeBindings )
1651 aToDoCopy.clear();
1653 // If more changes have occurred on the stach when
1654 // Activate/Deactivate/Delete:
1655 if (!bFlushed)
1656 // If Push/Pop hs been called by someone, theb also EnterReg was called!
1657 FlushImpl();
1659 if( bAwakeBindings && GetBindings() )
1660 GetBindings()->DLEAVEREGISTRATIONS();
1661 DBG_PROFSTOP(SfxDispatcherFlush);
1663 for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1664 pImp->aFixedObjBars[n].nResId = 0;
1666 SAL_INFO("sfx.control", "SfxDispatcher(" << this << ")::Flush() done");
1669 //--------------------------------------------------------------------
1670 void SfxDispatcher::SetSlotFilter
1672 // HACK(hier muss mal ein enum rein) ???
1673 sal_Bool bEnable, /* sal_True:
1674 only enable specified slots,
1675 disable all other
1677 sal_False:
1678 disable specified slots,
1679 first enable all other
1681 sal_uInt16 nCount, // Number of SIDs in the following Array
1682 const sal_uInt16* pSIDs // sorted Array of 'nCount' SIDs
1685 /* [Description]
1687 With this method a filter set, the target slots can be enabled or disabled.
1688 The passed array must be retained until the destructor or the next
1689 <SetSlotFilter()>, it is not deleted from the dispatcher, so it can thus be
1690 static.
1692 In read-only documents the quasi ReadOnlyDoc Flag of slots can be
1693 overturned by the use of 'bEnable == 2', so this will be displayed again.
1694 On the other slots it has no effect.
1696 [Example]
1698 Targeted disabling of Slots 1, 2 and 3:
1700 static sal_uInt16 const pSIDs[] = { 1, 2, 3 };
1701 pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
1703 only permit Slots 5, 6 and 7:
1705 static sal_uInt16 const pSIDs[] = { 5, 6, 7 };
1706 pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
1708 Turn-off Filter:
1710 pDisp->SetSlotFilter();
1714 #ifdef DBG_UTIL
1715 // Check Array
1716 for ( sal_uInt16 n = 1; n < nCount; ++n )
1717 DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sorted" );
1718 #endif
1720 if ( pImp->pFilterSIDs )
1721 pImp->pFilterSIDs = 0;
1723 pImp->bFilterEnabling = bEnable;
1724 pImp->nFilterCount = nCount;
1725 pImp->pFilterSIDs = pSIDs;
1727 GetBindings()->InvalidateAll(sal_True);
1730 //--------------------------------------------------------------------
1731 extern "C"
1732 #ifdef WNT
1733 int _cdecl
1734 #else
1736 #endif
1738 SfxCompareSIDs_Impl( const void* pSmaller, const void* pBigger )
1740 return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
1743 //--------------------------------------------------------------------
1744 sal_Bool SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
1746 /* [Description]
1748 Searches for 'nSID' in the Filter set by <SetSlotFilter()> and
1749 returns sal_True, if the SIDis allowed, or sal_False, if it is
1750 disabled by the Filter.
1752 [Return value]
1753 sal_Bool 0 => disabled
1754 1 => enabled
1755 2 => enabled even if ReadOnlyDoc
1759 // no filter?
1760 if ( 0 == pImp->nFilterCount )
1761 // => all SIDs allowed
1762 return sal_True;
1764 // search
1765 sal_Bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
1766 sizeof(sal_uInt16), SfxCompareSIDs_Impl );
1768 // even if ReadOnlyDoc
1769 if ( 2 == pImp->bFilterEnabling )
1770 return bFound ? 2 : 1;
1771 // Otherwise after Negative/Positive Filter
1772 return pImp->bFilterEnabling ? bFound : !bFound;
1775 //--------------------------------------------------------------------
1776 sal_Bool SfxDispatcher::_TryIntercept_Impl
1778 sal_uInt16 nSlot, // Slot-Id to search for
1779 SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
1780 sal_Bool bSelf
1783 // Maybe the parent is also belongs to a component
1784 SfxDispatcher *pParent = pImp->pParent;
1785 sal_uInt16 nLevels = pImp->aStack.size();
1786 while ( pParent && pParent->pImp->pFrame )
1788 if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
1790 // Components may be intercepted
1791 if ( pParent->_TryIntercept_Impl( nSlot, rServer, sal_True ) )
1793 // The own shells are added to the Shell Level
1794 rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
1795 return sal_True;
1797 else
1798 // No further Interception
1799 break;
1801 else
1802 nLevels = nLevels + pParent->pImp->aStack.size();
1804 pParent = pParent->pImp->pParent;
1807 if ( bSelf )
1809 // Query the ComponentViewShell
1810 Flush();
1811 SfxShell *pObjShell = GetShell(0);
1812 SfxInterface *pIFace = pObjShell->GetInterface();
1813 const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
1815 if ( pSlot )
1817 rServer.SetSlot(pSlot);
1818 rServer.SetShellLevel(0);
1819 return sal_True;
1823 return sal_False;
1826 sal_Bool SfxDispatcher::_FindServer
1828 sal_uInt16 nSlot, // Slot-Id to search for
1829 SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
1830 sal_Bool bModal // Dispite ModalMode
1833 /* [Description]
1835 This helper method searches for the <Slot-Server> which currently serves
1836 the nSlot. As the result, rServe is filled accordingly.
1838 If known the SfxInterface which is currently served by nSlot can be
1839 passed along.
1841 The SfxDispatcher is flushed while searching for nSlot.
1843 [Return value]
1846 sal_Bool sal_True
1847 The Slot was found, rServer is valid.
1849 sal_False
1850 The Slot is currently not served, rServer is invalid.
1854 SFX_STACK(SfxDispatcher::_FindServer);
1856 // Dispatcher locked? (nevertheless let SID_HELP_PI through)
1857 if ( IsLocked(nSlot) )
1859 pImp->bInvalidateOnUnlock = sal_True;
1860 return sal_False;
1863 // Count the number of Shells in the linked dispatchers.
1864 Flush();
1865 sal_uInt16 nTotCount = pImp->aStack.size();
1866 if ( pImp->pParent )
1868 SfxDispatcher *pParent = pImp->pParent;
1869 while ( pParent )
1871 nTotCount = nTotCount + pParent->pImp->aStack.size();
1872 pParent = pParent->pImp->pParent;
1876 // Verb-Slot?
1877 if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
1879 for ( sal_uInt16 nShell = 0;; ++nShell )
1881 SfxShell *pSh = GetShell(nShell);
1882 if ( pSh == NULL )
1883 return false;
1884 if ( pSh->ISA(SfxViewShell) )
1886 const SfxSlot* pSlot = pSh->GetVerbSlot_Impl(nSlot);
1887 if ( pSlot )
1889 rServer.SetShellLevel(nShell);
1890 rServer.SetSlot( pSlot );
1891 return true;
1897 // SID check against set filter
1898 sal_uInt16 nSlotEnableMode=0;
1899 if ( pImp->pFrame )
1901 nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
1902 if ( 0 == nSlotEnableMode )
1903 return sal_False;
1906 // In Quiet-Mode only Parent-Dispatcher
1907 if ( pImp->bQuiet )
1909 if ( pImp->pParent )
1911 sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
1912 rServer.SetShellLevel
1913 ( rServer.GetShellLevel() + pImp->aStack.size() );
1914 return bRet;
1916 else
1917 return sal_False;
1920 sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly );
1922 // search through all the shells of the chained dispatchers
1923 // from top to bottom
1924 sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.size() : 0;
1925 for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
1927 SfxShell *pObjShell = GetShell(i);
1928 SfxInterface *pIFace = pObjShell->GetInterface();
1929 const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
1931 if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
1932 return sal_False;
1934 if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
1935 return sal_False;
1937 if ( pSlot )
1939 // Slot belongs to Container?
1940 bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
1941 bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1943 // Shell belongs to Server?
1944 // AppDispatcher or IPFrame-Dispatcher
1945 bool bIsServerShell = !pImp->pFrame || bIsInPlace;
1947 // Of course ShellServer-Slots are also executable even when it is
1948 // excecuted on a container dispatcher without a IPClient.
1949 if ( !bIsServerShell )
1951 SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
1952 bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
1955 // Shell belongs to Container?
1956 // AppDispatcher or no IPFrameDispatcher
1957 bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
1958 // Shell and Slot match
1959 if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
1960 ( !bIsContainerSlot && bIsServerShell ) ) )
1961 pSlot = 0;
1964 if ( pSlot )
1966 rServer.SetSlot(pSlot);
1967 rServer.SetShellLevel(i);
1968 return sal_True;
1972 return sal_False;
1975 //--------------------------------------------------------------------
1976 sal_Bool SfxDispatcher::_FillState
1978 const SfxSlotServer& rSvr, // <Slot-Server> to query
1979 SfxItemSet& rState, // <SfxItemSet> to be filled
1980 const SfxSlot* pRealSlot // The actual Slot if possible
1983 /* [Description]
1985 Helper method to obtain the status of the <Slot-Server>s rSvr.
1986 The required slots IDs (partly converted to Which-IDs of the pool)
1987 must be present in rstate.
1989 The SfxDispatcher is flushed before the query.
1993 SFX_STACK(SfxDispatcher::_FillState);
1995 DBG_PROFSTART(SfxDispatcherFillState);
1997 const SfxSlot *pSlot = rSvr.GetSlot();
1998 if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
2000 pImp->bInvalidateOnUnlock = sal_True;
2001 DBG_PROFSTOP(SfxDispatcherFillState);
2002 return sal_False;
2005 if ( pSlot )
2007 DBG_ASSERT(bFlushed, "Dispatcher not flushed after retrieving slot servers!");
2008 if ( !bFlushed )
2009 return sal_False;
2011 // Determine the object and call the Message of this object
2012 SfxShell *pSh = GetShell(rSvr.GetShellLevel());
2013 DBG_ASSERT(pSh, "ObjectShell not found");
2015 SfxStateFunc pFunc;
2017 if (pRealSlot)
2018 pFunc = pRealSlot->GetStateFnc();
2019 else
2020 pFunc = pSlot->GetStateFnc();
2022 pSh->CallState( pFunc, rState );
2023 #ifdef DBG_UTIL
2024 // To examine the conformity of IDL (SlotMap) and current Items
2025 if ( DbgIsAssertWarning() && rState.Count() )
2027 SfxInterface *pIF = pSh->GetInterface();
2028 SfxItemIter aIter( rState );
2029 for ( const SfxPoolItem *pItem = aIter.FirstItem();
2030 pItem;
2031 pItem = aIter.NextItem() )
2033 if ( !IsInvalidItem(pItem) && !pItem->ISA(SfxVoidItem) )
2035 sal_uInt16 nSlotId = rState.GetPool()->GetSlotId(pItem->Which());
2036 if ( !pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()) )
2038 OStringBuffer aMsg("item-type unequal to IDL (=> no BASIC)");
2039 aMsg.append("\nwith SID: ");
2040 aMsg.append(static_cast<sal_Int32>(nSlotId));
2041 aMsg.append("\nin ");
2042 aMsg.append(pIF->GetClassName());
2043 DbgOut(aMsg.getStr(), DBG_OUT_ERROR, __FILE__, __LINE__);
2048 #endif
2050 DBG_PROFSTOP(SfxDispatcherFillState);
2051 return sal_True;
2054 DBG_PROFSTOP(SfxDispatcherFillState);
2055 return sal_False;
2058 SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, const Point *pPos )
2060 SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
2061 sal_uInt16 nShLevel = 0;
2062 SfxShell *pSh;
2064 if ( rDisp.pImp->bQuiet )
2066 nConfigId = 0;
2067 nShLevel = rDisp.pImp->aStack.size();
2070 Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2071 for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2073 const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
2074 if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
2076 return SfxPopupMenuManager::Popup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2079 return 0;
2083 //----------------------------------------------------------------------
2084 void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, Window *pWin, const Point *pPos )
2086 SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
2087 sal_uInt16 nShLevel = 0;
2088 SfxShell *pSh;
2090 if ( rDisp.pImp->bQuiet )
2092 nConfigId = 0;
2093 nShLevel = rDisp.pImp->aStack.size();
2096 Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2097 for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2099 const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
2100 if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
2102 SfxPopupMenuManager::ExecutePopup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2103 return;
2108 //----------------------------------------------------------------------
2109 void SfxDispatcher::ExecutePopup( const ResId &rId, Window *pWin, const Point *pPos )
2111 Window *pWindow = pWin ? pWin : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2112 SfxPopupMenuManager::ExecutePopup( rId, GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2115 //--------------------------------------------------------------------
2116 void SfxDispatcher::Lock( sal_Bool bLock )
2118 /* [Description]
2120 With this method the SfxDispatcher can be locked and released. A locked
2121 SfxDispatcher does not perform <SfxRequest>s and does no longer provide
2122 status information. It behaves as if all the slots were disabled.
2126 SfxBindings* pBindings = GetBindings();
2127 if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
2129 if ( pBindings )
2130 pBindings->InvalidateAll(sal_True);
2131 pImp->bInvalidateOnUnlock = sal_False;
2133 else if ( pBindings )
2134 pBindings->InvalidateAll(sal_False);
2135 pImp->bLocked = bLock;
2136 if ( !bLock )
2138 for(size_t i = 0; i < pImp->aReqArr.size(); ++i)
2139 pImp->xPoster->Post(pImp->aReqArr[i]);
2140 pImp->aReqArr.clear();
2144 sal_uInt32 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
2146 return pImp->aObjBars[nPos].nResId;
2149 //-------------------------------------------------------------------------
2150 void SfxDispatcher::HideUI( sal_Bool bHide )
2152 sal_Bool bWasHidden = pImp->bNoUI;
2153 pImp->bNoUI = bHide;
2154 if ( pImp->pFrame )
2156 SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
2157 if ( pTop && pTop->GetBindings().GetDispatcher() == this )
2159 SfxFrame& rFrame = pTop->GetFrame();
2160 if ( rFrame.IsMenuBarOn_Impl() )
2162 com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
2163 if ( xPropSet.is() )
2165 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
2166 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
2167 aValue >>= xLayoutManager;
2168 if ( xLayoutManager.is() )
2169 xLayoutManager->setVisible( !bHide );
2175 if ( bHide != bWasHidden )
2176 Update_Impl( sal_True );
2179 void SfxDispatcher::SetReadOnly_Impl( sal_Bool bOn )
2181 pImp->bReadOnly = bOn;
2184 sal_Bool SfxDispatcher::GetReadOnly_Impl() const
2186 return pImp->bReadOnly;
2189 //-------------------------------------------------------------------------
2190 void SfxDispatcher::SetQuietMode_Impl( sal_Bool bOn )
2192 /* [Description]
2194 With 'bOn' the Dispatcher is quasi dead and transfers everything to the
2195 Parent-Dispatcher.
2199 pImp->bQuiet = bOn;
2200 SfxBindings* pBindings = GetBindings();
2201 if ( pBindings )
2202 pBindings->InvalidateAll(sal_True);
2205 SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
2207 SfxShell *pShell = 0;
2208 const SfxSlot *pSlot = 0;
2209 if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
2211 rpState = pShell->GetSlotState(nSlot);
2212 if ( !rpState )
2213 return SFX_ITEM_DISABLED;
2214 else
2215 return SFX_ITEM_AVAILABLE;
2218 return SFX_ITEM_DISABLED;
2221 SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno::Any& rAny )
2223 SfxShell *pShell = 0;
2224 const SfxSlot *pSlot = 0;
2225 if ( GetShellAndSlot_Impl( nSID, &pShell, &pSlot, sal_False, sal_False ) )
2227 const SfxPoolItem* pItem( 0 );
2229 pItem = pShell->GetSlotState( nSID );
2230 if ( !pItem )
2231 return SFX_ITEM_DISABLED;
2232 else
2234 ::com::sun::star::uno::Any aState;
2235 if ( !pItem->ISA(SfxVoidItem) )
2237 sal_uInt16 nSubId( 0 );
2238 SfxItemPool& rPool = pShell->GetPool();
2239 sal_uInt16 nWhich = rPool.GetWhich( nSID );
2240 if ( rPool.GetMetric( nWhich ) == SFX_MAPUNIT_TWIP )
2241 nSubId |= CONVERT_TWIPS;
2242 pItem->QueryValue( aState, (sal_uInt8)nSubId );
2244 rAny = aState;
2246 return SFX_ITEM_AVAILABLE;
2250 return SFX_ITEM_DISABLED;
2253 sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
2255 sal_uInt16 nShellCount = pImp->aStack.size();
2256 if ( nShell < nShellCount )
2258 SfxShell* pShell = *( pImp->aStack.rbegin() + nShell );
2259 if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
2260 return sal_False;
2261 else
2262 return pImp->bReadOnly;
2264 else if ( pImp->pParent )
2265 return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
2266 return sal_True;
2269 void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
2271 Flush();
2273 sal_uInt16 nCount = pImp->aStack.size();
2274 for ( sal_uInt16 n=0; n<nCount; ++n )
2276 if ( pImp->aStack[n] == &rShell )
2278 pImp->aStack.erase( pImp->aStack.begin() + n );
2279 rShell.SetDisableFlags( 0 );
2280 rShell.DoDeactivate_Impl(pImp->pFrame, sal_True);
2281 break;
2285 if ( !SFX_APP()->IsDowning() )
2287 pImp->bUpdated = sal_False;
2288 pImp->pCachedServ1 = 0;
2289 pImp->pCachedServ2 = 0;
2290 InvalidateBindings_Impl(sal_True);
2294 void SfxDispatcher::InvalidateBindings_Impl( sal_Bool bModify )
2296 // App-Dispatcher?
2297 if ( IsAppDispatcher() )
2299 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst();
2300 pFrame;
2301 pFrame = SfxViewFrame::GetNext( *pFrame ) )
2302 pFrame->GetBindings().InvalidateAll(bModify);
2304 else
2306 SfxDispatcher *pDisp = GetBindings()->GetDispatcher_Impl();
2307 while ( pDisp )
2309 if ( pDisp == this )
2311 GetBindings()->InvalidateAll( bModify );
2312 break;
2315 pDisp = pDisp->pImp->pParent;
2320 sal_Bool SfxDispatcher::IsUpdated_Impl() const
2322 return pImp->bUpdated;
2325 void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
2327 pImp->nDisableFlags = nFlags;
2328 for ( SfxShellStack_Impl::const_reverse_iterator it = pImp->aStack.rbegin(); it != pImp->aStack.rend(); ++it )
2329 (*it)->SetDisableFlags( nFlags );
2332 sal_uInt32 SfxDispatcher::GetDisableFlags() const
2334 return pImp->nDisableFlags;
2337 SfxModule* SfxDispatcher::GetModule() const
2339 for ( sal_uInt16 nShell = 0;; ++nShell )
2341 SfxShell *pSh = GetShell(nShell);
2342 if ( pSh == NULL )
2343 return 0;
2344 if ( pSh->ISA(SfxModule) )
2345 return (SfxModule*) pSh;
2349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */