Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / control / shell.cxx
blobbbbe3f541533a8bac3886410a9fc7dfc0ffac917
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/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>
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>
47 //====================================================================
49 DBG_NAME(SfxShell)
51 //====================================================================
53 TYPEINIT0(SfxShell);
55 //====================================================================
56 class SfxVerbSlotArr_Impl : public std::vector<SfxSlot*>
58 public:
59 ~SfxVerbSlotArr_Impl()
61 for(const_iterator it = begin(); it != end(); ++it)
62 delete *it;
66 using namespace com::sun::star;
68 //=========================================================================
69 // SfxShell_Impl
70 //=========================================================================
71 struct SfxShell_Impl: public SfxBroadcaster
73 String aObjectName; // Name of Sbx-Objects
74 SfxItemPtrMap aItems; // Data exchange on Item level
75 SfxViewShell* pViewSh; // SfxViewShell if Shell is
76 // ViewFrame/ViewShell/SubShell list
77 SfxViewFrame* pFrame; // Frame, if <UI-active>
78 SfxRepeatTarget* pRepeatTarget; // SbxObjectRef xParent;
79 sal_Bool bInAppBASIC;
80 sal_Bool bActive;
81 sal_uIntPtr nDisableFlags;
82 sal_uIntPtr nHelpId;
83 svtools::AsynchronLink* pExecuter;
84 svtools::AsynchronLink* pUpdater;
85 SfxVerbSlotArr_Impl aSlotArr;
87 com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aVerbList;
88 ::sfx2::sidebar::ContextChangeBroadcaster maContextChangeBroadcaster;
90 SfxShell_Impl() : pExecuter( 0 ), pUpdater( 0 ) {}
91 ~SfxShell_Impl() { delete pExecuter; delete pUpdater;}
94 //=========================================================================
95 // SfxShell
96 //=========================================================================
98 void SfxShell::EmptyExecStub(SfxShell *, SfxRequest &)
102 void SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &)
106 SfxShell::SfxShell()
108 /* [Description]
110 The constructor of the SfxShell class initializes only simple types,
111 the corresponding SbxObject is only created on-demand. Therefore,
112 the application of a SfxShell instance is very cheap.
115 : pImp(0),
116 pPool(0),
117 pUndoMgr(0)
119 DBG_CTOR(SfxShell, 0);
120 pImp = new SfxShell_Impl;
121 pImp->pViewSh = 0;
122 pImp->pFrame = 0;
123 pImp->pRepeatTarget = 0;
124 pImp->bInAppBASIC = sal_False;
125 pImp->nHelpId = 0L;
126 pImp->bActive = sal_False;
127 pImp->nDisableFlags = 0;
130 //-------------------------------------------------------------------------
132 SfxShell::SfxShell( SfxViewShell *pViewSh )
134 /* [Description]
136 The constructor of the SfxShell class initializes only simple types,
137 the corresponding SbxObject is only created on-demand. Therefore,
138 the application of a SfxShell instance is very cheap.
141 : pImp(0),
142 pPool(0),
143 pUndoMgr(0)
145 DBG_CTOR(SfxShell, 0);
146 pImp = new SfxShell_Impl;
147 pImp->pViewSh = pViewSh;
148 pImp->pFrame = 0;
149 pImp->pRepeatTarget = 0;
150 pImp->bInAppBASIC = sal_False;
151 pImp->nHelpId = 0L;
152 pImp->bActive = sal_False;
155 //--------------------------------------------------------------------
157 SfxShell::~SfxShell()
159 /* [Description]
161 The connection to a possible corresponding SbxObject is dissolved.
162 The SbxObject may continoue to exist, but can not any longer perform
163 any functions and can not provide any properties.
167 DBG_DTOR(SfxShell, 0);
170 delete pImp;
173 //--------------------------------------------------------------------
175 void SfxShell::SetName( const String &rName )
177 /* [Description]
179 Sets the name of the Shell object. With this name, the SfxShell instance
180 of BASIC can be expressed.
184 pImp->aObjectName = rName;
187 //--------------------------------------------------------------------
189 const String& SfxShell::GetName() const
191 /* [Description]
193 Returns the name of the Shell object. With this name, the SfxShell instance
194 of BASIC can be expressed.
198 return pImp->aObjectName;
201 //--------------------------------------------------------------------
203 SfxDispatcher* SfxShell::GetDispatcher() const
205 /* [Description]
207 This method returns a pointer to the <SfxDispatcher>, when the SfxShell
208 is currently <UI-active> or a NULL-pointer if it is not UI-active.
210 The returned pointer is only valid in the immediate context of the method
211 call.
215 return pImp->pFrame ? pImp->pFrame->GetDispatcher() : 0;
218 //--------------------------------------------------------------------
220 SfxViewShell* SfxShell::GetViewShell() const
222 /* [Description]
224 Returns the SfxViewShell in which they are located in the subshells.
225 Otherwise, and if not specified by the App developer, this method
226 returns NULL.
230 return pImp->pViewSh;
233 //--------------------------------------------------------------------
235 SfxViewFrame* SfxShell::GetFrame() const
237 /* [Description]
239 This method returns a pointer to the <SfxViewFrame> to which this SfxShell
240 instance is associated or in which they currently is <UI-active>.
241 A NULL pointer is returned if this SfxShell instance is not UI-active at
242 the moment and also no SfxViewFrame is permanently assigned.
244 The returned pointer is only valid in the immediate context of the method
245 call.
247 [Note]
249 Only instances of a subclass of SfxApplication and SfxObjectShell
250 should here provide a NULL-pointer. Otherwise, there is an error in the
251 application program (wrong constructor was called from SfxShell).
253 [Cross-reference]
255 <SfxViewShell::GetViewFrame()const>
259 if ( pImp->pFrame )
260 return pImp->pFrame;
261 if ( pImp->pViewSh )
262 return pImp->pViewSh->GetViewFrame();
263 return 0;
266 //--------------------------------------------------------------------
268 const SfxPoolItem* SfxShell::GetItem
270 sal_uInt16 nSlotId // Slot-Id of the querying <SfxPoolItem>s
271 ) const
273 /* [Description]
275 With this method any objects of <SfxPoolItemu> subclasses can be accessed.
276 This exchange method is needed if, for example special <SfxToolBoxControl>
277 subclasses need access to certain data such as the <SfxObjectShell>.
279 The returned instance belongs to the particular SfxShell and may be
280 used only in the immediate context of the method call.
282 [Cross-reference]
284 <SfxShell::PutItem(const SfxPoolItem&)>
285 <SfxShell::RemoveItem(sal_uInt16)>
289 SfxItemPtrMap::iterator it = pImp->aItems.find( nSlotId );
290 if( it != pImp->aItems.end() )
291 return it->second;
292 return 0;
295 //--------------------------------------------------------------------
297 void SfxShell::PutItem
299 const SfxPoolItem& rItem /* Instance, of which a copy is created,
300 which is stored in the SfxShell in a list. */
303 /* [Description]
305 With this method, any objects of subclasses of <SfxPoolItem> can be made
306 available. This exchange technology is needed if, for example, special
307 <SfxToolBoxControl> Subclasses need access to certain data such as the
308 <SfxObjectShell>
310 If a SfxPoolItem exists with the same slot ID, it is deleted automatically.
312 [Cross-reference]
314 <SfxShell::RemoveItem(sal_uInt16)>
315 <SfxShell::GetItem(sal_uInt16)>
319 DBG_ASSERT( !rItem.ISA(SfxSetItem), "SetItems aren't allowed here" );
320 DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
321 "items with Which-Ids aren't allowed here" );
323 // MSC made a mess here of WNT/W95, beware of changes
324 SfxPoolItem *pItem = rItem.Clone();
325 SfxPoolItemHint aItemHint( pItem );
326 const sal_uInt16 nWhich = rItem.Which();
328 SfxItemPtrMap::iterator it = pImp->aItems.find( nWhich );
329 if( it != pImp->aItems.end() )
331 SfxPoolItem *pLoopItem = it->second;
332 // Replace Item
333 delete pLoopItem;
334 it->second = pItem;
336 // if active, notify Bindings
337 SfxDispatcher *pDispat = GetDispatcher();
338 if ( pDispat )
340 SfxBindings* pBindings = pDispat->GetBindings();
341 pBindings->Broadcast( aItemHint );
342 sal_uInt16 nSlotId = nWhich; //pItem->GetSlotId();
343 SfxStateCache* pCache = pBindings->GetStateCache( nSlotId );
344 if ( pCache )
346 pCache->SetState( SFX_ITEM_AVAILABLE, pItem->Clone(), sal_True );
347 pCache->SetCachedState( sal_True );
350 return;
352 else
354 Broadcast( aItemHint );
355 pImp->aItems[ pItem->Which() ] = pItem;
359 //--------------------------------------------------------------------
361 SfxInterface* SfxShell::GetInterface() const
363 /* [Description]
365 With this virtual method, which is automatically overloaded by each subclass
366 with its own slots through the macro <SFX_DECL_INTERFACE>, one can access
367 each of the <SfxInterface> instance beloning to the subclass.
369 The class SfxShell itself has no own SfxInterface (no slots), therefore a
370 NULL-pointer is returned.
374 return GetStaticInterface();
377 //--------------------------------------------------------------------
379 ::svl::IUndoManager* SfxShell::GetUndoManager()
381 /* [Description]
383 Each Subclass of SfxShell can hava a <SfxUndoManager>. This can be set in
384 the derived class with <SfxShell:SetUndoManager()>.
386 The class SfxShell itself does not have a SfxUndoManager, a NULL-pointer
387 is therefore returned.
391 return pUndoMgr;
394 //--------------------------------------------------------------------
396 void SfxShell::SetUndoManager( ::svl::IUndoManager *pNewUndoMgr )
398 /* [Description]
400 Sets a <SfxUndoManager> for this <SfxShell> Instance. For the undo
401 is only the undo-manager used for SfxShell at the top of the stack of each
402 <SfxDispatcher>.
404 On the given <SfxUndoManager> is automatically the current
405 Max-Undo-Action-Count setting set form the options.
407 'pNewUndoMgr' must exist until the Destuctor of SfxShell instance is called
408 or until the next 'SetUndoManager()'.
412 OSL_ENSURE( ( pUndoMgr == NULL ) || ( pNewUndoMgr == NULL ) || ( pUndoMgr == pNewUndoMgr ),
413 "SfxShell::SetUndoManager: exchanging one non-NULL manager with another non-NULL manager? Suspicious!" );
414 // there's at least one client of our UndoManager - the DocumentUndoManager at the SfxBaseModel - which
415 // caches the UndoManager, and registers itself as listener. If exchanging non-NULL UndoManagers is really
416 // a supported scenario (/me thinks it is not), then we would need to notify all such clients instances.
418 pUndoMgr = pNewUndoMgr;
419 if ( pUndoMgr )
420 pUndoMgr->SetMaxUndoActionCount(
421 officecfg::Office::Common::Undo::Steps::get());
424 //--------------------------------------------------------------------
426 SfxRepeatTarget* SfxShell::GetRepeatTarget() const
428 /* [Description]
430 Returns a pointer to the <SfxRepeatTarget> instance that is used in
431 SID_REPEAT as repeat target when it is addressed from the <SfxUndoManager>
432 supplied by this SfxShell. The return value can be NULL.
434 [Note]
436 A derivation of <SfxShell> or one of its subclasses of <SfxRepeatTarget>
437 is not recommended, as compiler errors are provoked.
438 (due to Call-to-Pointer-to-Member-Function to the subclass).
442 return pImp->pRepeatTarget;
445 //--------------------------------------------------------------------
447 void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget )
449 /* [Description]
451 Sets the <SfxRepeatTarget> instance that is used in SID_REPEAT as
452 RepeatTarget, when the current supplied by this <SfxUndoManager> is
453 addressed. By 'pTarget==0' the SID_REPEAT is disabled for this SfxShell.
454 The instance '*pTarget' must live as long as it is registered.
456 [Note]
458 A derivation of <SfxShell> or one of its subclasses of <SfxRepeatTarget>
459 is not recommended, as compiler errors are provoked.
460 (due to Call-to-Pointer-to-Member-Function to the subclass).
464 pImp->pRepeatTarget = pTarget;
467 //--------------------------------------------------------------------
469 void SfxShell::Invalidate
471 sal_uInt16 nId /* Invalidated Slot-Id or Which-Id.
472 If these are 0 (default), then all
473 by this Shell currently handled Slot-Ids are
474 invalidated. */
477 /* [Description]
479 With this method can the slots of the subclasses be invalidated through the
480 slot Id or alternatively through the Which ID. Slot IDs, which are
481 inherited by the subclass are also invalidert.
483 [Cross-reference]
485 <SfxBindings::Invalidate(sal_uInt16)>
486 <SfxBindings::InvalidateAll(sal_Bool)>
490 if ( !GetViewShell() )
492 OSL_FAIL( "wrong Invalidate method called!" );
493 return;
496 Invalidate_Impl( GetViewShell()->GetViewFrame()->GetBindings(), nId );
499 void SfxShell::Invalidate_Impl( SfxBindings& rBindings, sal_uInt16 nId )
501 if ( nId == 0 )
503 rBindings.InvalidateShell( *this, sal_False );
505 else
507 const SfxInterface *pIF = GetInterface();
510 const SfxSlot *pSlot = pIF->GetSlot(nId);
511 if ( pSlot )
513 // At Enum-Slots invalidate the Master-Slot
514 if ( SFX_KIND_ENUM == pSlot->GetKind() )
515 pSlot = pSlot->GetLinkedSlot();
517 // Invalidate the Slot itself and possible also all Slave-Slots
518 rBindings.Invalidate( pSlot->GetSlotId() );
519 for ( const SfxSlot *pSlave = pSlot->GetLinkedSlot();
520 pSlave && pIF->ContainsSlot_Impl( pSlave ) &&
521 pSlave->GetLinkedSlot() == pSlot;
522 ++pSlave )
523 rBindings.Invalidate( pSlave->GetSlotId() );
525 return;
528 pIF = pIF->GetGenoType();
531 while ( pIF );
533 DBG_WARNING( "W3: invalidating slot-id unknown in shell" );
537 //--------------------------------------------------------------------
539 void SfxShell::DoActivate_Impl( SfxViewFrame *pFrame, sal_Bool bMDI )
541 /* [Description]
543 This method controls the activation of SfxShell instance. First, by calling
544 the virtual method <SfxShell::Activate(sal_Bool)> which gives the subclass the
545 opportunity to respond to the event.
547 When bMDI == TRUE, the associated SbxObject is being 'armed', so that
548 unqualified methods of the object (without the name of the object)
549 from BASIC are found.
553 #ifdef DBG_UTIL
554 const SfxInterface *p_IF = GetInterface();
555 if ( !p_IF )
556 return;
557 #endif
558 SAL_INFO(
559 "sfx2.control",
560 "SfxShell::DoActivate() " << this << " " << GetInterface()->GetName()
561 << " bMDI " << (bMDI ? "MDI" : ""));
563 if ( bMDI )
565 // Remember Frame, in which it was activated
566 pImp->pFrame = pFrame;
567 pImp->bActive = sal_True;
570 // Notify Subclass
571 Activate(bMDI);
574 //--------------------------------------------------------------------
576 void SfxShell::DoDeactivate_Impl( SfxViewFrame *pFrame, sal_Bool bMDI )
578 /* [Description]
580 This method controls the deactivation of the SfxShell instance. When
581 bMDI == TRUE the SbxObject is first set to a status that only qualified
582 BASIC methods can be called.
584 Then the subclass gets the opportunity in every case to respond to the
585 event by calling the virtual method <SfxShell::Deactivate(sal_Bool)>.
589 #ifdef DBG_UTIL
590 const SfxInterface *p_IF = GetInterface();
591 if ( !p_IF )
592 return;
593 #endif
594 SAL_INFO(
595 "sfx2.control",
596 "SfxShell::DoDeactivate()" << this << " " << GetInterface()->GetName()
597 << " bMDI " << (bMDI ? "MDI" : ""));
599 // Only when it comes from a Frame
600 // (not when for instance by poping BASIC-IDE from AppDisp)
601 if ( bMDI && pImp->pFrame == pFrame )
603 // deliver
604 pImp->pFrame = 0;
605 pImp->bActive = sal_False;
608 // Notify Subclass
609 Deactivate(bMDI);
612 //--------------------------------------------------------------------
614 sal_Bool SfxShell::IsActive() const
616 return pImp->bActive;
619 //--------------------------------------------------------------------
621 void SfxShell::Activate
623 sal_Bool /*bMDI*/ /* TRUE
624 the <SfxDispatcher>, on which the SfxShell is
625 located, is activated or the SfxShell instance
626 was pushed on an active SfxDispatcher.
627 (compare with SystemWindow::IsMDIActivate())
629 FALSE
630 the <SfxViewFrame>, on which SfxDispatcher
631 the SfxShell instance is located, was
632 activated. (for example by a closing dialoge) */
635 /* [Description]
637 Virtual method that is called when enabling the SfxShell instance,
638 in order to give the Subclasses the opportunity to respond to the
639 to the enabling.
641 [Cross-reference]
643 StarView SystemWindow::Activate(sal_Bool)
647 BroadcastContextForActivation(true);
650 //--------------------------------------------------------------------
652 void SfxShell::Deactivate
654 sal_Bool /*bMDI*/ /* TRUE
655 the <SfxDispatcher>, on which the SfxShell is
656 located, is inactivated or the SfxShell instance
657 was popped on an active SfxDispatcher.
658 (compare with SystemWindow::IsMDIActivate())
660 FALSE
661 the <SfxViewFrame>, on which SfxDispatcher
662 the SfxShell instance is located, was
663 deactivated. (for example by a dialoge) */
667 /* [Description]
669 Virtual method that is called when disabling the SfxShell instance,
670 to give the Subclasses the opportunity to respond to the disabling.
672 [Cross-reference]
674 StarView SystemWindow::Dectivate(sal_Bool)
678 BroadcastContextForActivation(false);
682 void SfxShell::ParentActivate
686 /* [Description]
688 A parent of the <SfxDispatcher> on which the SfxShell is located, has
689 become active, or the SfxShell instance was pushed on a <SfxDispatcher>,
690 which parent is active.
692 The base implementation is empty and does not need to be called.
694 [Cross-reference]
696 SfxShell::Activate()
701 //--------------------------------------------------------------------
703 void SfxShell::ParentDeactivate
707 /* [Description]
709 The active parent of the <SfxDispatcher> on which the SfxShell is located,
710 has been disabled.
712 The base implementation is empty and does not need to be called.
714 [Cross-reference]
716 SfxShell::Deactivate()
721 //--------------------------------------------------------------------
723 ResMgr* SfxShell::GetResMgr() const
725 /* [Description]
727 This method provides the ResMgr of the <Resource-DLL> that are used by
728 the SfxShell instance. If this is a NULL-pointer, then the current
729 resource manager is to be used.
733 return GetInterface()->GetResMgr();
736 //--------------------------------------------------------------------
738 bool SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot )
740 /* [Description]
742 This method determines by calling the status function whether 'rSlot'
743 can be executed currently.
746 // Get Slot status
747 SfxItemPool &rPool = GetPool();
748 const sal_uInt16 nId = rSlot.GetWhich( rPool );
749 SfxItemSet aSet(rPool, nId, nId);
750 SfxStateFunc pFunc = rSlot.GetStateFnc();
751 CallState( pFunc, aSet );
752 return aSet.GetItemState(nId) != SFX_ITEM_DISABLED;
755 //--------------------------------------------------------------------
757 long ShellCall_Impl( void* pObj, void* pArg )
759 ((SfxShell* )pObj)->ExecuteSlot( *(SfxRequest*)pArg, (SfxInterface*)0L );
760 return 0;
763 /* [Description]
765 Asynchronous ExecuteSlot for the RELOAD
768 //--------------------------------------------------------------------
769 const SfxPoolItem* SfxShell::ExecuteSlot( SfxRequest& rReq, sal_Bool bAsync )
771 if( !bAsync )
772 return ExecuteSlot( rReq, (SfxInterface*)0L );
773 else
775 if( !pImp->pExecuter )
776 pImp->pExecuter = new svtools::AsynchronLink(
777 Link( this, ShellCall_Impl ) );
778 pImp->pExecuter->Call( new SfxRequest( rReq ) );
779 return 0;
783 const SfxPoolItem* SfxShell::ExecuteSlot
785 SfxRequest &rReq, // the relayed <SfxRequest>
786 const SfxInterface* pIF // default = 0 means get virtually
789 /* [Description]
791 This method allows you to forward a <SfxRequest> to the specified
792 base <SfxShell>.
794 [Example]
796 In a derived class of SfxViewShell the SID_PRINTDOCDIRECT will be
797 intercepted. Under certain circumstances a query should appear before
798 you print, and the request will be aborted if necessary.
800 Also in the IDL of this subclass of the above slot is entered. The status
801 method will contain in outline:
803 void SubViewShell::Exec( SfxRequest &rReq )
805 if ( rReq.GetSlot() == SID_PRINTDOCDIRECT )
807 'dialog'
808 if ( 'condition' )
809 ExecuteSlot( rReq, SfxViewShell::GetInterface() );
813 It usually takes no rReq.Done() to be called as that is already completed
814 in implementation of the SfxViewShell, for instance it has been canceled.
816 [Cross-reference]
818 <SfxShell::GetSlotState(sal_uInt16,const SfxInterface*,SfxItemSet*)>
822 if ( !pIF )
823 pIF = GetInterface();
825 sal_uInt16 nSlot = rReq.GetSlot();
826 const SfxSlot* pSlot = NULL;
827 if ( nSlot >= SID_VERB_START && nSlot <= SID_VERB_END )
828 pSlot = GetVerbSlot_Impl(nSlot);
829 if ( !pSlot )
830 pSlot = pIF->GetSlot(nSlot);
831 DBG_ASSERT( pSlot, "slot not supported" );
833 SfxExecFunc pFunc = pSlot->GetExecFnc();
834 if ( pFunc )
835 CallExec( pFunc, rReq );
837 return rReq.GetReturnValue();
840 //--------------------------------------------------------------------
842 const SfxPoolItem* SfxShell::GetSlotState
844 sal_uInt16 nSlotId, // Slot-Id to the Slots in question
845 const SfxInterface* pIF, // default = 0 means get virtually
846 SfxItemSet* pStateSet // SfxItemSet of the Slot-State method
849 /* [Description]
851 This method returns the status of the slot with the specified slot ID
852 on the specified interface.
854 If the slot is disabled or in this SfxShell (and their parent shells) are
855 not known, a Null-pointer is returned.
857 If the slot does not have a Status, a SfxVoidItem is returned.
859 The status is set directly in this Set when pStateSet != 0 , so that
860 overloaded Slots of the <SfxShell> Subclasses and also in the Status
861 method of the base implementation can be called.
863 [Example]
865 In a derived class of SfxViewShell the SID_PRINTDOCDIRECT will be
866 intercepted. Under certain circumstances a query should appear before
867 you print, and the request will be aborted if necessary.
869 Also in the IDL of this subclass of the above slot is entered. The status
870 method will contain in outline:
872 void SubViewShell::PrintState( SfxItemSet &rState )
874 if ( rState.GetItemState( SID_PRINTDOCDIRECT ) != SFX_ITEM_UNKNOWN )
875 GetSlotState( SID_PRINTDOCDIRECT, SfxViewShell::GetInterface(),
876 &rState );
880 [Cross-reference]
882 <SfxShell::ExecuteSlot(SfxRequest&)>
886 // Get Slot on the given Interface
887 if ( !pIF )
888 pIF = GetInterface();
889 SfxItemState eState;
890 SfxItemPool &rPool = GetPool();
892 const SfxSlot* pSlot = NULL;
893 if ( nSlotId >= SID_VERB_START && nSlotId <= SID_VERB_END )
894 pSlot = GetVerbSlot_Impl(nSlotId);
895 if ( !pSlot )
896 pSlot = pIF->GetSlot(nSlotId);
897 if ( pSlot )
898 // Map on Which-Id if possible
899 nSlotId = pSlot->GetWhich( rPool );
901 // Get Item and Item status
902 const SfxPoolItem *pItem = NULL;
903 SfxItemSet aSet( rPool, nSlotId, nSlotId ); // else pItem dies too soon
904 if ( pSlot )
906 // Call Status method
907 SfxStateFunc pFunc = pSlot->GetStateFnc();
908 if ( pFunc )
909 CallState( pFunc, aSet );
910 eState = aSet.GetItemState( nSlotId, sal_True, &pItem );
912 // get default Item if possible
913 if ( eState == SFX_ITEM_DEFAULT )
915 if ( SfxItemPool::IsWhich(nSlotId) )
916 pItem = &rPool.GetDefaultItem(nSlotId);
917 else
918 eState = SFX_ITEM_DONTCARE;
921 else
922 eState = SFX_ITEM_UNKNOWN;
924 // Evaluate Item and item status and possibly maintain them in pStateSet
925 SfxPoolItem *pRetItem = 0;
926 if ( eState <= SFX_ITEM_DISABLED )
928 if ( pStateSet )
929 pStateSet->DisableItem(nSlotId);
930 return 0;
932 else if ( eState == SFX_ITEM_DONTCARE )
934 if ( pStateSet )
935 pStateSet->ClearItem(nSlotId);
936 pRetItem = new SfxVoidItem(0);
938 else
940 if ( pStateSet && pStateSet->Put( *pItem ) )
941 return &pStateSet->Get( pItem->Which() );
942 pRetItem = pItem->Clone();
944 DeleteItemOnIdle(pRetItem);
946 return pRetItem;
949 //--------------------------------------------------------------------
951 SFX_EXEC_STUB(SfxShell, VerbExec)
952 SFX_STATE_STUB(SfxShell, VerbState)
954 void SfxShell::SetVerbs(const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs)
956 SfxViewShell *pViewSh = PTR_CAST ( SfxViewShell, this);
958 DBG_ASSERT(pViewSh, "Only call SetVerbs at the ViewShell!");
959 if ( !pViewSh )
960 return;
962 // First make all Statecaches dirty, so that no-one no longer tries to use
963 // the Slots
965 SfxBindings *pBindings =
966 pViewSh->GetViewFrame()->GetDispatcher()->GetBindings();
967 sal_uInt16 nCount = pImp->aSlotArr.size();
968 for (sal_uInt16 n1=0; n1<nCount ; n1++)
970 sal_uInt16 nId = SID_VERB_START + n1;
971 pBindings->Invalidate(nId, sal_False, sal_True);
975 sal_uInt16 nr=0;
976 for (sal_Int32 n=0; n<aVerbs.getLength(); n++)
978 sal_uInt16 nSlotId = SID_VERB_START + nr++;
979 DBG_ASSERT(nSlotId <= SID_VERB_END, "To many Verbs!");
980 if (nSlotId > SID_VERB_END)
981 break;
983 SfxSlot *pNewSlot = new SfxSlot;
984 pNewSlot->nSlotId = nSlotId;
985 pNewSlot->nGroupId = 0;
987 // Verb slots must be executed asynchronously, so that they can be
988 // destroyed while executing.
989 pNewSlot->nFlags = SFX_SLOT_ASYNCHRON | SFX_SLOT_CONTAINER;
990 pNewSlot->nMasterSlotId = 0;
991 pNewSlot->nValue = 0;
992 pNewSlot->fnExec = SFX_STUB_PTR(SfxShell,VerbExec);
993 pNewSlot->fnState = SFX_STUB_PTR(SfxShell,VerbState);
994 pNewSlot->pType = 0; // HACK(SFX_TYPE(SfxVoidItem)) ???
995 pNewSlot->pName = U2S(aVerbs[n].VerbName).getStr();
996 pNewSlot->pLinkedSlot = 0;
997 pNewSlot->nArgDefCount = 0;
998 pNewSlot->pFirstArgDef = 0;
999 pNewSlot->pUnoName = 0;
1001 if (!pImp->aSlotArr.empty())
1003 SfxSlot *pSlot = pImp->aSlotArr[0];
1004 pNewSlot->pNextSlot = pSlot->pNextSlot;
1005 pSlot->pNextSlot = pNewSlot;
1007 else
1008 pNewSlot->pNextSlot = pNewSlot;
1010 pImp->aSlotArr.insert(pImp->aSlotArr.begin() + (sal_uInt16) n, pNewSlot);
1013 pImp->aVerbList = aVerbs;
1015 if (pViewSh)
1017 // The status of SID_OBJECT is collected in the controller directly on
1018 // the Shell, it is thus enough to encourage a new status update
1019 SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()->
1020 GetBindings();
1021 pBindings->Invalidate( SID_OBJECT, sal_True, sal_True );
1025 //--------------------------------------------------------------------
1027 const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& SfxShell::GetVerbs() const
1029 return pImp->aVerbList;
1032 //--------------------------------------------------------------------
1034 void SfxShell::VerbExec(SfxRequest& rReq)
1036 sal_uInt16 nId = rReq.GetSlot();
1037 SfxViewShell *pViewShell = GetViewShell();
1038 if ( pViewShell )
1040 sal_Bool bReadOnly = pViewShell->GetObjectShell()->IsReadOnly();
1041 com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aList = pViewShell->GetVerbs();
1042 for (sal_Int32 n=0, nVerb=0; n<aList.getLength(); n++)
1044 // check for ReadOnly verbs
1045 if ( bReadOnly && !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_NEVERDIRTIES) )
1046 continue;
1048 // check for verbs that shouldn't appear in the menu
1049 if ( !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU) )
1050 continue;
1052 if (nId == SID_VERB_START + nVerb++)
1054 pViewShell->DoVerb(aList[n].VerbID);
1055 rReq.Done();
1056 return;
1062 //--------------------------------------------------------------------
1064 void SfxShell::VerbState(SfxItemSet& )
1068 //--------------------------------------------------------------------
1070 const SfxSlot* SfxShell::GetVerbSlot_Impl(sal_uInt16 nId) const
1072 com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > rList = pImp->aVerbList;
1074 DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Wrong VerbId!");
1075 sal_uInt16 nIndex = nId - SID_VERB_START;
1076 DBG_ASSERT(nIndex < rList.getLength(),"Wrong VerbId!");
1078 if (nIndex < rList.getLength())
1079 return pImp->aSlotArr[nIndex];
1080 else
1081 return 0;
1084 //--------------------------------------------------------------------
1086 void SfxShell::SetHelpId(sal_uIntPtr nId)
1088 pImp->nHelpId = nId;
1091 //--------------------------------------------------------------------
1093 sal_uIntPtr SfxShell::GetHelpId() const
1095 return pImp->nHelpId;
1098 //--------------------------------------------------------------------
1100 SfxObjectShell* SfxShell::GetObjectShell()
1102 if ( GetViewShell() )
1103 return GetViewShell()->GetViewFrame()->GetObjectShell();
1104 else
1105 return NULL;
1108 //--------------------------------------------------------------------
1110 sal_Bool SfxShell::HasUIFeature( sal_uInt32 )
1112 return sal_False;
1115 long DispatcherUpdate_Impl( void*, void* pArg )
1117 ((SfxDispatcher*) pArg)->Update_Impl( sal_True );
1118 ((SfxDispatcher*) pArg)->GetBindings()->InvalidateAll(sal_False);
1119 return 0;
1122 void SfxShell::UIFeatureChanged()
1124 SfxViewFrame *pFrame = GetFrame();
1125 if ( pFrame && pFrame->IsVisible() )
1127 // Also force an update, if dispatcher is already updated otherwise
1128 // something my get stuck in the bunkered tools. Asynchronous call to
1129 // prevent recursion.
1130 if ( !pImp->pUpdater )
1131 pImp->pUpdater = new svtools::AsynchronLink( Link( this, DispatcherUpdate_Impl ) );
1133 // Multiple views allowed
1134 pImp->pUpdater->Call( pFrame->GetDispatcher(), sal_True );
1138 void SfxShell::SetDisableFlags( sal_uIntPtr nFlags )
1140 pImp->nDisableFlags = nFlags;
1143 sal_uIntPtr SfxShell::GetDisableFlags() const
1145 return pImp->nDisableFlags;
1148 SfxItemSet* SfxShell::CreateItemSet( sal_uInt16 )
1150 return NULL;
1153 void SfxShell::ApplyItemSet( sal_uInt16, const SfxItemSet& )
1157 void SfxShell::SetContextName (const ::rtl::OUString& rsContextName)
1159 pImp->maContextChangeBroadcaster.Initialize(rsContextName);
1162 void SfxShell::SetViewShell_Impl( SfxViewShell* pView )
1164 pImp->pViewSh = pView;
1167 void SfxShell::BroadcastContextForActivation (const bool bIsActivated)
1169 SfxViewFrame* pViewFrame = GetFrame();
1170 if (pViewFrame != NULL)
1172 if (bIsActivated)
1173 pImp->maContextChangeBroadcaster.Activate(pViewFrame->GetFrame().GetFrameInterface());
1174 else
1175 pImp->maContextChangeBroadcaster.Deactivate(pViewFrame->GetFrame().GetFrameInterface());
1179 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */