Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_features.h>
21 :
22 : #include <algorithm>
23 : #include <deque>
24 : #include <vector>
25 :
26 : #include <stdarg.h>
27 : #include <stdio.h>
28 : #include <stdlib.h>
29 :
30 : #include <com/sun/star/beans/XPropertySet.hpp>
31 : #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
32 : #include <com/sun/star/frame/XLayoutManager.hpp>
33 :
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>
61 :
62 : #include <appdata.hxx>
63 : #include <sfxtypes.hxx>
64 : #include <slotserv.hxx>
65 : #include <workwin.hxx>
66 :
67 : typedef std::vector<SfxShell*> SfxShellStack_Impl;
68 :
69 : typedef std::vector<SfxRequest*> SfxRequestPtrArray;
70 :
71 : struct SfxToDo_Impl
72 : {
73 : SfxShell* pCluster;
74 : bool bPush;
75 : bool bDelete;
76 : bool bDeleted;
77 : bool bUntil;
78 :
79 93781 : SfxToDo_Impl( bool bOpPush, bool bOpDelete, bool bOpUntil, SfxShell& rCluster )
80 : : pCluster(&rCluster)
81 : , bPush(bOpPush)
82 : , bDelete(bOpDelete)
83 : , bDeleted(false)
84 93781 : , bUntil(bOpUntil)
85 93781 : {}
86 : };
87 :
88 147732 : struct SfxObjectBars_Impl
89 : {
90 : sal_uInt32 nResId; // Resource - and ConfigId of the Toolbox
91 : sal_uInt16 nMode; // special visibility flags
92 : OUString aName;
93 : SfxInterface* pIFace;
94 :
95 151294 : SfxObjectBars_Impl() : nResId(0), nMode(0), pIFace(NULL) {}
96 : };
97 :
98 5819 : struct SfxDispatcher_Impl
99 : {
100 : //When the dispatched is locked, SfxRequests accumulate in aReqArr for
101 : //later dispatch when unlocked via Post
102 :
103 : //The pointers are typically deleted in Post, only if we never get around
104 : //to posting them do we delete the unposted requests.
105 : SfxRequestPtrArray aReqArr;
106 5682 : ~SfxDispatcher_Impl()
107 5682 : {
108 5682 : for (SfxRequestPtrArray::iterator aI = aReqArr.begin(), aEnd = aReqArr.end(); aI != aEnd; ++aI)
109 0 : delete *aI;
110 5682 : }
111 : const SfxSlotServer* pCachedServ1; // last called message
112 : const SfxSlotServer* pCachedServ2; // penultimate called Message
113 : SfxShellStack_Impl aStack; // active functionality
114 : Timer aTimer; // for Flush
115 : std::deque<SfxToDo_Impl> aToDoStack; // not processed Push/Pop
116 : SfxViewFrame* pFrame; // NULL or associated Frame
117 : SfxDispatcher* pParent; // AppDispatcher, NULL if possible
118 : SfxHintPosterRef xPoster; // Execute asynchronous
119 : bool bFlushing; // sal_True during Flush //?
120 : bool bUpdated; // Update_Impl has run
121 : bool bLocked; // No Execute
122 : bool bInvalidateOnUnlock; // because someone asked
123 : bool bActive; // not to be confused with set!
124 : bool* pInCallAliveFlag; // view the Destructor Stack
125 : SfxObjectBars_Impl aObjBars[SFX_OBJECTBAR_MAX];
126 : SfxObjectBars_Impl aFixedObjBars[SFX_OBJECTBAR_MAX];
127 : std::vector<sal_uInt32> aChildWins;
128 : sal_uInt32 nEventId; // EventId UserEvent
129 : bool bNoUI; // UI only from Parent Dispatcher
130 : bool bReadOnly; // Document is ReadOnly
131 : bool bQuiet; // Only use parent dispatcher
132 : bool bModal; // Only slots from parent dispatcher
133 :
134 : SfxSlotFilterState nFilterEnabling; // 1==filter enabled slots,
135 : // 2==ReadOnlyDoc overturned
136 : sal_uInt16 nFilterCount; // Number of SIDs in pFilterSIDs
137 : const sal_uInt16* pFilterSIDs; // sorted Array of SIDs
138 : sal_uInt32 nDisableFlags;
139 : bool bFlushed;
140 : std::deque< std::deque<SfxToDo_Impl> > aToDoCopyStack;
141 : };
142 :
143 : #define SFX_FLUSH_TIMEOUT 50
144 :
145 : /** This method checks if the stack of the SfxDispatchers is flushed, or if
146 : push- or pop- commands are pending.
147 : */
148 1564 : bool SfxDispatcher::IsFlushed() const
149 : {
150 1564 : return pImp->bFlushed;
151 : }
152 :
153 : /** This method performs outstanding push- and pop- commands. For <SfxShell>s,
154 : which are new on the stack, the <SfxShell::Activate(bool)> is invoked
155 : with bMDI == sal_True, for SfxShells that are removed from the stack, the
156 : <SfxShell::Deactivate(bool)> is invoked with bMDI == sal_True
157 : */
158 501716 : void SfxDispatcher::Flush()
159 : {
160 501716 : if (!pImp->bFlushed) FlushImpl();
161 501716 : }
162 :
163 : /** With this method, a <SfxShell> pushed on to the SfxDispatcher.
164 : The SfxShell is first marked for push and a timer is set up.
165 : First when the timer has couted down to zero the push
166 : ( <SfxDispatcher::Flush()> ) is actually performed and the
167 : <SfxBindings> is invalidated. While the timer is counting down
168 : the opposing push and pop commands on the same SfxShell are
169 : leveled out.
170 : */
171 44707 : void SfxDispatcher::Push(SfxShell& rShell)
172 :
173 : {
174 44707 : Pop( rShell, SFX_SHELL_PUSH );
175 44707 : }
176 :
177 : /** This method checks whether a particular <SfxShell> instance is
178 : on the SfxDispatcher.
179 :
180 : @returns sal_True The SfxShell instance is on the SfxDispatcher.
181 : sal_False The SfxShell instance is not on the SfxDispatcher.
182 : */
183 4572 : bool SfxDispatcher::IsActive(const SfxShell& rShell)
184 :
185 : {
186 4572 : return CheckVirtualStack(rShell, true);
187 : }
188 :
189 : /** With this method it can be determined whether the SfxDispatcher is
190 : locked or unlocked. A locked SfxDispatcher does not perform <SfxRequest>s
191 : and no longer provides any status information. It behaves as if all the
192 : slots are disabled.
193 :
194 : The dispatcher is also marked as blocked, if all Dispatcher are locked
195 : (<SfxApplication::LockDispatcher()>) or the associated top frame is in the
196 : modal-mode and if the specified slot are handled as frame-specific
197 : (ie, not served by the application).
198 : */
199 315056 : bool SfxDispatcher::IsLocked(sal_uInt16) const
200 : {
201 315056 : return pImp->bLocked;
202 : }
203 :
204 : /** With this method it can be determined if the SfxDispacher is the
205 : applications dispatcher.
206 :
207 : @return bool it is the application dispatcher.
208 : */
209 46122 : bool SfxDispatcher::IsAppDispatcher() const
210 : {
211 46122 : return !pImp->pFrame;
212 : }
213 :
214 : /** Helper function to check whether a slot can be executed and
215 : check the execution itself
216 : */
217 1090 : int SfxDispatcher::Call_Impl(SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, bool bRecord)
218 : {
219 : SFX_STACK(SfxDispatcher::Call_Impl);
220 :
221 : // The slot may be called (meaning enabled)
222 1090 : if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
223 : {
224 1090 : if ( GetFrame() )
225 : {
226 : // Recording may start
227 : com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame(
228 1090 : GetFrame()->GetFrame().GetFrameInterface(),
229 1090 : com::sun::star::uno::UNO_QUERY);
230 :
231 : com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
232 : xFrame,
233 2180 : com::sun::star::uno::UNO_QUERY);
234 :
235 1090 : if ( xSet.is() )
236 : {
237 1090 : com::sun::star::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
238 2180 : com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
239 2180 : com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
240 1090 : aProp >>= xSupplier;
241 1090 : if(xSupplier.is())
242 2 : xRecorder = xSupplier->getDispatchRecorder();
243 :
244 1090 : if ( bRecord && xRecorder.is() && !rSlot.IsMode(SFX_SLOT_NORECORD) )
245 1092 : rReq.Record_Impl( rShell, rSlot, xRecorder, GetFrame() );
246 1090 : }
247 : }
248 : // Get all that is needed, because the slot may not have survived the
249 : // Execute if it is a 'pseudo slot' for macros or verbs.
250 1090 : bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
251 :
252 : // API-call parentheses and document-lock during the calls
253 : {
254 : // 'this' must respond in the Destructor
255 1090 : bool bThisDispatcherAlive = true;
256 1090 : bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
257 1090 : pImp->pInCallAliveFlag = &bThisDispatcherAlive;
258 :
259 1090 : SfxExecFunc pFunc = rSlot.GetExecFnc();
260 1090 : rShell.CallExec( pFunc, rReq );
261 :
262 : // If 'this' is still alive
263 1090 : if ( bThisDispatcherAlive )
264 1090 : pImp->pInCallAliveFlag = pOldInCallAliveFlag;
265 : else
266 : {
267 0 : if ( pOldInCallAliveFlag )
268 : {
269 : // also protect nested stack frames
270 0 : *pOldInCallAliveFlag = false;
271 : }
272 :
273 : // do nothing after this object is dead
274 0 : return rReq.IsDone() ? 1 : 0;
275 : }
276 : }
277 :
278 1090 : if ( rReq.IsDone() )
279 : {
280 467 : SfxBindings *pBindings = GetBindings();
281 :
282 : // When AutoUpdate update immediately; "Pseudoslots" must not be
283 : // Autoupdate!
284 467 : if ( bAutoUpdate && pBindings )
285 : {
286 238 : const SfxSlot* pSlave = rSlot.GetLinkedSlot();
287 238 : if (pSlave)
288 : {
289 : // When enum slots take any bound slave slot
290 0 : while (!pBindings->IsBound(pSlave->GetSlotId()) && pSlave != &rSlot )
291 0 : pSlave = pSlave->GetLinkedSlot();
292 0 : pBindings->Invalidate(pSlave->GetSlotId());
293 0 : pBindings->Update(pSlave->GetSlotId());
294 : }
295 : else
296 : {
297 238 : pBindings->Invalidate(rSlot.GetSlotId());
298 238 : pBindings->Update(rSlot.GetSlotId());
299 : }
300 : }
301 :
302 467 : return sal_True;
303 : }
304 : }
305 :
306 623 : return sal_False;
307 : }
308 :
309 5819 : void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
310 : {
311 5819 : pImp.reset(new SfxDispatcher_Impl);
312 5819 : pImp->bFlushed = true;
313 :
314 5819 : pImp->pCachedServ1 = 0;
315 5819 : pImp->pCachedServ2 = 0;
316 5819 : pImp->bFlushing = false;
317 5819 : pImp->bUpdated = false;
318 5819 : pImp->bLocked = false;
319 5819 : pImp->bActive = false;
320 5819 : pImp->pParent = NULL;
321 5819 : pImp->bNoUI = false;
322 5819 : pImp->bReadOnly = false;
323 5819 : pImp->bQuiet = false;
324 5819 : pImp->bModal = false;
325 5819 : pImp->pInCallAliveFlag = 0;
326 5819 : pImp->nFilterEnabling = SFX_SLOT_FILTER_DISABLED;
327 5819 : pImp->nFilterCount = 0;
328 5819 : pImp->pFilterSIDs = 0;
329 5819 : pImp->nDisableFlags = 0;
330 :
331 5819 : pImp->pParent = pParent;
332 :
333 5819 : pImp->bInvalidateOnUnlock = false;
334 :
335 81466 : for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
336 75647 : pImp->aObjBars[n].nResId = 0;
337 :
338 5819 : GenLink aGenLink( LINK(this, SfxDispatcher, PostMsgHandler) );
339 :
340 5819 : pImp->xPoster = new SfxHintPoster(aGenLink);
341 :
342 5819 : pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
343 5819 : pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
344 5819 : }
345 :
346 303 : SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
347 : {
348 303 : Construct_Impl( pParent );
349 303 : pImp->pFrame = 0;
350 303 : }
351 :
352 : /** The constructor of the SfxDispatcher class places a stack of empty
353 : <SfxShell> pointers. It is not initially locked and is considered flushed.
354 : */
355 5516 : SfxDispatcher::SfxDispatcher(SfxViewFrame *pViewFrame)
356 : {
357 5516 : if ( pViewFrame )
358 : {
359 5516 : SfxViewFrame *pFrame = pViewFrame->GetParentViewFrame();
360 5516 : if ( pFrame )
361 0 : Construct_Impl( pFrame->GetDispatcher() );
362 : else
363 5516 : Construct_Impl( 0 );
364 : }
365 : else
366 0 : Construct_Impl( 0 );
367 5516 : pImp->pFrame = pViewFrame;
368 5516 : }
369 :
370 : /** The destructor of the SfxDispatcher class should not be called when the
371 : SfxDispatcher instance is active. It may, however, still be a <SfxShell>
372 : pointer on the stack.
373 : */
374 17046 : SfxDispatcher::~SfxDispatcher()
375 : {
376 : #ifdef DBG_UTIL
377 : OStringBuffer sTemp("Delete Dispatcher ");
378 : sTemp.append(reinterpret_cast<sal_Int64>(this));
379 : OSL_TRACE("%s", sTemp.getStr());
380 : DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
381 : #endif
382 :
383 : // So that no timer by Reschedule in PlugComm strikes the LeaveRegistrations
384 5682 : pImp->aTimer.Stop();
385 5682 : pImp->xPoster->SetEventHdl( Link() );
386 :
387 : // Notify the stack varialbles in Call_Impl
388 5682 : if ( pImp->pInCallAliveFlag )
389 0 : *pImp->pInCallAliveFlag = false;
390 :
391 : // Get bindings and application
392 5682 : SfxApplication *pSfxApp = SfxGetpApp();
393 5682 : SfxBindings* pBindings = GetBindings();
394 :
395 : // When not flushed, revive the bindings
396 5682 : if (pBindings && !pSfxApp->IsDowning() && !pImp->bFlushed)
397 5506 : pBindings->DLEAVEREGISTRATIONS();
398 :
399 : // may unregister the bindings
400 16886 : while ( pBindings )
401 : {
402 5522 : if ( pBindings->GetDispatcher_Impl() == this)
403 5514 : pBindings->SetDispatcher(0);
404 5522 : pBindings = pBindings->GetSubBindings_Impl();
405 : }
406 11364 : }
407 :
408 : /** With this method, one or more <SfxShell> are poped from the SfxDispatcher.
409 : The SfxShell is marked for popping and a timer is set up. Only when the
410 : timer has reached the end, the pop is actually performed
411 : ( <SfxDispatcher::Flush()> ) and the <SfxBindings> is invalidated.
412 : While the timer is running the opposing push and pop commands on one
413 : SfxShell cancel each other out.
414 :
415 : @param rShell the stack to take the SfxShell instance.
416 : @param nMode SFX_SHELL_POP_UNTIL
417 : Also all 'rShell' of SfxShells are taken from the
418 : stack.
419 :
420 : SFX_SHELL_POP_DELETE
421 : All SfxShells actually taken from the stack
422 : will be deleted.
423 :
424 : SFX_SHELL_PUSH (InPlace use only)
425 : The Shell is pushed.
426 : */
427 66849 : void SfxDispatcher::Pop(SfxShell& rShell, sal_uInt16 nMode)
428 : {
429 : DBG_ASSERT( rShell.GetInterface(),
430 : "pushing SfxShell without previous RegisterInterface()" );
431 :
432 66849 : bool bDelete = (nMode & SFX_SHELL_POP_DELETE) == SFX_SHELL_POP_DELETE;
433 66849 : bool bUntil = (nMode & SFX_SHELL_POP_UNTIL) == SFX_SHELL_POP_UNTIL;
434 66849 : bool bPush = (nMode & SFX_SHELL_PUSH) == SFX_SHELL_PUSH;
435 :
436 66849 : SfxApplication *pSfxApp = SfxGetpApp();
437 :
438 : SAL_INFO(
439 : "sfx.control",
440 : "-SfxDispatcher(" << this << (bPush ? ")::Push(" : ")::Pop(")
441 : << (rShell.GetInterface()
442 : ? rShell.GetInterface()->GetClassName() : SAL_STREAM(&rShell))
443 : << (bDelete ? ") with delete" : ")")
444 : << (bUntil ? " (up to)" : ""));
445 :
446 : // same shell as on top of the to-do stack?
447 66849 : if(pImp->aToDoStack.size() && pImp->aToDoStack.front().pCluster == &rShell)
448 : {
449 : // cancel inverse actions
450 46 : if ( pImp->aToDoStack.front().bPush != bPush )
451 46 : pImp->aToDoStack.pop_front();
452 : else
453 : {
454 : DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
455 : DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
456 : }
457 : }
458 : else
459 : {
460 : // Remember Action
461 66803 : pImp->aToDoStack.push_front( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
462 66803 : if (pImp->bFlushed)
463 : {
464 : OSL_TRACE("Unflushed dispatcher!");
465 33761 : pImp->bFlushed = false;
466 33761 : pImp->bUpdated = false;
467 :
468 : // Put bindings to sleep
469 33761 : SfxBindings* pBindings = GetBindings();
470 33761 : if ( pBindings )
471 33290 : pBindings->DENTERREGISTRATIONS();
472 : }
473 : }
474 :
475 66849 : if(!pSfxApp->IsDowning() && !pImp->aToDoStack.empty())
476 : {
477 : // No immediate update is requested
478 66849 : pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
479 66849 : pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
480 66849 : pImp->aTimer.Start();
481 : }
482 : else
483 : {
484 : // but to do nothing
485 0 : pImp->aTimer.Stop();
486 :
487 : // Bindings may wake up again
488 0 : if(pImp->aToDoStack.empty())
489 : {
490 0 : SfxBindings* pBindings = GetBindings();
491 0 : if ( pBindings )
492 0 : pBindings->DLEAVEREGISTRATIONS();
493 : }
494 : }
495 66849 : }
496 :
497 :
498 : /** This handler is called after <SfxDispatcher::Invalidate()> or after
499 : changes on the stack (<SfxDispatcher::Push()> and <SfxDispatcher::Pop())
500 :
501 : It flushes the Stack, if it is dirty, thus it actually excecutes the
502 : pending Push and Pop commands.
503 : */
504 0 : IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
505 : {
506 : (void)pvoid; // unused
507 :
508 0 : Flush();
509 0 : Update_Impl();
510 0 : SfxBindings* pBindings = GetBindings();
511 0 : if ( pBindings )
512 0 : pBindings->StartUpdate_Impl(false);
513 0 : return 0;
514 : }
515 0 : IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
516 :
517 : /** With this method it can be tested whether the <SfxShell> rShell is on the
518 : stack, when it was flushed. This way the SfxDispatcher is not actually
519 : flushed.
520 :
521 : This method is intended among other things to make assertions possible
522 : without the side effect of having to flush the SfxDispathcer.
523 : */
524 4572 : bool SfxDispatcher::CheckVirtualStack(const SfxShell& rShell, bool bDeep)
525 : {
526 : SFX_STACK(SfxDispatcher::CheckVirtualStack);
527 :
528 4572 : SfxShellStack_Impl aStack( pImp->aStack );
529 4572 : for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
530 : {
531 0 : if(i->bPush)
532 0 : aStack.push_back(i->pCluster);
533 : else
534 : {
535 0 : SfxShell* pPopped(NULL);
536 0 : do
537 : {
538 : DBG_ASSERT( !aStack.empty(), "popping from empty stack" );
539 0 : pPopped = aStack.back();
540 0 : aStack.pop_back();
541 : }
542 0 : while(i->bUntil && pPopped != i->pCluster);
543 : DBG_ASSERT(pPopped == i->pCluster, "popping unpushed SfxInterface");
544 : }
545 : }
546 :
547 : bool bReturn;
548 4572 : if ( bDeep )
549 4572 : bReturn = std::find(aStack.begin(), aStack.end(), &rShell) != aStack.end();
550 : else
551 0 : bReturn = aStack.back() == &rShell;
552 4572 : return bReturn;
553 : }
554 :
555 : /** Determines the position of a given SfxShell in the stack of the dispatcher.
556 : If possible this is flushed before.
557 :
558 : [Return value]
559 :
560 : sal_uInt16 == USRT_MAX
561 : The SfxShell is not on this SfxDispatcher.
562 :
563 : < USHRT_MAX
564 : Position of the SfxShell on the Dispatcher
565 : from the top count stating with 0.
566 : */
567 6075 : sal_uInt16 SfxDispatcher::GetShellLevel(const SfxShell& rShell)
568 : {
569 : SFX_STACK(SfxDispatcher::GetShellLevel);
570 6075 : Flush();
571 :
572 21158 : for ( sal_uInt16 n = 0; n < pImp->aStack.size(); ++n )
573 21158 : if ( *( pImp->aStack.rbegin() + n ) == &rShell )
574 6075 : return n;
575 0 : if ( pImp->pParent )
576 : {
577 0 : sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
578 0 : if ( nRet == USHRT_MAX )
579 0 : return nRet;
580 0 : return nRet + pImp->aStack.size();
581 : }
582 :
583 0 : return USHRT_MAX;
584 : }
585 :
586 : /** Returns a pointer to the <SfxShell> which is at the position nIdx
587 : (from the top, last pushed is 0) on the stack.
588 :
589 : Thus the SfxDispatcher is not flushed.
590 :
591 : Is the stack not deep enough a NULL-Pointer is returned.
592 : */
593 920745 : SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
594 : {
595 920745 : sal_uInt16 nShellCount = pImp->aStack.size();
596 920745 : if ( nIdx < nShellCount )
597 920745 : return *(pImp->aStack.rbegin() + nIdx);
598 0 : else if ( pImp->pParent )
599 0 : return pImp->pParent->GetShell( nIdx - nShellCount );
600 0 : return 0;
601 : }
602 :
603 : /** This method returns a pointer to the <SfxBinding> Instance on which the
604 : SfxDispatcher is curretly bound. A SfxDispatcher is only bound to
605 : the SfxBindings when it is <UI-aktiv>. If it is not UI-active,
606 : a NULL-pointer is returned.
607 :
608 : The returned pointer is only valid in the immediate context of the method
609 : call.
610 : */
611 230621 : SfxBindings* SfxDispatcher::GetBindings() const
612 : {
613 230621 : if ( pImp->pFrame )
614 229208 : return &pImp->pFrame->GetBindings();
615 : else
616 1413 : return NULL;
617 : }
618 :
619 : /** Returns a pointer to the <SfxViewFrame> instance, which belongs to
620 : this SfxDispatcher. If it is about the application dispatcher,
621 : a NULL-pointer is returned.
622 : */
623 533694 : SfxViewFrame* SfxDispatcher::GetFrame() const
624 : {
625 533694 : return pImp->pFrame;
626 : }
627 :
628 : /** This method controls the activation of a dispatcher.
629 :
630 : Since the application dispatcher is always active, either as a sub
631 : dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
632 : activated as a whole, instead only its individual <SfxShell>s at
633 : <SfxDispatcher::Push(SfxShell&)>.
634 :
635 : When activating a SfxDispatcher all of the SfxShells located on its stack
636 : are called with the handler <SfxShell::Activate(bool)>, starting with
637 : the lowest.
638 : */
639 5741 : void SfxDispatcher::DoActivate_Impl(bool bMDI, SfxViewFrame* /* pOld */)
640 : {
641 : SFX_STACK(SfxDispatcher::DoActivate);
642 5741 : if ( bMDI )
643 : {
644 : #ifdef DBG_UTIL
645 : OStringBuffer sTemp("Activate Dispatcher ");
646 : sTemp.append(reinterpret_cast<sal_Int64>(this));
647 : OSL_TRACE("%s", sTemp.getStr());
648 : DBG_ASSERT( !pImp->bActive, "Activation error" );
649 : #endif
650 5741 : pImp->bActive = true;
651 5741 : pImp->bUpdated = false;
652 5741 : SfxBindings* pBindings = GetBindings();
653 5741 : if ( pBindings )
654 : {
655 5438 : pBindings->SetDispatcher(this);
656 5438 : pBindings->SetActiveFrame( pImp->pFrame->GetFrame().GetFrameInterface() );
657 : }
658 : }
659 : else
660 : {
661 : #ifdef DBG_UTIL
662 : OStringBuffer sTemp("Non-MDI-Activate Dispatcher");
663 : sTemp.append(reinterpret_cast<sal_Int64>(this));
664 : OSL_TRACE("%s", sTemp.getStr());
665 : #endif
666 : }
667 :
668 5741 : if ( IsAppDispatcher() )
669 6044 : return;
670 :
671 34602 : for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
672 29164 : (*(pImp->aStack.rbegin() + i ))->DoActivate_Impl(pImp->pFrame, bMDI);
673 :
674 5438 : if ( bMDI && pImp->pFrame )
675 : {
676 5438 : SfxBindings *pBind = GetBindings();
677 16314 : while ( pBind )
678 : {
679 5438 : pBind->HidePopupCtrls_Impl( false );
680 5438 : pBind = pBind->GetSubBindings_Impl();
681 : }
682 :
683 5438 : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( false, false, 1 );
684 : }
685 :
686 5438 : if(!pImp->aToDoStack.empty())
687 : {
688 : // No immediate update is requested
689 0 : pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
690 0 : pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
691 0 : pImp->aTimer.Start();
692 : }
693 : }
694 :
695 0 : void SfxDispatcher::DoParentActivate_Impl()
696 : {
697 0 : for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
698 0 : (*(pImp->aStack.rbegin() + i ))->ParentActivate();
699 0 : }
700 :
701 : /** This method controls the deactivation of a dispatcher.
702 :
703 : Since the application dispatcher is always active, either as a sub
704 : dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
705 : deactivated as a whole, instead only its individual <SfxShell>s at
706 : <SfxDispatcher::Pop(SfxShell&)>.
707 :
708 : When deactivating a SfxDispatcher all of the SfxShells located on its stack
709 : are called with the handler <SfxShell::Deactivate(bool)>, starting with
710 : the lowest.
711 : */
712 5606 : void SfxDispatcher::DoDeactivate_Impl(bool bMDI, SfxViewFrame* pNew)
713 : {
714 : SFX_STACK(SfxDispatcher::DoDeactivate);
715 :
716 5606 : SfxApplication *pSfxApp = SfxGetpApp();
717 :
718 5606 : if ( bMDI )
719 : {
720 : OSL_TRACE(OStringBuffer("Deactivate Dispatcher").append(reinterpret_cast<sal_Int64>(this)).getStr());
721 : DBG_ASSERT( pImp->bActive, "Deactivate error" );
722 5606 : pImp->bActive = false;
723 :
724 5606 : if ( pImp->pFrame && !(pImp->pFrame->GetObjectShell()->IsInPlaceActive() ) )
725 : {
726 5438 : SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
727 5438 : if ( pWorkWin )
728 : {
729 199258 : for (size_t n=0; n<pImp->aChildWins.size();)
730 : {
731 188382 : SfxChildWindow *pWin = pWorkWin->GetChildWindow_Impl( (sal_uInt16) ( pImp->aChildWins[n] & 0xFFFF ) );
732 188382 : if (!pWin || (pWin && pWin->GetAlignment() == SFX_ALIGN_NOALIGNMENT))
733 188306 : pImp->aChildWins.erase(pImp->aChildWins.begin()+n);
734 : else
735 76 : n++;
736 : }
737 : }
738 : }
739 : }
740 : else {
741 : OSL_TRACE(OStringBuffer("Non-MDI-DeActivate Dispatcher").append(reinterpret_cast<sal_Int64>(this)).getStr());
742 : }
743 :
744 5606 : if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
745 5606 : return;
746 :
747 48254 : for ( sal_uInt16 i = 0; i < pImp->aStack.size(); ++i )
748 42648 : (*(pImp->aStack.rbegin() + i))->DoDeactivate_Impl(pImp->pFrame, bMDI);
749 :
750 5606 : bool bHidePopups = bMDI && pImp->pFrame;
751 5606 : if ( pNew && pImp->pFrame )
752 : {
753 : com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xOldFrame(
754 34 : pNew->GetFrame().GetFrameInterface()->getCreator(), com::sun::star::uno::UNO_QUERY );
755 :
756 : com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xMyFrame(
757 68 : GetFrame()->GetFrame().GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
758 :
759 34 : if ( xOldFrame == xMyFrame )
760 34 : bHidePopups = false;
761 : }
762 :
763 5606 : if ( bHidePopups )
764 : {
765 5438 : SfxBindings *pBind = GetBindings();
766 16314 : while ( pBind )
767 : {
768 5438 : pBind->HidePopupCtrls_Impl( true );
769 5438 : pBind = pBind->GetSubBindings_Impl();
770 : }
771 :
772 5438 : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( true, false, 1 );
773 : }
774 :
775 5606 : Flush();
776 : }
777 :
778 0 : void SfxDispatcher::DoParentDeactivate_Impl()
779 : {
780 0 : for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
781 0 : (*(pImp->aStack.rbegin() + i))->ParentDeactivate();
782 0 : }
783 :
784 : /** This method searches in SfxDispatcher after <SfxShell> , from the Slot Id
785 : nSlot currently being handled. For this, the dispatcher is first flushed.
786 :
787 : @param nSlot the searchable Slot-Id
788 : @param ppShell the SfxShell, which are currently handled the nSlot
789 : @param ppSlot the SfxSlot, which are currently handled the nSlot
790 :
791 : @return int sal_True
792 : The SfxShell was found, ppShell and ppSlot are valid.
793 :
794 : sal_False
795 : The SfxShell was not found, ppShell and ppSlot are invalid.
796 : */
797 152131 : int SfxDispatcher::GetShellAndSlot_Impl(sal_uInt16 nSlot, SfxShell** ppShell,
798 : const SfxSlot** ppSlot, bool bOwnShellsOnly, bool bModal, bool bRealSlot)
799 : {
800 : SFX_STACK(SfxDispatcher::GetShellAndSlot_Impl);
801 :
802 152131 : Flush();
803 152131 : SfxSlotServer aSvr;
804 152131 : if ( _FindServer(nSlot, aSvr, bModal) )
805 : {
806 147689 : if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.size() )
807 0 : return sal_False;
808 :
809 147689 : *ppShell = GetShell(aSvr.GetShellLevel());
810 147689 : *ppSlot = aSvr.GetSlot();
811 147689 : if ( 0 == (*ppSlot)->GetExecFnc() && bRealSlot )
812 0 : *ppSlot = (*ppShell)->GetInterface()->GetRealSlot(*ppSlot);
813 : // Check only real slots as enum slots don't have an execute function!
814 147689 : if ( bRealSlot && ((0 == *ppSlot) || (0 == (*ppSlot)->GetExecFnc()) ))
815 0 : return sal_False;
816 :
817 147689 : return sal_True;
818 : }
819 :
820 4442 : return sal_False;
821 : }
822 :
823 : /** This method performs a request for a cached <Slot-Server>.
824 :
825 : @param rShell to the calling <SfxShell>
826 : @param rSlot to the calling <SfxSlot>
827 : @param rReq function to be performed (Id and optional parameters)
828 : @param eCallMode Synchronously, asynchronously or as shown in the slot
829 : */
830 1679 : void SfxDispatcher::_Execute(SfxShell& rShell, const SfxSlot& rSlot,
831 : SfxRequest& rReq, SfxCallMode eCallMode)
832 : {
833 : DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
834 : DBG_ASSERT( pImp->aToDoStack.empty(), "unprepared InPlace _Execute" );
835 :
836 1679 : if ( IsLocked( rSlot.GetSlotId() ) )
837 0 : return;
838 :
839 3378 : if ( bool(eCallMode & SfxCallMode::ASYNCHRON) ||
840 636 : ( (eCallMode & SfxCallMode::SYNCHRON) == SfxCallMode::SLOT &&
841 296 : rSlot.IsMode(SFX_SLOT_ASYNCHRON) ) )
842 : {
843 1359 : SfxDispatcher *pDispat = this;
844 2718 : while ( pDispat )
845 : {
846 1359 : sal_uInt16 nShellCount = pDispat->pImp->aStack.size();
847 1461 : for ( sal_uInt16 n=0; n<nShellCount; n++ )
848 : {
849 1461 : if ( &rShell == *(pDispat->pImp->aStack.rbegin() + n) )
850 : {
851 1359 : if ( bool(eCallMode & SfxCallMode::RECORD) )
852 1339 : rReq.AllowRecording( true );
853 1359 : pDispat->pImp->xPoster->Post(new SfxRequest(rReq));
854 1359 : return;
855 : }
856 : }
857 :
858 0 : pDispat = pDispat->pImp->pParent;
859 : }
860 : }
861 : else
862 320 : Call_Impl( rShell, rSlot, rReq, SfxCallMode::RECORD==(eCallMode&SfxCallMode::RECORD) );
863 : }
864 :
865 : /** Helper function to put from rItem below the Which-ID in the pool of the
866 : Item Sets rSet.
867 : */
868 1015 : void MappedPut_Impl(SfxAllItemSet &rSet, const SfxPoolItem &rItem)
869 : {
870 : // Put with mapped Which-Id if possible
871 1015 : const SfxItemPool *pPool = rSet.GetPool();
872 1015 : sal_uInt16 nWhich = rItem.Which();
873 1015 : if ( SfxItemPool::IsSlot(nWhich) )
874 1015 : nWhich = pPool->GetWhich(nWhich);
875 1015 : rSet.Put( rItem, nWhich );
876 1015 : }
877 :
878 4619 : const SfxSlot* SfxDispatcher::GetSlot( const OUString& rCommand )
879 : {
880 : // Count the number of Shells on the linked Dispatcher
881 4619 : Flush();
882 4619 : sal_uInt16 nTotCount = pImp->aStack.size();
883 4619 : if ( pImp->pParent )
884 : {
885 0 : SfxDispatcher *pParent = pImp->pParent;
886 0 : while ( pParent )
887 : {
888 0 : nTotCount = nTotCount + pParent->pImp->aStack.size();
889 0 : pParent = pParent->pImp->pParent;
890 : }
891 : }
892 :
893 4619 : const SfxSlot *pSlot=NULL;
894 4619 : sal_uInt16 nFirstShell = 0;
895 9107 : for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
896 : {
897 4619 : SfxShell *pObjShell = GetShell(i);
898 4619 : SfxInterface *pIFace = pObjShell->GetInterface();
899 4619 : pSlot = pIFace->GetSlot( rCommand );
900 4619 : if ( pSlot )
901 131 : return pSlot;
902 : }
903 :
904 4488 : return 0;
905 : }
906 :
907 246 : const SfxPoolItem* SfxDispatcher::Execute(sal_uInt16 nSlot, SfxCallMode nCall,
908 : SfxItemSet* pArgs, SfxItemSet* pInternalArgs, sal_uInt16 nModi)
909 : {
910 246 : if ( IsLocked(nSlot) )
911 0 : return 0;
912 :
913 246 : SfxShell *pShell = 0;
914 246 : const SfxSlot *pSlot = 0;
915 246 : if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, false,
916 246 : SfxCallMode::MODAL==(nCall&SfxCallMode::MODAL) ) )
917 : {
918 246 : SfxAllItemSet aSet( pShell->GetPool() );
919 246 : if ( pArgs )
920 : {
921 246 : SfxItemIter aIter(*pArgs);
922 492 : for ( const SfxPoolItem *pArg = aIter.FirstItem();
923 : pArg;
924 : pArg = aIter.NextItem() )
925 492 : MappedPut_Impl( aSet, *pArg );
926 : }
927 492 : SfxRequest aReq( nSlot, nCall, aSet );
928 246 : if (pInternalArgs)
929 246 : aReq.SetInternalArgs_Impl( *pInternalArgs );
930 246 : aReq.SetModifier( nModi );
931 :
932 246 : _Execute( *pShell, *pSlot, aReq, nCall );
933 492 : return aReq.GetReturnValue();
934 : }
935 0 : return 0;
936 : }
937 :
938 : /** Method to excecute a <SfxSlot>s over the Slot-Id.
939 :
940 : @param nSlot the Id of the executing function
941 : @param eCall SfxCallMode::SYNCRHON, ..._ASYNCHRON or ..._SLOT
942 : @param pArgs Zero teminated C-Array of Parameters
943 : @param pInternalArgs Zero terminated C-Array of Parameters
944 :
945 : @return const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
946 : though the Message-Loop, which contains the return
947 : value.
948 :
949 : Or a NULL-Pointer, when the function was not
950 : executed (for example canceled by the user).
951 : */
952 932 : const SfxPoolItem* SfxDispatcher::Execute(sal_uInt16 nSlot, SfxCallMode eCall,
953 : const SfxPoolItem **pArgs, sal_uInt16 nModi, const SfxPoolItem **pInternalArgs)
954 : {
955 932 : if ( IsLocked(nSlot) )
956 0 : return 0;
957 :
958 932 : SfxShell *pShell = 0;
959 932 : const SfxSlot *pSlot = 0;
960 932 : if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, false,
961 932 : SfxCallMode::MODAL==(eCall&SfxCallMode::MODAL) ) )
962 : {
963 : SfxRequest* pReq;
964 612 : if ( pArgs && *pArgs )
965 : {
966 0 : SfxAllItemSet aSet( pShell->GetPool() );
967 0 : for ( const SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
968 0 : MappedPut_Impl( aSet, **pArg );
969 0 : pReq = new SfxRequest( nSlot, eCall, aSet );
970 : }
971 : else
972 612 : pReq = new SfxRequest( nSlot, eCall, pShell->GetPool() );
973 612 : pReq->SetModifier( nModi );
974 612 : if( pInternalArgs && *pInternalArgs)
975 : {
976 0 : SfxAllItemSet aSet( SfxGetpApp()->GetPool() );
977 0 : for ( const SfxPoolItem **pArg = pInternalArgs; *pArg; ++pArg )
978 0 : aSet.Put( **pArg );
979 0 : pReq->SetInternalArgs_Impl( aSet );
980 : }
981 612 : _Execute( *pShell, *pSlot, *pReq, eCall );
982 612 : const SfxPoolItem* pRet = pReq->GetReturnValue();
983 612 : delete pReq; return pRet;
984 : }
985 320 : return 0;
986 : }
987 :
988 : /** Method to excecute a <SfxSlot>s over the Slot-Id.
989 :
990 : @param nSlot the Id of the executing function
991 : @param eCall SfxCallMode::SYNCRHON, ..._ASYNCHRON or ..._SLOT
992 : @param rArgs <SfxItemSet> with the parameters
993 :
994 : @return const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
995 : though the Message-Loop, which contains the return
996 : value.
997 :
998 : Or a NULL-Pointer, when the function was not
999 : executed (for example canceled by the user).
1000 : */
1001 22 : const SfxPoolItem* SfxDispatcher::Execute(sal_uInt16 nSlot, SfxCallMode eCall,
1002 : const SfxItemSet &rArgs)
1003 : {
1004 22 : return Execute( nSlot, eCall, 0, rArgs );
1005 : }
1006 :
1007 22 : const SfxPoolItem* SfxDispatcher::Execute(sal_uInt16 nSlot, SfxCallMode eCall,
1008 : sal_uInt16 nModi, const SfxItemSet &rArgs)
1009 : {
1010 22 : if ( IsLocked(nSlot) )
1011 0 : return 0;
1012 :
1013 22 : SfxShell *pShell = 0;
1014 22 : const SfxSlot *pSlot = 0;
1015 22 : if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, false,
1016 22 : SfxCallMode::MODAL==(eCall&SfxCallMode::MODAL) ) )
1017 : {
1018 22 : SfxAllItemSet aSet( pShell->GetPool() );
1019 44 : SfxItemIter aIter(rArgs);
1020 44 : for ( const SfxPoolItem *pArg = aIter.FirstItem();
1021 : pArg;
1022 : pArg = aIter.NextItem() )
1023 22 : MappedPut_Impl( aSet, *pArg );
1024 44 : SfxRequest aReq( nSlot, eCall, aSet );
1025 22 : aReq.SetModifier( nModi );
1026 22 : _Execute( *pShell, *pSlot, aReq, eCall );
1027 44 : return aReq.GetReturnValue();
1028 : }
1029 0 : return 0;
1030 : }
1031 :
1032 : /** Method to excecute a <SfxSlot>s over the Slot-Id.
1033 :
1034 : [Note]
1035 :
1036 : The parameters are copied, can therefore be passed on as the address
1037 : of stack objects.
1038 :
1039 : @param nSlot the Id of the executing function
1040 : @param eCall SfxCallMode::SYNCRHON, ..._ASYNCHRON or ..._SLOT
1041 : @param pArg1 First parameter
1042 : @param ... Zero terminated list of parameters
1043 :
1044 : @return Pointer to the SfxPoolItem valid to the next run
1045 : though the Message-Loop, which contains the return
1046 : value.
1047 :
1048 : Or a NULL-Pointer, when the function was not
1049 : executed (for example canceled by the user).
1050 :
1051 : [Example]
1052 :
1053 : pDispatcher->Execute( SID_OPENDOCUMENT, SfxCallMode::SYNCHRON,
1054 : &SfxStringItem( SID_FILE_NAME, "\\tmp\\temp.sdd" ),
1055 : &SfxStringItem( SID_FILTER_NAME, "StarDraw Presentation" ),
1056 : &SfxBoolItem( SID_DOC_READONLY, sal_False ),
1057 : 0L );
1058 : */
1059 1095 : const SfxPoolItem* SfxDispatcher::Execute(sal_uInt16 nSlot, SfxCallMode eCall,
1060 : const SfxPoolItem* pArg1, ...)
1061 : {
1062 1095 : if ( IsLocked(nSlot) )
1063 0 : return 0;
1064 :
1065 1095 : SfxShell *pShell = 0;
1066 1095 : const SfxSlot *pSlot = 0;
1067 1095 : if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, false,
1068 1095 : SfxCallMode::MODAL==(eCall&SfxCallMode::MODAL) ) )
1069 : {
1070 747 : SfxAllItemSet aSet( pShell->GetPool() );
1071 :
1072 : va_list pVarArgs;
1073 747 : va_start( pVarArgs, pArg1 );
1074 2241 : for ( const SfxPoolItem *pArg = pArg1;
1075 : pArg;
1076 747 : pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
1077 747 : MappedPut_Impl( aSet, *pArg );
1078 747 : va_end(pVarArgs);
1079 :
1080 1494 : SfxRequest aReq( nSlot, eCall, aSet );
1081 747 : _Execute( *pShell, *pSlot, aReq, eCall );
1082 1494 : return aReq.GetReturnValue();
1083 : }
1084 348 : return 0;
1085 : }
1086 :
1087 : /** Helper method to receive the asynchronously executed <SfxRequest>s.
1088 : */
1089 1540 : IMPL_LINK(SfxDispatcher, PostMsgHandler, SfxRequest*, pReq)
1090 : {
1091 : DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
1092 : SFX_STACK(SfxDispatcher::PostMsgHandler);
1093 :
1094 : // Has also the Pool not yet died?
1095 770 : if ( !pReq->IsCancelled() )
1096 : {
1097 770 : if ( !IsLocked(pReq->GetSlot()) )
1098 : {
1099 770 : Flush();
1100 770 : SfxSlotServer aSvr;
1101 770 : if ( _FindServer(pReq->GetSlot(), aSvr, true ) ) // HACK(x), whatever that was supposed to mean
1102 : {
1103 770 : const SfxSlot *pSlot = aSvr.GetSlot();
1104 770 : SfxShell *pSh = GetShell(aSvr.GetShellLevel());
1105 :
1106 : // When the pSlot is a "Pseudoslot" for macros or Verbs, it can
1107 : // be destroyed in the Call_Impl, thus do not use it anymore!
1108 770 : pReq->SetSynchronCall( false );
1109 770 : Call_Impl( *pSh, *pSlot, *pReq, pReq->AllowsRecording() ); //! why bRecord?
1110 : }
1111 : }
1112 : else
1113 : {
1114 0 : if ( pImp->bLocked )
1115 0 : pImp->aReqArr.push_back(new SfxRequest(*pReq));
1116 : else
1117 0 : pImp->xPoster->Post(new SfxRequest(*pReq));
1118 : }
1119 : }
1120 :
1121 770 : delete pReq;
1122 770 : return 0;
1123 : }
1124 :
1125 11917 : void SfxDispatcher::SetMenu_Impl()
1126 : {
1127 : #if HAVE_FEATURE_DESKTOP
1128 11917 : if ( pImp->pFrame )
1129 : {
1130 11917 : SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
1131 11917 : if ( pTop && pTop->GetBindings().GetDispatcher() == this )
1132 : {
1133 11917 : SfxFrame& rFrame = pTop->GetFrame();
1134 11917 : if ( rFrame.IsMenuBarOn_Impl() )
1135 : {
1136 11917 : com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
1137 11917 : if ( xPropSet.is() )
1138 : {
1139 11917 : com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1140 23834 : com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1141 11917 : aValue >>= xLayoutManager;
1142 11917 : if ( xLayoutManager.is() )
1143 : {
1144 11917 : OUString aMenuBarURL( "private:resource/menubar/menubar" );
1145 11917 : if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
1146 5456 : xLayoutManager->createElement( aMenuBarURL );
1147 11917 : }
1148 11917 : }
1149 : }
1150 : }
1151 : }
1152 : #endif
1153 11917 : }
1154 :
1155 13470 : void SfxDispatcher::Update_Impl( bool bForce )
1156 : {
1157 : SFX_STACK(SfxDispatcher::Update_Impl);
1158 :
1159 13470 : Flush();
1160 :
1161 13470 : if ( !pImp->pFrame )
1162 0 : return;
1163 :
1164 13470 : SfxGetpApp(); // -Wall is this required???
1165 13470 : SfxDispatcher *pDisp = this;
1166 13470 : bool bUpdate = bForce;
1167 40410 : while ( pDisp && pDisp->pImp->pFrame )
1168 : {
1169 13470 : SfxWorkWindow *pWork = pDisp->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1170 13470 : SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1171 13470 : if ( pAct == pDisp || pAct == this )
1172 : {
1173 13470 : if ( !bUpdate )
1174 7018 : bUpdate = !pDisp->pImp->bUpdated;
1175 13470 : pDisp->pImp->bUpdated = true;
1176 : }
1177 : else
1178 : break;
1179 :
1180 13470 : pDisp = pDisp->pImp->pParent;
1181 : }
1182 :
1183 13470 : if ( !bUpdate || pImp->pFrame->GetFrame().IsClosing_Impl() )
1184 1553 : return;
1185 :
1186 11917 : SfxViewFrame* pTop = pImp->pFrame ? pImp->pFrame->GetTopViewFrame() : NULL;
1187 11917 : bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
1188 :
1189 11917 : if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
1190 : // keep own tools internally for collecting
1191 0 : GetBindings()->GetDispatcher()->pImp->bUpdated = false;
1192 :
1193 11917 : com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame;
1194 11917 : SfxBindings* pBindings = GetBindings();
1195 11917 : if (pBindings)
1196 : {
1197 11917 : pBindings->DENTERREGISTRATIONS();
1198 11917 : xFrame = pBindings->GetActiveFrame();
1199 : }
1200 23834 : com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, com::sun::star::uno::UNO_QUERY );
1201 23834 : com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1202 11917 : if ( xPropSet.is() )
1203 : {
1204 : try
1205 : {
1206 11917 : com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1207 11917 : aValue >>= xLayoutManager;
1208 : }
1209 0 : catch (const com::sun::star::uno::Exception&)
1210 : {
1211 : }
1212 : }
1213 :
1214 11917 : if ( xLayoutManager.is() )
1215 11917 : xLayoutManager->lock();
1216 :
1217 11917 : bool bIsIPActive = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1218 11917 : SfxInPlaceClient *pClient = pImp->pFrame ? pImp->pFrame->GetViewShell()->GetUIActiveClient() : NULL;
1219 11917 : if ( bUIActive && /* !bIsIPActive && */ ( !pClient || !pClient->IsObjectUIActive() ) )
1220 11917 : SetMenu_Impl();
1221 :
1222 11917 : SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1223 11917 : SfxWorkWindow *pTaskWin = pImp->pFrame->GetTopFrame().GetWorkWindow_Impl();
1224 11917 : pTaskWin->ResetStatusBar_Impl();
1225 :
1226 11917 : SfxDispatcher *pDispat = this;
1227 35751 : while ( pDispat )
1228 : {
1229 11917 : SfxWorkWindow *pWork = pDispat->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1230 11917 : SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1231 11917 : if ( pAct == pDispat || pAct == this )
1232 : {
1233 11917 : pWork->ResetObjectBars_Impl();
1234 11917 : pWork->ResetChildWindows_Impl();
1235 : }
1236 :
1237 11917 : pDispat = pDispat->pImp->pParent;
1238 : }
1239 :
1240 11917 : bool bIsActive = false;
1241 11917 : SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1242 11917 : pDispat = this;
1243 35751 : while ( pActDispat && !bIsActive )
1244 : {
1245 11917 : if ( pDispat == pActDispat )
1246 11917 : bIsActive = true;
1247 11917 : pActDispat = pActDispat->pImp->pParent;
1248 : }
1249 :
1250 11917 : _Update_Impl( bUIActive, !bIsIPActive, bIsIPActive, pTaskWin );
1251 11917 : if ( bUIActive || bIsActive )
1252 11917 : pWorkWin->UpdateObjectBars_Impl();
1253 :
1254 11917 : if ( pBindings )
1255 11917 : pBindings->DLEAVEREGISTRATIONS();
1256 :
1257 11917 : if ( xLayoutManager.is() )
1258 11917 : xLayoutManager->unlock();
1259 :
1260 23834 : return;
1261 : }
1262 :
1263 11917 : void SfxDispatcher::_Update_Impl( bool bUIActive, bool bIsMDIApp, bool bIsIPOwner, SfxWorkWindow *pTaskWin )
1264 : {
1265 11917 : SfxGetpApp();
1266 11917 : SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1267 11917 : bool bIsActive = false;
1268 11917 : bool bIsTaskActive = false;
1269 11917 : SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1270 11917 : SfxDispatcher *pDispat = this;
1271 35751 : while ( pActDispat && !bIsActive )
1272 : {
1273 11917 : if ( pDispat == pActDispat )
1274 11917 : bIsActive = true;
1275 11917 : pActDispat = pActDispat->pImp->pParent;
1276 : }
1277 :
1278 11917 : if ( pImp->pParent && !pImp->bQuiet /* && bUIActive */ )
1279 0 : pImp->pParent->_Update_Impl( bUIActive, bIsMDIApp, bIsIPOwner, pTaskWin );
1280 :
1281 166838 : for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1282 154921 : pImp->aObjBars[n].nResId = 0;
1283 11917 : pImp->aChildWins.clear();
1284 :
1285 : // bQuiet : own shells aren't considered for UI and SlotServer
1286 : // bNoUI: own Shells aren't considered fors UI
1287 11917 : if ( pImp->bQuiet || pImp->bNoUI || (pImp->pFrame && pImp->pFrame->GetObjectShell()->IsPreview()) )
1288 11917 : return;
1289 :
1290 11917 : sal_uInt32 nStatBarId=0;
1291 11917 : SfxShell *pStatusBarShell = NULL;
1292 :
1293 11917 : SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() );
1294 11917 : sal_uInt16 nTotCount = pImp->aStack.size();
1295 92698 : for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
1296 : {
1297 80781 : SfxShell *pShell = GetShell( nShell-1 );
1298 80781 : SfxInterface *pIFace = pShell->GetInterface();
1299 :
1300 : // don't consider shells if "Hidden" oder "Quiet"
1301 80781 : bool bReadOnlyShell = IsReadOnlyShell_Impl( nShell-1 );
1302 : sal_uInt16 nNo;
1303 178257 : for ( nNo = 0; pIFace && nNo<pIFace->GetObjectBarCount(); ++nNo )
1304 : {
1305 97476 : sal_uInt16 nPos = pIFace->GetObjectBarPos(nNo);
1306 97476 : if ( bReadOnlyShell && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
1307 52 : continue;
1308 :
1309 : // check whether toolbar needs activation of a special feature
1310 97424 : sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
1311 97424 : if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1312 21741 : continue;
1313 :
1314 : // check for toolboxes that are exclusively for a viewer
1315 75683 : if ( pImp->pFrame)
1316 : {
1317 75683 : bool bViewerTbx = SFX_VISIBILITY_VIEWER == ( nPos & SFX_VISIBILITY_VIEWER );
1318 75683 : SfxObjectShell* pSh = pImp->pFrame->GetObjectShell();
1319 75683 : SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, false );
1320 75683 : bool bIsViewer = pItem && pItem->GetValue();
1321 75683 : if ( bIsViewer != bViewerTbx )
1322 11392 : continue;
1323 : }
1324 :
1325 : // always register toolbars, allows to switch them on
1326 64291 : bool bVisible = pIFace->IsObjectBarVisible(nNo);
1327 64291 : if ( !bVisible )
1328 0 : nPos &= SFX_POSITION_MASK;
1329 :
1330 64291 : SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
1331 64291 : rBar.nMode = nPos;
1332 64291 : rBar.nResId = pIFace->GetObjectBarResId(nNo).GetId();
1333 64291 : const OUString *pName = pIFace->GetObjectBarName(nNo);
1334 64291 : if ( pName )
1335 64291 : rBar.aName = *pName;
1336 : else
1337 0 : rBar.aName = "";
1338 64291 : rBar.pIFace = pIFace;
1339 :
1340 64291 : if ( bUIActive || bIsActive )
1341 : {
1342 : pWorkWin->SetObjectBar_Impl(
1343 64291 : nPos, rBar.nResId, rBar.pIFace, &rBar.aName );
1344 : }
1345 :
1346 64291 : if ( !bVisible )
1347 0 : rBar.nResId = 0;
1348 : }
1349 :
1350 490792 : for ( nNo=0; pIFace && nNo<pIFace->GetChildWindowCount(); nNo++ )
1351 : {
1352 410011 : sal_uInt32 nId = pIFace->GetChildWindowId(nNo);
1353 410011 : const SfxSlot *pSlot = pSlotPool->GetSlot( (sal_uInt16) nId );
1354 : SAL_WARN_IF( !pSlot, "sfx.control", "Childwindow slot missing: " << nId );
1355 410011 : if ( bReadOnlyShell )
1356 : {
1357 : // only show ChildWindows if their slot is allowed for readonly documents
1358 294 : if ( pSlot && !pSlot->IsMode( SFX_SLOT_READONLYDOC ) )
1359 49801 : continue;
1360 : }
1361 :
1362 409831 : sal_uInt32 nFeature = pIFace->GetChildWindowFeature(nNo);
1363 409831 : if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1364 49441 : continue;
1365 :
1366 : // slot decides whether a ChildWindow is shown when document is OLE server or OLE client
1367 360390 : sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
1368 360390 : if( pSlot )
1369 : {
1370 348547 : if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
1371 : {
1372 35667 : if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
1373 35667 : nMode |= SFX_VISIBILITY_CLIENT;
1374 : }
1375 : else
1376 : {
1377 312880 : if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
1378 312880 : nMode |= SFX_VISIBILITY_SERVER;
1379 : }
1380 : }
1381 :
1382 360390 : if ( bUIActive || bIsActive )
1383 360390 : pWorkWin->SetChildWindowVisible_Impl( nId, true, nMode );
1384 360390 : if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
1385 360390 : pImp->aChildWins.push_back( nId );
1386 : }
1387 :
1388 80781 : if ( bIsMDIApp || bIsIPOwner )
1389 : {
1390 80781 : sal_uInt32 nId = pIFace->GetStatusBarResId().GetId();
1391 80781 : if ( nId )
1392 : {
1393 23834 : nStatBarId = nId;
1394 23834 : pStatusBarShell = pShell;
1395 : }
1396 : }
1397 : }
1398 :
1399 166838 : for ( sal_uInt16 nPos=0; nPos<SFX_OBJECTBAR_MAX; nPos++ )
1400 : {
1401 154921 : SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos];
1402 154921 : if ( rFixed.nResId )
1403 : {
1404 0 : SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos];
1405 0 : rBar = rFixed;
1406 : pWorkWin->SetObjectBar_Impl( rFixed.nMode,
1407 0 : rFixed.nResId, rFixed.pIFace, &rFixed.aName );
1408 : }
1409 : }
1410 :
1411 11917 : if ( pTaskWin && ( bIsMDIApp || bIsIPOwner ) )
1412 : {
1413 11917 : SfxDispatcher *pActDispatcher = pTaskWin->GetBindings().GetDispatcher_Impl();
1414 11917 : SfxDispatcher *pDispatcher = this;
1415 35751 : while ( pActDispatcher && !bIsTaskActive )
1416 : {
1417 11917 : if ( pDispatcher == pActDispatcher )
1418 11917 : bIsTaskActive = true;
1419 11917 : pActDispatcher = pActDispatcher->pImp->pParent;
1420 : }
1421 :
1422 11917 : if ( bIsTaskActive && nStatBarId && pImp->pFrame )
1423 : {
1424 : // internal frames also may control statusbar
1425 11917 : SfxBindings& rBindings = pImp->pFrame->GetBindings();
1426 11917 : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->SetStatusBar_Impl( nStatBarId, pStatusBarShell, rBindings );
1427 : }
1428 : }
1429 : }
1430 :
1431 : /** Helper method to execute the outstanding push and pop commands.
1432 : */
1433 28255 : void SfxDispatcher::FlushImpl()
1434 : {
1435 : SFX_STACK(SfxDispatcher::FlushImpl);
1436 :
1437 : OSL_TRACE("Flushing dispatcher!");
1438 :
1439 28255 : pImp->aTimer.Stop();
1440 :
1441 28255 : if ( pImp->pParent )
1442 0 : pImp->pParent->Flush();
1443 :
1444 28255 : pImp->bFlushing = !pImp->bFlushing;
1445 28255 : if ( !pImp->bFlushing )
1446 : {
1447 0 : pImp->bFlushing = true;
1448 28255 : return;
1449 : }
1450 :
1451 28255 : SfxApplication *pSfxApp = SfxGetpApp();
1452 :
1453 : // Re-build the true stack in the first round
1454 28255 : std::deque<SfxToDo_Impl> aToDoCopy;
1455 28255 : bool bModify = false;
1456 89506 : for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
1457 : {
1458 61251 : bModify = true;
1459 :
1460 61251 : if(i->bPush)
1461 : {
1462 : // Actually push
1463 : DBG_ASSERT( std::find(pImp->aStack.begin(), pImp->aStack.end(), i->pCluster) == pImp->aStack.end(),
1464 : "pushed SfxShell already on stack" );
1465 44661 : pImp->aStack.push_back(i->pCluster);
1466 44661 : i->pCluster->SetDisableFlags(pImp->nDisableFlags);
1467 :
1468 : // Mark the moved shell
1469 44661 : aToDoCopy.push_front(*i);
1470 : }
1471 : else
1472 : {
1473 : // Actually pop
1474 16590 : SfxShell* pPopped = 0;
1475 16590 : bool bFound = false;
1476 26978 : do
1477 : {
1478 : DBG_ASSERT( !pImp->aStack.empty(), "popping from empty stack" );
1479 26978 : pPopped = pImp->aStack.back();
1480 26978 : pImp->aStack.pop_back();
1481 26978 : pPopped->SetDisableFlags( 0 );
1482 26978 : bFound = (pPopped == i->pCluster);
1483 :
1484 : // Mark the moved Shell
1485 26978 : aToDoCopy.push_front(SfxToDo_Impl(false, i->bDelete, false, *pPopped));
1486 : }
1487 26978 : while(i->bUntil && !bFound);
1488 : DBG_ASSERT( bFound, "wrong SfxShell popped" );
1489 : }
1490 : }
1491 28255 : pImp->aToDoStack.clear();
1492 :
1493 : // Invalidate bindings, if possible
1494 28255 : if ( !pSfxApp->IsDowning() )
1495 : {
1496 28255 : if ( bModify )
1497 : {
1498 28255 : pImp->pCachedServ1 = 0;
1499 28255 : pImp->pCachedServ2 = 0;
1500 : }
1501 :
1502 28255 : InvalidateBindings_Impl( bModify );
1503 : }
1504 :
1505 28255 : pImp->bFlushing = false;
1506 28255 : pImp->bUpdated = false; // not only when bModify, if Doc/Template-Config
1507 28255 : pImp->bFlushed = true;
1508 : OSL_TRACE("Successfully flushed dispatcher!");
1509 :
1510 : //fdo#70703 FlushImpl may call back into itself so use aToDoCopyStack to talk
1511 : //to outer levels of ourself. If DoActivate_Impl/DoDeactivate_Impl deletes
1512 : //an entry, then they will walk back up aToDoCopyStack and set outer
1513 : //levels's entries to bDeleted
1514 28255 : pImp->aToDoCopyStack.push_back(aToDoCopy);
1515 28255 : std::deque<SfxToDo_Impl>& rToDoCopy = pImp->aToDoCopyStack.back();
1516 : // Activate the Shells and possible delete them in the 2nd round
1517 99894 : for(std::deque<SfxToDo_Impl>::reverse_iterator i = rToDoCopy.rbegin(); i != rToDoCopy.rend(); ++i)
1518 : {
1519 71639 : if (i->bDeleted)
1520 0 : continue;
1521 71639 : if (!pImp->bActive)
1522 56573 : continue;
1523 15066 : if (i->bPush)
1524 14698 : i->pCluster->DoActivate_Impl(pImp->pFrame, true);
1525 : else
1526 368 : i->pCluster->DoDeactivate_Impl(pImp->pFrame, true);
1527 : }
1528 :
1529 28255 : aToDoCopy = pImp->aToDoCopyStack.back();
1530 28255 : pImp->aToDoCopyStack.pop_back();
1531 :
1532 99894 : for(std::deque<SfxToDo_Impl>::reverse_iterator i = aToDoCopy.rbegin(); i != aToDoCopy.rend(); ++i)
1533 : {
1534 71639 : if (i->bDelete && !i->bDeleted)
1535 : {
1536 14648 : if (!pImp->aToDoCopyStack.empty())
1537 : {
1538 : //fdo#70703 if there is an outer FlushImpl then inform it that
1539 : //we have deleted this cluster
1540 0 : for (std::deque< std::deque<SfxToDo_Impl> >::iterator aI = pImp->aToDoCopyStack.begin();
1541 0 : aI != pImp->aToDoCopyStack.end(); ++aI)
1542 : {
1543 0 : std::deque<SfxToDo_Impl> &v = *aI;
1544 0 : for(std::deque<SfxToDo_Impl>::iterator aJ = v.begin(); aJ != v.end(); ++aJ)
1545 : {
1546 0 : if (aJ->pCluster == i->pCluster)
1547 0 : aJ->bDeleted = true;
1548 : }
1549 : }
1550 : }
1551 14648 : delete i->pCluster;
1552 : }
1553 : }
1554 28255 : bool bAwakeBindings = !aToDoCopy.empty();
1555 28255 : if( bAwakeBindings )
1556 28255 : aToDoCopy.clear();
1557 :
1558 : // If more changes have occurred on the stach when
1559 : // Activate/Deactivate/Delete:
1560 28255 : if (!pImp->bFlushed)
1561 : // If Push/Pop hs been called by someone, theb also EnterReg was called!
1562 0 : FlushImpl();
1563 :
1564 28255 : if( bAwakeBindings && GetBindings() )
1565 27784 : GetBindings()->DLEAVEREGISTRATIONS();
1566 :
1567 395570 : for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1568 367315 : pImp->aFixedObjBars[n].nResId = 0;
1569 :
1570 28255 : SAL_INFO("sfx.control", "SfxDispatcher(" << this << ")::Flush() done");
1571 : }
1572 :
1573 : /** With this method a filter set, the target slots can be enabled or disabled.
1574 : The passed array must be retained until the destructor or the next
1575 : <SetSlotFilter()>, it is not deleted from the dispatcher, so it can thus be
1576 : static.
1577 :
1578 : In read-only documents the quasi ReadOnlyDoc Flag of slots can be
1579 : overturned by the use of 'bEnable == 2', so this will be displayed again.
1580 : On the other slots it has no effect.
1581 :
1582 : // HACK(hier muss mal ein enum rein) ???
1583 : @param nEnable 1==true: only enable specified slots, disable all other
1584 : 0==false: disable specified slots, first enable all other
1585 : @param nCount Number of SIDs in the following Array
1586 : @param pSIDs sorted Array of 'nCount' SIDs
1587 :
1588 : [Example]
1589 :
1590 : Targeted disabling of Slots 1, 2 and 3:
1591 :
1592 : static sal_uInt16 const pSIDs[] = { 1, 2, 3 };
1593 : pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
1594 :
1595 : only permit Slots 5, 6 and 7:
1596 :
1597 : static sal_uInt16 const pSIDs[] = { 5, 6, 7 };
1598 : pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
1599 :
1600 : Turn-off Filter:
1601 :
1602 : pDisp->SetSlotFilter();
1603 : */
1604 212 : void SfxDispatcher::SetSlotFilter(SfxSlotFilterState nEnable,
1605 : sal_uInt16 nCount, const sal_uInt16* pSIDs)
1606 : {
1607 : #ifdef DBG_UTIL
1608 : // Check Array
1609 : for ( sal_uInt16 n = 1; n < nCount; ++n )
1610 : DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sorted" );
1611 : #endif
1612 :
1613 212 : if ( pImp->pFilterSIDs )
1614 0 : pImp->pFilterSIDs = 0;
1615 :
1616 212 : pImp->nFilterEnabling = nEnable;
1617 212 : pImp->nFilterCount = nCount;
1618 212 : pImp->pFilterSIDs = pSIDs;
1619 :
1620 212 : GetBindings()->InvalidateAll(true);
1621 212 : }
1622 :
1623 0 : extern "C" int SAL_CALL SfxCompareSIDs_Impl(const void* pSmaller, const void* pBigger)
1624 : {
1625 0 : return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
1626 : }
1627 :
1628 : /** Searches for 'nSID' in the Filter set by <SetSlotFilter()> and
1629 : returns sal_True, if the SIDis allowed, or sal_False, if it is
1630 : disabled by the Filter.
1631 :
1632 : @return 0 => disabled
1633 : 1 => enabled
1634 : 2 => enabled even if ReadOnlyDoc
1635 : */
1636 259662 : SfxSlotFilterState SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
1637 : {
1638 : // no filter?
1639 259662 : if ( 0 == pImp->nFilterCount )
1640 : // => all SIDs allowed
1641 259662 : return SFX_SLOT_FILTER_ENABLED;
1642 :
1643 : // search
1644 0 : bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
1645 0 : sizeof(sal_uInt16), SfxCompareSIDs_Impl );
1646 :
1647 : // even if ReadOnlyDoc
1648 0 : if ( SFX_SLOT_FILTER_ENABLED_READONLY == pImp->nFilterEnabling )
1649 0 : return bFound ? SFX_SLOT_FILTER_ENABLED_READONLY : SFX_SLOT_FILTER_ENABLED;
1650 : // Otherwise after Negative/Positive Filter
1651 0 : else if ( SFX_SLOT_FILTER_ENABLED == pImp->nFilterEnabling )
1652 0 : return bFound ? SFX_SLOT_FILTER_ENABLED : SFX_SLOT_FILTER_DISABLED;
1653 : else
1654 0 : return bFound ? SFX_SLOT_FILTER_DISABLED : SFX_SLOT_FILTER_ENABLED;
1655 : }
1656 :
1657 0 : bool SfxDispatcher::_TryIntercept_Impl
1658 : (
1659 : sal_uInt16 nSlot, // Slot-Id to search for
1660 : SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
1661 : bool bSelf
1662 : )
1663 : {
1664 : // Maybe the parent is also belongs to a component
1665 0 : SfxDispatcher *pParent = pImp->pParent;
1666 0 : sal_uInt16 nLevels = pImp->aStack.size();
1667 0 : while ( pParent && pParent->pImp->pFrame )
1668 : {
1669 0 : if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
1670 : {
1671 : // Components may be intercepted
1672 0 : if ( pParent->_TryIntercept_Impl( nSlot, rServer, true ) )
1673 : {
1674 : // The own shells are added to the Shell Level
1675 0 : rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
1676 0 : return true;
1677 : }
1678 : else
1679 : // No further Interception
1680 0 : break;
1681 : }
1682 : else
1683 0 : nLevels = nLevels + pParent->pImp->aStack.size();
1684 :
1685 0 : pParent = pParent->pImp->pParent;
1686 : }
1687 :
1688 0 : if ( bSelf )
1689 : {
1690 : // Query the ComponentViewShell
1691 0 : Flush();
1692 0 : SfxShell *pObjShell = GetShell(0);
1693 0 : SfxInterface *pIFace = pObjShell->GetInterface();
1694 0 : const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
1695 :
1696 0 : if ( pSlot )
1697 : {
1698 0 : rServer.SetSlot(pSlot);
1699 0 : rServer.SetShellLevel(0);
1700 0 : return true;
1701 : }
1702 : }
1703 :
1704 0 : return false;
1705 : }
1706 :
1707 : /** This helper method searches for the <Slot-Server> which currently serves
1708 : the nSlot. As the result, rServe is filled accordingly.
1709 :
1710 : If known the SfxInterface which is currently served by nSlot can be
1711 : passed along.
1712 :
1713 : The SfxDispatcher is flushed while searching for nSlot.
1714 :
1715 : @param nSlot Slot-Id to search for
1716 : @param rServer <SfxSlotServer>-Instance to fill
1717 : @param bModal Dispite ModalMode
1718 :
1719 : @return true
1720 : The Slot was found, rServer is valid.
1721 :
1722 : false
1723 : The Slot is currently not served, rServer is invalid.
1724 : */
1725 259781 : bool SfxDispatcher::_FindServer(sal_uInt16 nSlot, SfxSlotServer& rServer, bool bModal)
1726 : {
1727 : SFX_STACK(SfxDispatcher::_FindServer);
1728 :
1729 : // Dispatcher locked? (nevertheless let SID_HELP_PI through)
1730 259781 : if ( IsLocked(nSlot) )
1731 : {
1732 0 : pImp->bInvalidateOnUnlock = true;
1733 0 : return false;
1734 : }
1735 :
1736 : // Count the number of Shells in the linked dispatchers.
1737 259781 : Flush();
1738 259781 : sal_uInt16 nTotCount = pImp->aStack.size();
1739 259781 : if ( pImp->pParent )
1740 : {
1741 0 : SfxDispatcher *pParent = pImp->pParent;
1742 0 : while ( pParent )
1743 : {
1744 0 : nTotCount = nTotCount + pParent->pImp->aStack.size();
1745 0 : pParent = pParent->pImp->pParent;
1746 : }
1747 : }
1748 :
1749 : // Verb-Slot?
1750 259781 : if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
1751 : {
1752 0 : for ( sal_uInt16 nShell = 0;; ++nShell )
1753 : {
1754 0 : SfxShell *pSh = GetShell(nShell);
1755 0 : if ( pSh == NULL )
1756 0 : return false;
1757 0 : if ( pSh->ISA(SfxViewShell) )
1758 : {
1759 0 : const SfxSlot* pSlot = pSh->GetVerbSlot_Impl(nSlot);
1760 0 : if ( pSlot )
1761 : {
1762 0 : rServer.SetShellLevel(nShell);
1763 0 : rServer.SetSlot( pSlot );
1764 0 : return true;
1765 : }
1766 : }
1767 0 : }
1768 : }
1769 :
1770 : // SID check against set filter
1771 259781 : SfxSlotFilterState nSlotEnableMode = SFX_SLOT_FILTER_DISABLED;
1772 259781 : if ( pImp->pFrame )
1773 : {
1774 259662 : nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
1775 259662 : if ( SFX_SLOT_FILTER_DISABLED == nSlotEnableMode )
1776 0 : return false;
1777 : }
1778 :
1779 : // In Quiet-Mode only Parent-Dispatcher
1780 259781 : if ( pImp->bQuiet )
1781 : {
1782 0 : if ( pImp->pParent )
1783 : {
1784 0 : bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
1785 : rServer.SetShellLevel
1786 0 : ( rServer.GetShellLevel() + pImp->aStack.size() );
1787 0 : return bRet;
1788 : }
1789 : else
1790 0 : return false;
1791 : }
1792 :
1793 259781 : bool bReadOnly = ( SFX_SLOT_FILTER_ENABLED_READONLY != nSlotEnableMode && pImp->bReadOnly );
1794 :
1795 : // search through all the shells of the chained dispatchers
1796 : // from top to bottom
1797 259781 : sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.size() : 0;
1798 635956 : for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
1799 : {
1800 627086 : SfxShell *pObjShell = GetShell(i);
1801 627086 : SfxInterface *pIFace = pObjShell->GetInterface();
1802 627086 : const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
1803 :
1804 627086 : if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
1805 0 : return false;
1806 :
1807 627086 : if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
1808 98 : return false;
1809 :
1810 626988 : if ( pSlot )
1811 : {
1812 : // Slot belongs to Container?
1813 250921 : bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
1814 250921 : bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1815 :
1816 : // Shell belongs to Server?
1817 : // AppDispatcher or IPFrame-Dispatcher
1818 250921 : bool bIsServerShell = !pImp->pFrame || bIsInPlace;
1819 :
1820 : // Of course ShellServer-Slots are also executable even when it is
1821 : // excecuted on a container dispatcher without a IPClient.
1822 250921 : if ( !bIsServerShell )
1823 : {
1824 250802 : SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
1825 250802 : bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
1826 : }
1827 :
1828 : // Shell belongs to Container?
1829 : // AppDispatcher or no IPFrameDispatcher
1830 250921 : bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
1831 : // Shell and Slot match
1832 250921 : if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
1833 230346 : ( !bIsContainerSlot && bIsServerShell ) ) )
1834 108 : pSlot = 0;
1835 : }
1836 :
1837 626988 : if ( pSlot )
1838 : {
1839 250813 : rServer.SetSlot(pSlot);
1840 250813 : rServer.SetShellLevel(i);
1841 250813 : return true;
1842 : }
1843 : }
1844 :
1845 8870 : return false;
1846 : }
1847 :
1848 : /** Helper method to obtain the status of the <Slot-Server>s rSvr.
1849 : The required slots IDs (partly converted to Which-IDs of the pool)
1850 : must be present in rstate.
1851 :
1852 : The SfxDispatcher is flushed before the query.
1853 :
1854 : @param rSvr Slot-Server to query
1855 : @param rState SfxItemSet to be filled
1856 : @param pRealSlot The actual Slot if possible
1857 : */
1858 11428 : bool SfxDispatcher::_FillState(const SfxSlotServer& rSvr, SfxItemSet& rState,
1859 : const SfxSlot* pRealSlot)
1860 : {
1861 : SFX_STACK(SfxDispatcher::_FillState);
1862 :
1863 11428 : const SfxSlot *pSlot = rSvr.GetSlot();
1864 11428 : if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
1865 : {
1866 0 : pImp->bInvalidateOnUnlock = true;
1867 0 : return false;
1868 : }
1869 :
1870 11428 : if ( pSlot )
1871 : {
1872 : DBG_ASSERT(pImp->bFlushed,
1873 : "Dispatcher not flushed after retrieving slot servers!");
1874 11428 : if (!pImp->bFlushed)
1875 0 : return false;
1876 :
1877 : // Determine the object and call the Message of this object
1878 11428 : SfxShell *pSh = GetShell(rSvr.GetShellLevel());
1879 : DBG_ASSERT(pSh, "ObjectShell not found");
1880 :
1881 : SfxStateFunc pFunc;
1882 :
1883 11428 : if (pRealSlot)
1884 11428 : pFunc = pRealSlot->GetStateFnc();
1885 : else
1886 0 : pFunc = pSlot->GetStateFnc();
1887 :
1888 11428 : pSh->CallState( pFunc, rState );
1889 : #ifdef DBG_UTIL
1890 : // To examine the conformity of IDL (SlotMap) and current Items
1891 : if ( rState.Count() )
1892 : {
1893 : SfxInterface *pIF = pSh->GetInterface();
1894 : SfxItemIter aIter( rState );
1895 : for ( const SfxPoolItem *pItem = aIter.FirstItem();
1896 : pItem;
1897 : pItem = aIter.NextItem() )
1898 : {
1899 : if ( !IsInvalidItem(pItem) && !pItem->ISA(SfxVoidItem) )
1900 : {
1901 : sal_uInt16 nSlotId = rState.GetPool()->GetSlotId(pItem->Which());
1902 : SAL_INFO_IF(
1903 : !pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()),
1904 : "sfx.control",
1905 : "item-type unequal to IDL (=> no BASIC) with SID: "
1906 : << nSlotId << " in " << pIF->GetClassName());
1907 : }
1908 : }
1909 : }
1910 : #endif
1911 :
1912 11428 : return true;
1913 : }
1914 :
1915 0 : return false;
1916 : }
1917 :
1918 0 : SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId, vcl::Window *pWin, const Point *pPos )
1919 : {
1920 0 : SfxDispatcher &rDisp = *SfxGetpApp()->GetDispatcher_Impl();
1921 0 : sal_uInt16 nShLevel = 0;
1922 : SfxShell *pSh;
1923 :
1924 0 : if ( rDisp.pImp->bQuiet )
1925 : {
1926 0 : nConfigId = 0;
1927 0 : nShLevel = rDisp.pImp->aStack.size();
1928 : }
1929 :
1930 0 : vcl::Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
1931 0 : for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
1932 : {
1933 0 : const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
1934 0 : if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
1935 : {
1936 0 : return SfxPopupMenuManager::Popup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
1937 : }
1938 : }
1939 0 : return 0;
1940 : }
1941 :
1942 0 : void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, vcl::Window *pWin, const Point *pPos )
1943 : {
1944 0 : SfxDispatcher &rDisp = *SfxGetpApp()->GetDispatcher_Impl();
1945 0 : sal_uInt16 nShLevel = 0;
1946 : SfxShell *pSh;
1947 :
1948 0 : if ( rDisp.pImp->bQuiet )
1949 : {
1950 0 : nConfigId = 0;
1951 0 : nShLevel = rDisp.pImp->aStack.size();
1952 : }
1953 :
1954 0 : vcl::Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
1955 0 : for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
1956 : {
1957 0 : const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
1958 0 : if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
1959 : {
1960 0 : SfxPopupMenuManager::ExecutePopup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
1961 0 : return;
1962 : }
1963 : }
1964 : }
1965 :
1966 0 : void SfxDispatcher::ExecutePopup( const ResId &rId, vcl::Window *pWin, const Point *pPos )
1967 : {
1968 0 : vcl::Window *pWindow = pWin ? pWin : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
1969 0 : SfxPopupMenuManager::ExecutePopup( rId, GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
1970 0 : }
1971 :
1972 : /** With this method the SfxDispatcher can be locked and released. A locked
1973 : SfxDispatcher does not perform <SfxRequest>s and does no longer provide
1974 : status information. It behaves as if all the slots were disabled.
1975 : */
1976 20770 : void SfxDispatcher::Lock( bool bLock )
1977 : {
1978 20770 : SfxBindings* pBindings = GetBindings();
1979 20770 : if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
1980 : {
1981 0 : if ( pBindings )
1982 0 : pBindings->InvalidateAll(true);
1983 0 : pImp->bInvalidateOnUnlock = false;
1984 : }
1985 20770 : else if ( pBindings )
1986 20770 : pBindings->InvalidateAll(false);
1987 20770 : pImp->bLocked = bLock;
1988 20770 : if ( !bLock )
1989 : {
1990 10392 : for(size_t i = 0; i < pImp->aReqArr.size(); ++i)
1991 0 : pImp->xPoster->Post(pImp->aReqArr[i]);
1992 10392 : pImp->aReqArr.clear();
1993 : }
1994 20770 : }
1995 :
1996 48 : sal_uInt32 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
1997 : {
1998 48 : return pImp->aObjBars[nPos].nResId;
1999 : }
2000 :
2001 5454 : void SfxDispatcher::HideUI( bool bHide )
2002 : {
2003 5454 : bool bWasHidden = pImp->bNoUI;
2004 5454 : pImp->bNoUI = bHide;
2005 5454 : if ( pImp->pFrame )
2006 : {
2007 5454 : SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
2008 5454 : if ( pTop && pTop->GetBindings().GetDispatcher() == this )
2009 : {
2010 5454 : SfxFrame& rFrame = pTop->GetFrame();
2011 5454 : if ( rFrame.IsMenuBarOn_Impl() )
2012 : {
2013 5454 : com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
2014 5454 : if ( xPropSet.is() )
2015 : {
2016 5454 : com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
2017 10908 : com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
2018 5454 : aValue >>= xLayoutManager;
2019 5454 : if ( xLayoutManager.is() )
2020 10908 : xLayoutManager->setVisible( !bHide );
2021 5454 : }
2022 : }
2023 : }
2024 : }
2025 :
2026 5454 : if ( bHide != bWasHidden )
2027 0 : Update_Impl( true );
2028 5454 : }
2029 :
2030 5508 : void SfxDispatcher::SetReadOnly_Impl( bool bOn )
2031 : {
2032 5508 : pImp->bReadOnly = bOn;
2033 5508 : }
2034 :
2035 20 : bool SfxDispatcher::GetReadOnly_Impl() const
2036 : {
2037 20 : return pImp->bReadOnly;
2038 : }
2039 :
2040 : /** With 'bOn' the Dispatcher is quasi dead and transfers everything to the
2041 : Parent-Dispatcher.
2042 : */
2043 0 : void SfxDispatcher::SetQuietMode_Impl( bool bOn )
2044 : {
2045 0 : pImp->bQuiet = bOn;
2046 0 : SfxBindings* pBindings = GetBindings();
2047 0 : if ( pBindings )
2048 0 : pBindings->InvalidateAll(true);
2049 0 : }
2050 :
2051 8669 : SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
2052 : {
2053 8669 : SfxShell *pShell = 0;
2054 8669 : const SfxSlot *pSlot = 0;
2055 8669 : if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, false, false ) )
2056 : {
2057 8633 : rpState = pShell->GetSlotState(nSlot);
2058 8633 : if ( !rpState )
2059 1 : return SfxItemState::DISABLED;
2060 : else
2061 8632 : return SfxItemState::DEFAULT;
2062 : }
2063 :
2064 36 : return SfxItemState::DISABLED;
2065 : }
2066 :
2067 140869 : SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno::Any& rAny )
2068 : {
2069 140869 : SfxShell *pShell = 0;
2070 140869 : const SfxSlot *pSlot = 0;
2071 140869 : if ( GetShellAndSlot_Impl( nSID, &pShell, &pSlot, false, false ) )
2072 : {
2073 137131 : const SfxPoolItem* pItem( 0 );
2074 :
2075 137131 : pItem = pShell->GetSlotState( nSID );
2076 137131 : if ( !pItem )
2077 9095 : return SfxItemState::DISABLED;
2078 : else
2079 : {
2080 128036 : ::com::sun::star::uno::Any aState;
2081 128036 : if ( !pItem->ISA(SfxVoidItem) )
2082 : {
2083 88548 : sal_uInt16 nSubId( 0 );
2084 88548 : SfxItemPool& rPool = pShell->GetPool();
2085 88548 : sal_uInt16 nWhich = rPool.GetWhich( nSID );
2086 88548 : if ( rPool.GetMetric( nWhich ) == SFX_MAPUNIT_TWIP )
2087 73971 : nSubId |= CONVERT_TWIPS;
2088 88548 : pItem->QueryValue( aState, (sal_uInt8)nSubId );
2089 : }
2090 128036 : rAny = aState;
2091 :
2092 128036 : return SfxItemState::DEFAULT;
2093 : }
2094 : }
2095 :
2096 3738 : return SfxItemState::DISABLED;
2097 : }
2098 :
2099 80781 : bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
2100 : {
2101 80781 : sal_uInt16 nShellCount = pImp->aStack.size();
2102 80781 : if ( nShell < nShellCount )
2103 : {
2104 80781 : SfxShell* pShell = *( pImp->aStack.rbegin() + nShell );
2105 80781 : if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
2106 35751 : return false;
2107 : else
2108 45030 : return pImp->bReadOnly;
2109 : }
2110 0 : else if ( pImp->pParent )
2111 0 : return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
2112 0 : return true;
2113 : }
2114 :
2115 6520 : void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
2116 : {
2117 6520 : Flush();
2118 :
2119 6520 : sal_uInt16 nCount = pImp->aStack.size();
2120 18488 : for ( sal_uInt16 n=0; n<nCount; ++n )
2121 : {
2122 18488 : if ( pImp->aStack[n] == &rShell )
2123 : {
2124 6520 : pImp->aStack.erase( pImp->aStack.begin() + n );
2125 6520 : rShell.SetDisableFlags( 0 );
2126 6520 : rShell.DoDeactivate_Impl(pImp->pFrame, true);
2127 6520 : break;
2128 : }
2129 : }
2130 :
2131 6520 : if ( !SfxGetpApp()->IsDowning() )
2132 : {
2133 6520 : pImp->bUpdated = false;
2134 6520 : pImp->pCachedServ1 = 0;
2135 6520 : pImp->pCachedServ2 = 0;
2136 6520 : InvalidateBindings_Impl(true);
2137 : }
2138 6520 : }
2139 :
2140 34775 : void SfxDispatcher::InvalidateBindings_Impl( bool bModify )
2141 : {
2142 : // App-Dispatcher?
2143 34775 : if ( IsAppDispatcher() )
2144 : {
2145 471 : for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst();
2146 : pFrame;
2147 : pFrame = SfxViewFrame::GetNext( *pFrame ) )
2148 0 : pFrame->GetBindings().InvalidateAll(bModify);
2149 : }
2150 : else
2151 : {
2152 34304 : SfxDispatcher *pDisp = GetBindings()->GetDispatcher_Impl();
2153 68608 : while ( pDisp )
2154 : {
2155 34304 : if ( pDisp == this )
2156 : {
2157 34304 : GetBindings()->InvalidateAll( bModify );
2158 34304 : break;
2159 : }
2160 :
2161 0 : pDisp = pDisp->pImp->pParent;
2162 : }
2163 : }
2164 34775 : }
2165 :
2166 0 : bool SfxDispatcher::IsUpdated_Impl() const
2167 : {
2168 0 : return pImp->bUpdated;
2169 : }
2170 :
2171 11046 : void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
2172 : {
2173 11046 : pImp->nDisableFlags = nFlags;
2174 44234 : for ( SfxShellStack_Impl::reverse_iterator it = pImp->aStack.rbegin(); it != pImp->aStack.rend(); ++it )
2175 33188 : (*it)->SetDisableFlags( nFlags );
2176 11046 : }
2177 :
2178 49196 : sal_uInt32 SfxDispatcher::GetDisableFlags() const
2179 : {
2180 49196 : return pImp->nDisableFlags;
2181 : }
2182 :
2183 0 : SfxModule* SfxDispatcher::GetModule() const
2184 : {
2185 0 : for ( sal_uInt16 nShell = 0;; ++nShell )
2186 : {
2187 0 : SfxShell *pSh = GetShell(nShell);
2188 0 : if ( pSh == NULL )
2189 0 : return 0;
2190 0 : if ( pSh->ISA(SfxModule) )
2191 0 : return static_cast<SfxModule*>(pSh);
2192 0 : }
2193 951 : }
2194 :
2195 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|