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 <com/sun/star/embed/VerbDescriptor.hpp>
21 : #include <com/sun/star/embed/VerbAttributes.hpp>
22 : #include <basic/sbstar.hxx>
23 : #include <officecfg/Office/Common.hxx>
24 : #include <rtl/ustring.hxx>
25 : #include <sal/log.hxx>
26 : #include <svl/itempool.hxx>
27 : #include <svl/undo.hxx>
28 : #include <svtools/itemdel.hxx>
29 : #include <svtools/asynclink.hxx>
30 : #include <basic/sbx.hxx>
31 :
32 : #include <sfx2/app.hxx>
33 : #include <sfx2/shell.hxx>
34 : #include <sfx2/bindings.hxx>
35 : #include <sfx2/dispatch.hxx>
36 : #include <sfx2/viewfrm.hxx>
37 : #include <sfx2/objface.hxx>
38 : #include <sfx2/objsh.hxx>
39 : #include <sfx2/viewsh.hxx>
40 : #include "sfxtypes.hxx"
41 : #include <sfx2/request.hxx>
42 : #include <sfx2/mnumgr.hxx>
43 : #include "statcach.hxx"
44 : #include <sfx2/msgpool.hxx>
45 : #include <sfx2/sidebar/ContextChangeBroadcaster.hxx>
46 :
47 : #include <map>
48 :
49 :
50 : // Maps the Which() field to a pointer to a SfxPoolItem
51 15456 : class SfxItemPtrMap : public std::map<sal_uInt16, SfxPoolItem*>
52 : {
53 : public:
54 14988 : ~SfxItemPtrMap()
55 14988 : {
56 32446 : for(iterator it = begin(); it != end(); ++it)
57 17458 : delete it->second;
58 14988 : }
59 : };
60 :
61 230864 : TYPEINIT0(SfxShell);
62 :
63 :
64 15456 : class SfxVerbSlotArr_Impl : public std::vector<SfxSlot*>
65 : {
66 : public:
67 14988 : ~SfxVerbSlotArr_Impl()
68 14988 : {
69 14988 : for(const_iterator it = begin(); it != end(); ++it)
70 0 : delete *it;
71 14988 : }
72 : };
73 :
74 : using namespace com::sun::star;
75 :
76 :
77 : // SfxShell_Impl
78 :
79 : struct SfxShell_Impl: public SfxBroadcaster
80 : {
81 : OUString aObjectName; // Name of Sbx-Objects
82 : SfxItemPtrMap aItems; // Data exchange on Item level
83 : SfxViewShell* pViewSh; // SfxViewShell if Shell is
84 : // ViewFrame/ViewShell/SubShell list
85 : SfxViewFrame* pFrame; // Frame, if <UI-active>
86 : SfxRepeatTarget* pRepeatTarget; // SbxObjectRef xParent;
87 : bool bInAppBASIC;
88 : bool bActive;
89 : sal_uIntPtr nDisableFlags;
90 : sal_uIntPtr nHelpId;
91 : svtools::AsynchronLink* pExecuter;
92 : svtools::AsynchronLink* pUpdater;
93 : SfxVerbSlotArr_Impl aSlotArr;
94 :
95 : com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aVerbList;
96 : ::sfx2::sidebar::ContextChangeBroadcaster maContextChangeBroadcaster;
97 :
98 15456 : SfxShell_Impl() : pViewSh(0), pFrame(0), pRepeatTarget(0), pExecuter(0), pUpdater(0) {}
99 29976 : virtual ~SfxShell_Impl() { delete pExecuter; delete pUpdater;}
100 : };
101 :
102 :
103 : // SfxShell
104 :
105 :
106 0 : void SfxShell::EmptyExecStub(SfxShell *, SfxRequest &)
107 : {
108 0 : }
109 :
110 5992 : void SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &)
111 : {
112 5992 : }
113 :
114 5670 : SfxShell::SfxShell()
115 :
116 : /* [Description]
117 :
118 : The constructor of the SfxShell class initializes only simple types,
119 : the corresponding SbxObject is only created on-demand. Therefore,
120 : the application of a SfxShell instance is very cheap.
121 : */
122 :
123 : : pImp(0),
124 : pPool(0),
125 5670 : pUndoMgr(0)
126 : {
127 5670 : pImp = new SfxShell_Impl;
128 5670 : pImp->pViewSh = 0;
129 5670 : pImp->pFrame = 0;
130 5670 : pImp->pRepeatTarget = 0;
131 5670 : pImp->bInAppBASIC = false;
132 5670 : pImp->nHelpId = 0L;
133 5670 : pImp->bActive = false;
134 5670 : pImp->nDisableFlags = 0;
135 5670 : }
136 :
137 :
138 :
139 9786 : SfxShell::SfxShell( SfxViewShell *pViewSh )
140 :
141 : /* [Description]
142 :
143 : The constructor of the SfxShell class initializes only simple types,
144 : the corresponding SbxObject is only created on-demand. Therefore,
145 : the application of a SfxShell instance is very cheap.
146 : */
147 :
148 : : pImp(0),
149 : pPool(0),
150 9786 : pUndoMgr(0)
151 : {
152 9786 : pImp = new SfxShell_Impl;
153 9786 : pImp->pViewSh = pViewSh;
154 9786 : pImp->pFrame = 0;
155 9786 : pImp->pRepeatTarget = 0;
156 9786 : pImp->bInAppBASIC = false;
157 9786 : pImp->nHelpId = 0L;
158 9786 : pImp->bActive = false;
159 9786 : }
160 :
161 :
162 :
163 29976 : SfxShell::~SfxShell()
164 :
165 : /* [Description]
166 :
167 : The connection to a possible corresponding SbxObject is dissolved.
168 : The SbxObject may continoue to exist, but can not any longer perform
169 : any functions and can not provide any properties.
170 : */
171 :
172 : {
173 :
174 :
175 14988 : delete pImp;
176 14988 : }
177 :
178 :
179 :
180 27612 : void SfxShell::SetName( const OUString &rName )
181 :
182 : /* [Description]
183 :
184 : Sets the name of the Shell object. With this name, the SfxShell instance
185 : of BASIC can be expressed.
186 : */
187 :
188 : {
189 27612 : pImp->aObjectName = rName;
190 27612 : }
191 :
192 :
193 :
194 17403 : const OUString& SfxShell::GetName() const
195 :
196 : /* [Description]
197 :
198 : Returns the name of the Shell object. With this name, the SfxShell instance
199 : of BASIC can be expressed.
200 : */
201 :
202 : {
203 17403 : return pImp->aObjectName;
204 : }
205 :
206 :
207 :
208 8947 : SfxDispatcher* SfxShell::GetDispatcher() const
209 :
210 : /* [Description]
211 :
212 : This method returns a pointer to the <SfxDispatcher>, when the SfxShell
213 : is currently <UI-active> or a NULL-pointer if it is not UI-active.
214 :
215 : The returned pointer is only valid in the immediate context of the method
216 : call.
217 : */
218 :
219 : {
220 8947 : return pImp->pFrame ? pImp->pFrame->GetDispatcher() : 0;
221 : }
222 :
223 :
224 :
225 421612 : SfxViewShell* SfxShell::GetViewShell() const
226 :
227 : /* [Description]
228 :
229 : Returns the SfxViewShell in which they are located in the subshells.
230 : Otherwise, and if not specified by the App developer, this method
231 : returns NULL.
232 : */
233 :
234 : {
235 421612 : return pImp->pViewSh;
236 : }
237 :
238 :
239 :
240 38028 : SfxViewFrame* SfxShell::GetFrame() const
241 :
242 : /* [Description]
243 :
244 : This method returns a pointer to the <SfxViewFrame> to which this SfxShell
245 : instance is associated or in which they currently is <UI-active>.
246 : A NULL pointer is returned if this SfxShell instance is not UI-active at
247 : the moment and also no SfxViewFrame is permanently assigned.
248 :
249 : The returned pointer is only valid in the immediate context of the method
250 : call.
251 :
252 : [Note]
253 :
254 : Only instances of a subclass of SfxApplication and SfxObjectShell
255 : should here provide a NULL-pointer. Otherwise, there is an error in the
256 : application program (wrong constructor was called from SfxShell).
257 :
258 : [Cross-reference]
259 :
260 : <SfxViewShell::GetViewFrame()const>
261 : */
262 :
263 : {
264 38028 : if ( pImp->pFrame )
265 14265 : return pImp->pFrame;
266 23763 : if ( pImp->pViewSh )
267 14220 : return pImp->pViewSh->GetViewFrame();
268 9543 : return 0;
269 : }
270 :
271 :
272 :
273 11266 : const SfxPoolItem* SfxShell::GetItem
274 : (
275 : sal_uInt16 nSlotId // Slot-Id of the querying <SfxPoolItem>s
276 : ) const
277 :
278 : /* [Description]
279 :
280 : With this method any objects of <SfxPoolItemu> subclasses can be accessed.
281 : This exchange method is needed if, for example special <SfxToolBoxControl>
282 : subclasses need access to certain data such as the <SfxObjectShell>.
283 :
284 : The returned instance belongs to the particular SfxShell and may be
285 : used only in the immediate context of the method call.
286 :
287 : [Cross-reference]
288 :
289 : <SfxShell::PutItem(const SfxPoolItem&)>
290 : <SfxShell::RemoveItem(sal_uInt16)>
291 : */
292 :
293 : {
294 11266 : SfxItemPtrMap::iterator it = pImp->aItems.find( nSlotId );
295 11266 : if( it != pImp->aItems.end() )
296 11100 : return it->second;
297 166 : return 0;
298 : }
299 :
300 :
301 :
302 20807 : void SfxShell::PutItem
303 : (
304 : const SfxPoolItem& rItem /* Instance, of which a copy is created,
305 : which is stored in the SfxShell in a list. */
306 : )
307 :
308 : /* [Description]
309 :
310 : With this method, any objects of subclasses of <SfxPoolItem> can be made
311 : available. This exchange technology is needed if, for example, special
312 : <SfxToolBoxControl> Subclasses need access to certain data such as the
313 : <SfxObjectShell>
314 :
315 : If a SfxPoolItem exists with the same slot ID, it is deleted automatically.
316 :
317 : [Cross-reference]
318 :
319 : <SfxShell::RemoveItem(sal_uInt16)>
320 : <SfxShell::GetItem(sal_uInt16)>
321 : */
322 :
323 : {
324 : DBG_ASSERT( !rItem.ISA(SfxSetItem), "SetItems aren't allowed here" );
325 : DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
326 : "items with Which-Ids aren't allowed here" );
327 :
328 : // MSC made a mess here of WNT/W95, beware of changes
329 20807 : SfxPoolItem *pItem = rItem.Clone();
330 20807 : SfxPoolItemHint aItemHint( pItem );
331 20807 : const sal_uInt16 nWhich = rItem.Which();
332 :
333 20807 : SfxItemPtrMap::iterator it = pImp->aItems.find( nWhich );
334 20807 : if( it != pImp->aItems.end() )
335 : {
336 2945 : SfxPoolItem *pLoopItem = it->second;
337 : // Replace Item
338 2945 : delete pLoopItem;
339 2945 : it->second = pItem;
340 :
341 : // if active, notify Bindings
342 2945 : SfxDispatcher *pDispat = GetDispatcher();
343 2945 : if ( pDispat )
344 : {
345 470 : SfxBindings* pBindings = pDispat->GetBindings();
346 470 : pBindings->Broadcast( aItemHint );
347 470 : sal_uInt16 nSlotId = nWhich; //pItem->GetSlotId();
348 470 : SfxStateCache* pCache = pBindings->GetStateCache( nSlotId );
349 470 : if ( pCache )
350 : {
351 114 : pCache->SetState( SFX_ITEM_AVAILABLE, pItem->Clone(), true );
352 114 : pCache->SetCachedState( true );
353 : }
354 : }
355 23752 : return;
356 : }
357 : else
358 : {
359 17862 : Broadcast( aItemHint );
360 17862 : pImp->aItems[ pItem->Which() ] = pItem;
361 17862 : }
362 : }
363 :
364 :
365 :
366 0 : SfxInterface* SfxShell::GetInterface() const
367 :
368 : /* [Description]
369 :
370 : With this virtual method, which is automatically overloaded by each subclass
371 : with its own slots through the macro <SFX_DECL_INTERFACE>, one can access
372 : each of the <SfxInterface> instance beloning to the subclass.
373 :
374 : The class SfxShell itself has no own SfxInterface (no slots), therefore a
375 : NULL-pointer is returned.
376 : */
377 :
378 : {
379 0 : return GetStaticInterface();
380 : }
381 :
382 :
383 :
384 1567 : ::svl::IUndoManager* SfxShell::GetUndoManager()
385 :
386 : /* [Description]
387 :
388 : Each Subclass of SfxShell can hava a <SfxUndoManager>. This can be set in
389 : the derived class with <SfxShell:SetUndoManager()>.
390 :
391 : The class SfxShell itself does not have a SfxUndoManager, a NULL-pointer
392 : is therefore returned.
393 : */
394 :
395 : {
396 1567 : return pUndoMgr;
397 : }
398 :
399 :
400 :
401 6347 : void SfxShell::SetUndoManager( ::svl::IUndoManager *pNewUndoMgr )
402 :
403 : /* [Description]
404 :
405 : Sets a <SfxUndoManager> for this <SfxShell> Instance. For the undo
406 : is only the undo-manager used for SfxShell at the top of the stack of each
407 : <SfxDispatcher>.
408 :
409 : On the given <SfxUndoManager> is automatically the current
410 : Max-Undo-Action-Count setting set form the options.
411 :
412 : 'pNewUndoMgr' must exist until the Destuctor of SfxShell instance is called
413 : or until the next 'SetUndoManager()'.
414 : */
415 :
416 : {
417 : OSL_ENSURE( ( pUndoMgr == NULL ) || ( pNewUndoMgr == NULL ) || ( pUndoMgr == pNewUndoMgr ),
418 : "SfxShell::SetUndoManager: exchanging one non-NULL manager with another non-NULL manager? Suspicious!" );
419 : // there's at least one client of our UndoManager - the DocumentUndoManager at the SfxBaseModel - which
420 : // caches the UndoManager, and registers itself as listener. If exchanging non-NULL UndoManagers is really
421 : // a supported scenario (/me thinks it is not), then we would need to notify all such clients instances.
422 :
423 6347 : pUndoMgr = pNewUndoMgr;
424 6347 : if ( pUndoMgr )
425 : pUndoMgr->SetMaxUndoActionCount(
426 4415 : officecfg::Office::Common::Undo::Steps::get());
427 6347 : }
428 :
429 :
430 :
431 448 : SfxRepeatTarget* SfxShell::GetRepeatTarget() const
432 :
433 : /* [Description]
434 :
435 : Returns a pointer to the <SfxRepeatTarget> instance that is used in
436 : SID_REPEAT as repeat target when it is addressed from the <SfxUndoManager>
437 : supplied by this SfxShell. The return value can be NULL.
438 :
439 : [Note]
440 :
441 : A derivation of <SfxShell> or one of its subclasses of <SfxRepeatTarget>
442 : is not recommended, as compiler errors are provoked.
443 : (due to Call-to-Pointer-to-Member-Function to the subclass).
444 : */
445 :
446 : {
447 448 : return pImp->pRepeatTarget;
448 : }
449 :
450 :
451 :
452 669 : void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget )
453 :
454 : /* [Description]
455 :
456 : Sets the <SfxRepeatTarget> instance that is used in SID_REPEAT as
457 : RepeatTarget, when the current supplied by this <SfxUndoManager> is
458 : addressed. By 'pTarget==0' the SID_REPEAT is disabled for this SfxShell.
459 : The instance '*pTarget' must live as long as it is registered.
460 :
461 : [Note]
462 :
463 : A derivation of <SfxShell> or one of its subclasses of <SfxRepeatTarget>
464 : is not recommended, as compiler errors are provoked.
465 : (due to Call-to-Pointer-to-Member-Function to the subclass).
466 : */
467 :
468 : {
469 669 : pImp->pRepeatTarget = pTarget;
470 669 : }
471 :
472 :
473 :
474 10587 : void SfxShell::Invalidate
475 : (
476 : sal_uInt16 nId /* Invalidated Slot-Id or Which-Id.
477 : If these are 0 (default), then all
478 : by this Shell currently handled Slot-Ids are
479 : invalidated. */
480 : )
481 :
482 : /* [Description]
483 :
484 : With this method can the slots of the subclasses be invalidated through the
485 : slot Id or alternatively through the Which ID. Slot IDs, which are
486 : inherited by the subclass are also invalidert.
487 :
488 : [Cross-reference]
489 :
490 : <SfxBindings::Invalidate(sal_uInt16)>
491 : <SfxBindings::InvalidateAll(sal_Bool)>
492 : */
493 :
494 : {
495 10587 : if ( !GetViewShell() )
496 : {
497 : OSL_FAIL( "wrong Invalidate method called!" );
498 10587 : return;
499 : }
500 :
501 10587 : Invalidate_Impl( GetViewShell()->GetViewFrame()->GetBindings(), nId );
502 : }
503 :
504 12459 : void SfxShell::Invalidate_Impl( SfxBindings& rBindings, sal_uInt16 nId )
505 : {
506 12459 : if ( nId == 0 )
507 : {
508 402 : rBindings.InvalidateShell( *this, false );
509 : }
510 : else
511 : {
512 12057 : const SfxInterface *pIF = GetInterface();
513 620 : do
514 : {
515 12057 : const SfxSlot *pSlot = pIF->GetSlot(nId);
516 12057 : if ( pSlot )
517 : {
518 : // At Enum-Slots invalidate the Master-Slot
519 11437 : if ( SFX_KIND_ENUM == pSlot->GetKind() )
520 0 : pSlot = pSlot->GetLinkedSlot();
521 :
522 : // Invalidate the Slot itself and possible also all Slave-Slots
523 11437 : rBindings.Invalidate( pSlot->GetSlotId() );
524 22874 : for ( const SfxSlot *pSlave = pSlot->GetLinkedSlot();
525 11437 : pSlave && pIF->ContainsSlot_Impl( pSlave ) &&
526 0 : pSlave->GetLinkedSlot() == pSlot;
527 : ++pSlave )
528 0 : rBindings.Invalidate( pSlave->GetSlotId() );
529 :
530 23896 : return;
531 : }
532 :
533 620 : pIF = pIF->GetGenoType();
534 : }
535 :
536 : while ( pIF );
537 :
538 : DBG_WARNING( "W3: invalidating slot-id unknown in shell" );
539 : }
540 : }
541 :
542 :
543 :
544 16377 : void SfxShell::DoActivate_Impl( SfxViewFrame *pFrame, bool bMDI )
545 :
546 : /* [Description]
547 :
548 : This method controls the activation of SfxShell instance. First, by calling
549 : the virtual method <SfxShell::Activate(sal_Bool)> which gives the subclass the
550 : opportunity to respond to the event.
551 :
552 : When bMDI == TRUE, the associated SbxObject is being 'armed', so that
553 : unqualified methods of the object (without the name of the object)
554 : from BASIC are found.
555 : */
556 :
557 : {
558 : #ifdef DBG_UTIL
559 : const SfxInterface *p_IF = GetInterface();
560 : if ( !p_IF )
561 : return;
562 : #endif
563 : SAL_INFO(
564 : "sfx.control",
565 : "SfxShell::DoActivate() " << this << " " << GetInterface()->GetName()
566 : << " bMDI " << (bMDI ? "MDI" : ""));
567 :
568 16377 : if ( bMDI )
569 : {
570 : // Remember Frame, in which it was activated
571 16377 : pImp->pFrame = pFrame;
572 16377 : pImp->bActive = true;
573 : }
574 :
575 : // Notify Subclass
576 16377 : Activate(bMDI);
577 16377 : }
578 :
579 :
580 :
581 18485 : void SfxShell::DoDeactivate_Impl( SfxViewFrame *pFrame, bool bMDI )
582 :
583 : /* [Description]
584 :
585 : This method controls the deactivation of the SfxShell instance. When
586 : bMDI == TRUE the SbxObject is first set to a status that only qualified
587 : BASIC methods can be called.
588 :
589 : Then the subclass gets the opportunity in every case to respond to the
590 : event by calling the virtual method <SfxShell::Deactivate(sal_Bool)>.
591 : */
592 :
593 : {
594 : #ifdef DBG_UTIL
595 : const SfxInterface *p_IF = GetInterface();
596 : if ( !p_IF )
597 : return;
598 : #endif
599 : SAL_INFO(
600 : "sfx.control",
601 : "SfxShell::DoDeactivate()" << this << " " << GetInterface()->GetName()
602 : << " bMDI " << (bMDI ? "MDI" : ""));
603 :
604 : // Only when it comes from a Frame
605 : // (not when for instance by poping BASIC-IDE from AppDisp)
606 18485 : if ( bMDI && pImp->pFrame == pFrame )
607 : {
608 : // deliver
609 16446 : pImp->pFrame = 0;
610 16446 : pImp->bActive = false;
611 : }
612 :
613 : // Notify Subclass
614 18485 : Deactivate(bMDI);
615 18485 : }
616 :
617 :
618 :
619 8005 : bool SfxShell::IsActive() const
620 : {
621 8005 : return pImp->bActive;
622 : }
623 :
624 :
625 :
626 12043 : void SfxShell::Activate
627 : (
628 : bool /*bMDI*/ /* TRUE
629 : the <SfxDispatcher>, on which the SfxShell is
630 : located, is activated or the SfxShell instance
631 : was pushed on an active SfxDispatcher.
632 : (compare with SystemWindow::IsMDIActivate())
633 :
634 : FALSE
635 : the <SfxViewFrame>, on which SfxDispatcher
636 : the SfxShell instance is located, was
637 : activated. (for example by a closing dialoge) */
638 : )
639 :
640 : /* [Description]
641 :
642 : Virtual method that is called when enabling the SfxShell instance,
643 : in order to give the Subclasses the opportunity to respond to the
644 : to the enabling.
645 :
646 : [Cross-reference]
647 :
648 : StarView SystemWindow::Activate(bool)
649 : */
650 :
651 : {
652 12043 : BroadcastContextForActivation(true);
653 12043 : }
654 :
655 :
656 :
657 14636 : void SfxShell::Deactivate
658 : (
659 : bool /*bMDI*/ /* TRUE
660 : the <SfxDispatcher>, on which the SfxShell is
661 : located, is inactivated or the SfxShell instance
662 : was popped on an active SfxDispatcher.
663 : (compare with SystemWindow::IsMDIActivate())
664 :
665 : FALSE
666 : the <SfxViewFrame>, on which SfxDispatcher
667 : the SfxShell instance is located, was
668 : deactivated. (for example by a dialoge) */
669 :
670 : )
671 :
672 : /* [Description]
673 :
674 : Virtual method that is called when disabling the SfxShell instance,
675 : to give the Subclasses the opportunity to respond to the disabling.
676 :
677 : [Cross-reference]
678 :
679 : StarView SystemWindow::Dectivate(bool)
680 : */
681 :
682 : {
683 14636 : BroadcastContextForActivation(false);
684 14636 : }
685 :
686 :
687 0 : void SfxShell::ParentActivate
688 : (
689 : )
690 :
691 : /* [Description]
692 :
693 : A parent of the <SfxDispatcher> on which the SfxShell is located, has
694 : become active, or the SfxShell instance was pushed on a <SfxDispatcher>,
695 : which parent is active.
696 :
697 : The base implementation is empty and does not need to be called.
698 :
699 : [Cross-reference]
700 :
701 : SfxShell::Activate()
702 : */
703 : {
704 0 : }
705 :
706 :
707 :
708 0 : void SfxShell::ParentDeactivate
709 : (
710 : )
711 :
712 : /* [Description]
713 :
714 : The active parent of the <SfxDispatcher> on which the SfxShell is located,
715 : has been disabled.
716 :
717 : The base implementation is empty and does not need to be called.
718 :
719 : [Cross-reference]
720 :
721 : SfxShell::Deactivate()
722 : */
723 : {
724 0 : }
725 :
726 :
727 :
728 60 : ResMgr* SfxShell::GetResMgr() const
729 :
730 : /* [Description]
731 :
732 : This method provides the ResMgr of the <Resource-DLL> that are used by
733 : the SfxShell instance. If this is a NULL-pointer, then the current
734 : resource manager is to be used.
735 : */
736 :
737 : {
738 60 : return GetInterface()->GetResMgr();
739 : }
740 :
741 :
742 :
743 641 : bool SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot )
744 :
745 : /* [Description]
746 :
747 : This method determines by calling the status function whether 'rSlot'
748 : can be executed currently.
749 : */
750 : {
751 : // Get Slot status
752 641 : SfxItemPool &rPool = GetPool();
753 641 : const sal_uInt16 nId = rSlot.GetWhich( rPool );
754 641 : SfxItemSet aSet(rPool, nId, nId);
755 641 : SfxStateFunc pFunc = rSlot.GetStateFnc();
756 641 : CallState( pFunc, aSet );
757 641 : return aSet.GetItemState(nId) != SFX_ITEM_DISABLED;
758 : }
759 :
760 :
761 :
762 0 : long ShellCall_Impl( void* pObj, void* pArg )
763 : {
764 0 : ((SfxShell* )pObj)->ExecuteSlot( *(SfxRequest*)pArg, (SfxInterface*)0L );
765 0 : return 0;
766 : }
767 :
768 : /* [Description]
769 :
770 : Asynchronous ExecuteSlot for the RELOAD
771 : */
772 :
773 :
774 0 : const SfxPoolItem* SfxShell::ExecuteSlot( SfxRequest& rReq, bool bAsync )
775 : {
776 0 : if( !bAsync )
777 0 : return ExecuteSlot( rReq, (SfxInterface*)0L );
778 : else
779 : {
780 0 : if( !pImp->pExecuter )
781 : pImp->pExecuter = new svtools::AsynchronLink(
782 0 : Link( this, ShellCall_Impl ) );
783 0 : pImp->pExecuter->Call( new SfxRequest( rReq ) );
784 0 : return 0;
785 : }
786 : }
787 :
788 249 : const SfxPoolItem* SfxShell::ExecuteSlot
789 : (
790 : SfxRequest &rReq, // the relayed <SfxRequest>
791 : const SfxInterface* pIF // default = 0 means get virtually
792 : )
793 :
794 : /* [Description]
795 :
796 : This method allows you to forward a <SfxRequest> to the specified
797 : base <SfxShell>.
798 :
799 : [Example]
800 :
801 : In a derived class of SfxViewShell the SID_PRINTDOCDIRECT will be
802 : intercepted. Under certain circumstances a query should appear before
803 : you print, and the request will be aborted if necessary.
804 :
805 : Also in the IDL of this subclass of the above slot is entered. The status
806 : method will contain in outline:
807 :
808 : void SubViewShell::Exec( SfxRequest &rReq )
809 : {
810 : if ( rReq.GetSlot() == SID_PRINTDOCDIRECT )
811 : {
812 : 'dialog'
813 : if ( 'condition' )
814 : ExecuteSlot( rReq, SfxViewShell::GetInterface() );
815 : }
816 : }
817 :
818 : It usually takes no rReq.Done() to be called as that is already completed
819 : in implementation of the SfxViewShell, for instance it has been canceled.
820 :
821 : [Cross-reference]
822 :
823 : <SfxShell::GetSlotState(sal_uInt16,const SfxInterface*,SfxItemSet*)>
824 : */
825 :
826 : {
827 249 : if ( !pIF )
828 249 : pIF = GetInterface();
829 :
830 249 : sal_uInt16 nSlot = rReq.GetSlot();
831 249 : const SfxSlot* pSlot = NULL;
832 249 : if ( nSlot >= SID_VERB_START && nSlot <= SID_VERB_END )
833 0 : pSlot = GetVerbSlot_Impl(nSlot);
834 249 : if ( !pSlot )
835 249 : pSlot = pIF->GetSlot(nSlot);
836 : DBG_ASSERT( pSlot, "slot not supported" );
837 :
838 249 : SfxExecFunc pFunc = pSlot->GetExecFnc();
839 249 : if ( pFunc )
840 249 : CallExec( pFunc, rReq );
841 :
842 249 : return rReq.GetReturnValue();
843 : }
844 :
845 :
846 :
847 60968 : const SfxPoolItem* SfxShell::GetSlotState
848 : (
849 : sal_uInt16 nSlotId, // Slot-Id to the Slots in question
850 : const SfxInterface* pIF, // default = 0 means get virtually
851 : SfxItemSet* pStateSet // SfxItemSet of the Slot-State method
852 : )
853 :
854 : /* [Description]
855 :
856 : This method returns the status of the slot with the specified slot ID
857 : on the specified interface.
858 :
859 : If the slot is disabled or in this SfxShell (and their parent shells) are
860 : not known, a Null-pointer is returned.
861 :
862 : If the slot does not have a Status, a SfxVoidItem is returned.
863 :
864 : The status is set directly in this Set when pStateSet != 0 , so that
865 : overloaded Slots of the <SfxShell> Subclasses and also in the Status
866 : method of the base implementation can be called.
867 :
868 : [Example]
869 :
870 : In a derived class of SfxViewShell the SID_PRINTDOCDIRECT will be
871 : intercepted. Under certain circumstances a query should appear before
872 : you print, and the request will be aborted if necessary.
873 :
874 : Also in the IDL of this subclass of the above slot is entered. The status
875 : method will contain in outline:
876 :
877 : void SubViewShell::PrintState( SfxItemSet &rState )
878 : {
879 : if ( rState.GetItemState( SID_PRINTDOCDIRECT ) != SFX_ITEM_UNKNOWN )
880 : GetSlotState( SID_PRINTDOCDIRECT, SfxViewShell::GetInterface(),
881 : &rState );
882 : ...
883 : }
884 :
885 : [Cross-reference]
886 :
887 : <SfxShell::ExecuteSlot(SfxRequest&)>
888 : */
889 :
890 : {
891 : // Get Slot on the given Interface
892 60968 : if ( !pIF )
893 58582 : pIF = GetInterface();
894 : SfxItemState eState;
895 60968 : SfxItemPool &rPool = GetPool();
896 :
897 60968 : const SfxSlot* pSlot = NULL;
898 60968 : if ( nSlotId >= SID_VERB_START && nSlotId <= SID_VERB_END )
899 0 : pSlot = GetVerbSlot_Impl(nSlotId);
900 60968 : if ( !pSlot )
901 60968 : pSlot = pIF->GetSlot(nSlotId);
902 60968 : if ( pSlot )
903 : // Map on Which-Id if possible
904 60968 : nSlotId = pSlot->GetWhich( rPool );
905 :
906 : // Get Item and Item status
907 60968 : const SfxPoolItem *pItem = NULL;
908 60968 : SfxItemSet aSet( rPool, nSlotId, nSlotId ); // else pItem dies too soon
909 60968 : if ( pSlot )
910 : {
911 : // Call Status method
912 60968 : SfxStateFunc pFunc = pSlot->GetStateFnc();
913 60968 : if ( pFunc )
914 60968 : CallState( pFunc, aSet );
915 60968 : eState = aSet.GetItemState( nSlotId, true, &pItem );
916 :
917 : // get default Item if possible
918 60968 : if ( eState == SFX_ITEM_DEFAULT )
919 : {
920 18401 : if ( SfxItemPool::IsWhich(nSlotId) )
921 673 : pItem = &rPool.GetDefaultItem(nSlotId);
922 : else
923 17728 : eState = SFX_ITEM_DONTCARE;
924 : }
925 : }
926 : else
927 0 : eState = SFX_ITEM_UNKNOWN;
928 :
929 : // Evaluate Item and item status and possibly maintain them in pStateSet
930 60968 : SfxPoolItem *pRetItem = 0;
931 60968 : if ( eState <= SFX_ITEM_DISABLED )
932 : {
933 5388 : if ( pStateSet )
934 552 : pStateSet->DisableItem(nSlotId);
935 5388 : return 0;
936 : }
937 55580 : else if ( eState == SFX_ITEM_DONTCARE )
938 : {
939 17728 : if ( pStateSet )
940 1136 : pStateSet->ClearItem(nSlotId);
941 17728 : pRetItem = new SfxVoidItem(0);
942 : }
943 : else
944 : {
945 37852 : if ( pStateSet && pStateSet->Put( *pItem ) )
946 1675 : return &pStateSet->Get( pItem->Which() );
947 36177 : pRetItem = pItem->Clone();
948 : }
949 53905 : DeleteItemOnIdle(pRetItem);
950 :
951 53905 : return pRetItem;
952 : }
953 :
954 :
955 :
956 0 : SFX_EXEC_STUB(SfxShell, VerbExec)
957 0 : SFX_STATE_STUB(SfxShell, VerbState)
958 :
959 377 : void SfxShell::SetVerbs(const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs)
960 : {
961 377 : SfxViewShell *pViewSh = PTR_CAST ( SfxViewShell, this);
962 :
963 : DBG_ASSERT(pViewSh, "Only call SetVerbs at the ViewShell!");
964 377 : if ( !pViewSh )
965 377 : return;
966 :
967 : // First make all Statecaches dirty, so that no-one no longer tries to use
968 : // the Slots
969 : {
970 : SfxBindings *pBindings =
971 377 : pViewSh->GetViewFrame()->GetDispatcher()->GetBindings();
972 377 : sal_uInt16 nCount = pImp->aSlotArr.size();
973 377 : for (sal_uInt16 n1=0; n1<nCount ; n1++)
974 : {
975 0 : sal_uInt16 nId = SID_VERB_START + n1;
976 0 : pBindings->Invalidate(nId, false, true);
977 : }
978 : }
979 :
980 377 : sal_uInt16 nr=0;
981 377 : for (sal_Int32 n=0; n<aVerbs.getLength(); n++)
982 : {
983 0 : sal_uInt16 nSlotId = SID_VERB_START + nr++;
984 : DBG_ASSERT(nSlotId <= SID_VERB_END, "To many Verbs!");
985 0 : if (nSlotId > SID_VERB_END)
986 0 : break;
987 :
988 0 : SfxSlot *pNewSlot = new SfxSlot;
989 0 : pNewSlot->nSlotId = nSlotId;
990 0 : pNewSlot->nGroupId = 0;
991 :
992 : // Verb slots must be executed asynchronously, so that they can be
993 : // destroyed while executing.
994 0 : pNewSlot->nFlags = SFX_SLOT_ASYNCHRON | SFX_SLOT_CONTAINER;
995 0 : pNewSlot->nMasterSlotId = 0;
996 0 : pNewSlot->nValue = 0;
997 0 : pNewSlot->fnExec = SFX_STUB_PTR(SfxShell,VerbExec);
998 0 : pNewSlot->fnState = SFX_STUB_PTR(SfxShell,VerbState);
999 0 : pNewSlot->pType = 0; // HACK(SFX_TYPE(SfxVoidItem)) ???
1000 0 : pNewSlot->pName = OUStringToOString( aVerbs[n].VerbName, RTL_TEXTENCODING_UTF8 ).getStr();
1001 0 : pNewSlot->pLinkedSlot = 0;
1002 0 : pNewSlot->nArgDefCount = 0;
1003 0 : pNewSlot->pFirstArgDef = 0;
1004 0 : pNewSlot->pUnoName = 0;
1005 :
1006 0 : if (!pImp->aSlotArr.empty())
1007 : {
1008 0 : SfxSlot *pSlot = pImp->aSlotArr[0];
1009 0 : pNewSlot->pNextSlot = pSlot->pNextSlot;
1010 0 : pSlot->pNextSlot = pNewSlot;
1011 : }
1012 : else
1013 0 : pNewSlot->pNextSlot = pNewSlot;
1014 :
1015 0 : pImp->aSlotArr.insert(pImp->aSlotArr.begin() + (sal_uInt16) n, pNewSlot);
1016 : }
1017 :
1018 377 : pImp->aVerbList = aVerbs;
1019 :
1020 377 : if (pViewSh)
1021 : {
1022 : // The status of SID_OBJECT is collected in the controller directly on
1023 : // the Shell, it is thus enough to encourage a new status update
1024 : SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()->
1025 377 : GetBindings();
1026 377 : pBindings->Invalidate( SID_OBJECT, true, true );
1027 : }
1028 : }
1029 :
1030 :
1031 :
1032 7 : const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& SfxShell::GetVerbs() const
1033 : {
1034 7 : return pImp->aVerbList;
1035 : }
1036 :
1037 :
1038 :
1039 0 : void SfxShell::VerbExec(SfxRequest& rReq)
1040 : {
1041 0 : sal_uInt16 nId = rReq.GetSlot();
1042 0 : SfxViewShell *pViewShell = GetViewShell();
1043 0 : if ( pViewShell )
1044 : {
1045 0 : bool bReadOnly = pViewShell->GetObjectShell()->IsReadOnly();
1046 0 : com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aList = pViewShell->GetVerbs();
1047 0 : for (sal_Int32 n=0, nVerb=0; n<aList.getLength(); n++)
1048 : {
1049 : // check for ReadOnly verbs
1050 0 : if ( bReadOnly && !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_NEVERDIRTIES) )
1051 0 : continue;
1052 :
1053 : // check for verbs that shouldn't appear in the menu
1054 0 : if ( !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU) )
1055 0 : continue;
1056 :
1057 0 : if (nId == SID_VERB_START + nVerb++)
1058 : {
1059 0 : pViewShell->DoVerb(aList[n].VerbID);
1060 0 : rReq.Done();
1061 0 : return;
1062 : }
1063 0 : }
1064 : }
1065 : }
1066 :
1067 :
1068 :
1069 0 : void SfxShell::VerbState(SfxItemSet& )
1070 : {
1071 0 : }
1072 :
1073 :
1074 :
1075 0 : const SfxSlot* SfxShell::GetVerbSlot_Impl(sal_uInt16 nId) const
1076 : {
1077 0 : com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > rList = pImp->aVerbList;
1078 :
1079 : DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Wrong VerbId!");
1080 0 : sal_uInt16 nIndex = nId - SID_VERB_START;
1081 : DBG_ASSERT(nIndex < rList.getLength(),"Wrong VerbId!");
1082 :
1083 0 : if (nIndex < rList.getLength())
1084 0 : return pImp->aSlotArr[nIndex];
1085 : else
1086 0 : return 0;
1087 : }
1088 :
1089 :
1090 :
1091 7213 : void SfxShell::SetHelpId(sal_uIntPtr nId)
1092 : {
1093 7213 : pImp->nHelpId = nId;
1094 7213 : }
1095 :
1096 :
1097 :
1098 45 : sal_uIntPtr SfxShell::GetHelpId() const
1099 : {
1100 45 : return pImp->nHelpId;
1101 : }
1102 :
1103 :
1104 :
1105 665 : SfxObjectShell* SfxShell::GetObjectShell()
1106 : {
1107 665 : if ( GetViewShell() )
1108 665 : return GetViewShell()->GetViewFrame()->GetObjectShell();
1109 : else
1110 0 : return NULL;
1111 : }
1112 :
1113 :
1114 :
1115 0 : bool SfxShell::HasUIFeature( sal_uInt32 )
1116 : {
1117 0 : return false;
1118 : }
1119 :
1120 493 : long DispatcherUpdate_Impl( void*, void* pArg )
1121 : {
1122 493 : ((SfxDispatcher*) pArg)->Update_Impl( true );
1123 493 : ((SfxDispatcher*) pArg)->GetBindings()->InvalidateAll(false);
1124 493 : return 0;
1125 : }
1126 :
1127 2224 : void SfxShell::UIFeatureChanged()
1128 : {
1129 2224 : SfxViewFrame *pFrame = GetFrame();
1130 2224 : if ( pFrame && pFrame->IsVisible() )
1131 : {
1132 : // Also force an update, if dispatcher is already updated otherwise
1133 : // something my get stuck in the bunkered tools. Asynchronous call to
1134 : // prevent recursion.
1135 1821 : if ( !pImp->pUpdater )
1136 1691 : pImp->pUpdater = new svtools::AsynchronLink( Link( this, DispatcherUpdate_Impl ) );
1137 :
1138 : // Multiple views allowed
1139 1821 : pImp->pUpdater->Call( pFrame->GetDispatcher(), true );
1140 : }
1141 2224 : }
1142 :
1143 41476 : void SfxShell::SetDisableFlags( sal_uIntPtr nFlags )
1144 : {
1145 41476 : pImp->nDisableFlags = nFlags;
1146 41476 : }
1147 :
1148 38834 : sal_uIntPtr SfxShell::GetDisableFlags() const
1149 : {
1150 38834 : return pImp->nDisableFlags;
1151 : }
1152 :
1153 0 : SfxItemSet* SfxShell::CreateItemSet( sal_uInt16 )
1154 : {
1155 0 : return NULL;
1156 : }
1157 :
1158 0 : void SfxShell::ApplyItemSet( sal_uInt16, const SfxItemSet& )
1159 : {
1160 0 : }
1161 :
1162 2436 : void SfxShell::SetContextName (const ::rtl::OUString& rsContextName)
1163 : {
1164 2436 : pImp->maContextChangeBroadcaster.Initialize(rsContextName);
1165 2436 : }
1166 :
1167 4095 : void SfxShell::SetViewShell_Impl( SfxViewShell* pView )
1168 : {
1169 4095 : pImp->pViewSh = pView;
1170 4095 : }
1171 :
1172 26679 : void SfxShell::BroadcastContextForActivation (const bool bIsActivated)
1173 : {
1174 26679 : SfxViewFrame* pViewFrame = GetFrame();
1175 26679 : if (pViewFrame != NULL)
1176 : {
1177 18499 : if (bIsActivated)
1178 12043 : pImp->maContextChangeBroadcaster.Activate(pViewFrame->GetFrame().GetFrameInterface());
1179 : else
1180 6456 : pImp->maContextChangeBroadcaster.Deactivate(pViewFrame->GetFrame().GetFrameInterface());
1181 : }
1182 26679 : }
1183 :
1184 666 : bool SfxShell::SetContextBroadcasterEnabled (const bool bIsEnabled)
1185 : {
1186 666 : return pImp->maContextChangeBroadcaster.SetBroadcasterEnabled(bIsEnabled);
1187 : }
1188 :
1189 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|