/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #include #include #include #include #include #include #include #ifndef GCC #endif #include #include #include #include #include #include #include #include #include #include "sfxtypes.hxx" #include #include #include "statcach.hxx" #include #include //==================================================================== DBG_NAME(SfxShell) //==================================================================== TYPEINIT0(SfxShell); //==================================================================== typedef SfxSlot* SfxSlotPtr; SV_DECL_PTRARR_DEL( SfxVerbSlotArr_Impl, SfxSlotPtr, 4, 4) SV_IMPL_PTRARR( SfxVerbSlotArr_Impl, SfxSlotPtr); using namespace com::sun::star; //========================================================================= // SfxShell_Impl //========================================================================= struct SfxShell_Impl: public SfxBroadcaster { String aObjectName;// Name des Sbx-Objects SfxItemArray_Impl aItems; // Datenaustausch auf Item-Basis SfxViewShell* pViewSh; // SfxViewShell falls Shell ViewFrame/ViewShell/SubShell ist SfxViewFrame* pFrame; // Frame, falls SfxRepeatTarget* pRepeatTarget; // SbxObjectRef xParent; sal_Bool bInAppBASIC; sal_Bool bActive; sal_uIntPtr nDisableFlags; sal_uIntPtr nHelpId; svtools::AsynchronLink* pExecuter; svtools::AsynchronLink* pUpdater; SfxVerbSlotArr_Impl aSlotArr; com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aVerbList; ::sfx2::sidebar::ContextChangeBroadcaster maContextChangeBroadcaster; SfxShell_Impl() : pExecuter( 0 ), pUpdater( 0 ) {} ~SfxShell_Impl() { delete pExecuter; delete pUpdater;} }; //==================================================================== #ifdef DBG_UTIL String SfxShellIdent_Impl( const SfxShell *pSh ) /* [Beschreibung] Interne Hilfesfunktion. Liefert einen die SfxShell 'pSh' beschreibenden String zur"uck. Z.B.: SfxApplication[StarWriter] */ { String aIdent( pSh->ISA(SfxApplication) ? DEFINE_CONST_UNICODE("SfxApplication") : pSh->ISA(SfxViewFrame) ? DEFINE_CONST_UNICODE("SfxViewFrame") : pSh->ISA(SfxViewShell) ? DEFINE_CONST_UNICODE("SfxViewShell") : pSh->ISA(SfxObjectShell) ? DEFINE_CONST_UNICODE("SfxObjectShell") : DEFINE_CONST_UNICODE("SfxShell") ); aIdent += '['; aIdent += pSh->GetName(); aIdent += ']'; return aIdent; } #endif //==================================================================== //========================================================================= // SfxShell //========================================================================= void __EXPORT SfxShell::EmptyExecStub(SfxShell *, SfxRequest &) { } void __EXPORT SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &) { } SfxShell::SfxShell() /* [Beschreibung] Der Konstruktor der Klasse SfxShell initialisierung nur einfache Typen, das dazugeh"orige SbxObject wird erst on-demand erzeugt. Daher ist das Anlegen einer SfxShell Instanz sehr billig. */ : pImp(0), pPool(0), pUndoMgr(0) { DBG_CTOR(SfxShell, 0); pImp = new SfxShell_Impl; pImp->pViewSh = 0; pImp->pFrame = 0; pImp->pRepeatTarget = 0; pImp->bInAppBASIC = sal_False; pImp->nHelpId = 0L; pImp->bActive = sal_False; pImp->nDisableFlags = 0; } //------------------------------------------------------------------------- SfxShell::SfxShell( SfxViewShell *pViewSh ) /* [Beschreibung] Der Konstruktor der Klasse SfxShell initialisierung nur einfache Typen, das dazugeh"orige SbxObject wird erst on-demand erzeugt. Daher ist das Anlegen einer SfxShell Instanz sehr billig. */ : pImp(0), pPool(0), pUndoMgr(0) { DBG_CTOR(SfxShell, 0); pImp = new SfxShell_Impl; pImp->pViewSh = pViewSh; pImp->pFrame = 0; pImp->pRepeatTarget = 0; pImp->bInAppBASIC = sal_False; pImp->nHelpId = 0L; pImp->bActive = sal_False; } //-------------------------------------------------------------------- SfxShell::~SfxShell() /* [Beschreibung] Die Verbindungs zu einem ggf. zugeh"origen SbxObject wird gel"ost. Das SbxObject existiert ggf. weiter, kann aber keine Funktionen mehr ausf"uhren und keine Properties mehr bereitstellen. */ { DBG_DTOR(SfxShell, 0); delete pImp; } //-------------------------------------------------------------------- void SfxShell::SetName( const String &rName ) /* [Beschreibung] Setzt den Namen des Shell-Objekts. Mit diesem Namen kann die SfxShell-Instanz vom BASIC aus angesprochen werden. */ { pImp->aObjectName = rName; } //-------------------------------------------------------------------- const String& SfxShell::GetName() const /* [Beschreibung] Liefert den Namen des Shell-Objekts. Mit diesem Namen kann die SfxShell-Instanz vom BASIC aus angesprochen werden. */ { return pImp->aObjectName; } //-------------------------------------------------------------------- SvGlobalName SfxShell::GetGlobalName() const /* [Beschreibung] Liefert den Global Unique Identifier des Shell-Objekts. Mit diesem Namen kann die SfxShell-Instanz z.B. via OLE Automation angesprochen werden, bzw. in der Registration-Database gefunden werden. */ { return SvGlobalName(); } //-------------------------------------------------------------------- SfxDispatcher* SfxShell::GetDispatcher() const /* [Beschreibung] Diese Methode liefert einen Pointer auf den , in dem die SfxShell gerade ist bzw. einen 0-Pointer, wenn sie gerade nicht UI-aktiv ist. Der zur"uckgegebene Pointer ist nur im unmittelbaren Kontext des Methodenaufrufs g"ultig. */ { return pImp->pFrame ? pImp->pFrame->GetDispatcher() : 0; } //-------------------------------------------------------------------- SfxViewShell* SfxShell::GetViewShell() const /* [Beschreibung] Liefert bei SubShells die SfxViewShell, in der sie liegen. Sonst und falls nicht vom App-Entwickler angegeben liefert diese Methode 0. */ { return pImp->pViewSh; } //-------------------------------------------------------------------- SfxViewFrame* SfxShell::GetFrame() const /* [Beschreibung] Diese Methode liefert einen Pointer auf den , dem diese SfxShell-Instanz zugeordnet ist oder in dem sie zur Zeit ist. Ein 0-Pointer wird geliefert, wenn diese SfxShell-OInstanz gerade nicht UI-aktiv ist und auch keinem SfxViewFrame fest zugeordnet ist. Der zur"uckgegebene Pointer ist nur im unmittelbaren Kontext des Methodenaufrufs g"ultig. [Anmerkung] Nur Instanzen von Subklasse von SfxApplication und SfxObjectShell sollten hier einen 0-Pointer liefern. Ansonsten liegt ein Fehler im Anwendungs- programm vor (falscher Ctor von SfxShell gerufen). [Querverweise] */ { if ( pImp->pFrame ) return pImp->pFrame; if ( pImp->pViewSh ) return pImp->pViewSh->GetViewFrame(); return 0; } //-------------------------------------------------------------------- const SfxPoolItem* SfxShell::GetItem ( sal_uInt16 nSlotId // Slot-Id des zu erfragenden s ) const /* [Beschreibung] Mit dieser Methode kann auf beliebige Objekte von Subklassen von zugegriffen werden. Diese Austauschtechnik wird ben"otigt, wenn z.B. spezielle Subklassen Zugriff auf bestimmte Daten z.B. der ben"otigen. Die zur"uckgelieferte Instanz geh"ort der jeweilige SfxShell und darf nur im unmittelbaren Kontext des Methodenaufrufs verwendet werden. [Querverweise] */ { for ( sal_uInt16 nPos = 0; nPos < pImp->aItems.Count(); ++nPos ) if ( pImp->aItems.GetObject(nPos)->Which() == nSlotId ) return pImp->aItems.GetObject(nPos); return 0; } //-------------------------------------------------------------------- void SfxShell::RemoveItem ( sal_uInt16 nSlotId // Slot-Id des zu l"oschenden s ) /* [Beschreibung] Mit dieser Methode k"onnen die allgemein zur Verf"ugung gestellten Instanzen von Subklassen von aus der SfxShell entfernt werden. Die gespeicherte Instanz wird gel"oscht. [Querverweise] */ { for ( sal_uInt16 nPos = 0; nPos < pImp->aItems.Count(); ++nPos ) if ( pImp->aItems.GetObject(nPos)->Which() == nSlotId ) { // Item entfernen und l"oschen SfxPoolItem *pItem = pImp->aItems.GetObject(nPos); delete pItem; pImp->aItems.Remove(nPos); // falls aktiv Bindings benachrichtigen SfxDispatcher *pDispat = GetDispatcher(); if ( pDispat ) { SfxVoidItem aVoid( nSlotId ); pDispat->GetBindings()->Broadcast( SfxPoolItemHint( &aVoid ) ); } } } //-------------------------------------------------------------------- void SfxShell::PutItem ( const SfxPoolItem& rItem /* Instanz, von der eine Kopie erstellt wird, die in der SfxShell in einer Liste gespeichert wird. */ ) /* [Beschreibung] Mit dieser Methode k"onnen beliebige Objekte von Subklassen von zur Verf"ugung gestellt werden. Diese Austauschtechnik wird ben"otigt, wenn z.B. spezielle Subklassen Zugriff auf bestimmte Daten z.B. der ben"otigen. Falls ein SfxPoolItem mit derselben Slot-Id exisitert, wird dieses automatisch gel"oscht. [Querverweise] */ { DBG_ASSERT( !rItem.ISA(SfxSetItem), "SetItems aren't allowed here" ); DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ), "items with Which-Ids aren't allowed here" ); // MSC auf WNT/W95 machte hier Mist, Vorsicht bei Umstellungen const SfxPoolItem *pItem = rItem.Clone(); SfxPoolItemHint aItemHint( (SfxPoolItem*) pItem ); const sal_uInt16 nWhich = rItem.Which(); SfxPoolItem **ppLoopItem = (SfxPoolItem**) pImp->aItems.GetData(); sal_uInt16 nPos; for ( nPos = 0; nPos < pImp->aItems.Count(); ++nPos, ++ppLoopItem ) { if ( (*ppLoopItem)->Which() == nWhich ) { // Item austauschen delete *ppLoopItem; pImp->aItems.Remove(nPos); pImp->aItems.Insert( (SfxPoolItemPtr) pItem, nPos ); // falls aktiv Bindings benachrichtigen SfxDispatcher *pDispat = GetDispatcher(); if ( pDispat ) { SfxBindings* pBindings = pDispat->GetBindings(); pBindings->Broadcast( aItemHint ); sal_uInt16 nSlotId = nWhich; //pItem->GetSlotId(); SfxStateCache* pCache = pBindings->GetStateCache( nSlotId ); if ( pCache ) { pCache->SetState( SFX_ITEM_AVAILABLE, pItem->Clone(), sal_True ); pCache->SetCachedState( sal_True ); } } return; } } Broadcast( aItemHint ); pImp->aItems.Insert((SfxPoolItemPtr)pItem, nPos ); } //-------------------------------------------------------------------- SfxInterface* SfxShell::GetInterface() const /* [Beschreibung] Mit dieser virtuellen Methode, die durch das Makro von jeder Subclass mit eigenen Slots automatisch "uberladen wird, kann auf die zu der Subklasse geh"orende -Instanz zugegriffen werden. Die Klasse SfxShell selbst hat noch kein eigenes SfxInterface (keine Slots), daher wird ein 0-Pointer zur"uckgeliefert. */ { return GetStaticInterface(); } //-------------------------------------------------------------------- SfxBroadcaster* SfxShell::GetBroadcaster() /* [Beschreibung] Liefert einen SfxBroadcaster f"ur diese SfxShell-Instanz bis die Klasse SfxShell von SfxBroadcaster abgeleitet ist. */ { return pImp; } //-------------------------------------------------------------------- ::svl::IUndoManager* SfxShell::GetUndoManager() /* [Beschreibung] Jede Subclass von SfxShell kann "uber einen verf"ugen. Dieser kann in den abgeleiteten Klasse mit gesetzt werden. Die Klasse SfxShell selbst hat noch keinen SfxUndoManager, es wird daher ein 0-Pointer zur"uckgeliefert. */ { return pUndoMgr; } //-------------------------------------------------------------------- void SfxShell::SetUndoManager( ::svl::IUndoManager *pNewUndoMgr ) /* [Beschreibung] Setzt einen f"ur diese Instanz. F"ur das Undo wird immer nur der Undo-Manager an der jeweils oben auf dem Stack des liegenden SfxShell verwendet. Am "ubergebenen wird automatisch die aktuelle Max-Undo-Action-Count Einstellung aus den Optionen gesetzt. 'pNewUndoMgr' mu\s bis zum Dtor dieser SfxShell-Instanz oder bis zum n"achsten 'SetUndoManager()' existieren. */ { OSL_ENSURE( ( pUndoMgr == NULL ) || ( pNewUndoMgr == NULL ) || ( pUndoMgr == pNewUndoMgr ), "SfxShell::SetUndoManager: exchanging one non-NULL manager with another non-NULL manager? Suspicious!" ); // there's at least one client of our UndoManager - the DocumentUndoManager at the SfxBaseModel - which // caches the UndoManager, and registers itself as listener. If exchanging non-NULL UndoManagers is really // a supported scenario (/me thinks it is not), then we would need to notify all such clients instances. pUndoMgr = pNewUndoMgr; if ( pUndoMgr ) pUndoMgr->SetMaxUndoActionCount( (sal_uInt16) SvtUndoOptions().GetUndoCount() ); } //-------------------------------------------------------------------- SfxRepeatTarget* SfxShell::GetRepeatTarget() const /* [Beschreibung] Liefert einen Pointer auf die -Instanz, die als RepeatTarget bei SID_REPEAT verwendet wird, wenn der von dieser SfxShell gelieferte angesprochen wird. Der R"uckgabewert kann 0 sein. [Anmerkung] Eine Ableitung von oder einer ihrer Subklassen von ist nicht zu empfehlen, da Compiler-Fehler provoziert werden (wegen Call-to-Pointer-to-Member-Function to subclass). */ { return pImp->pRepeatTarget; } //-------------------------------------------------------------------- void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget ) /* [Beschreibung] Setzt den die -Instanz, die bei SID_REPEAT als RepeatTarget verwendet wird, wenn der von dieser SfxShell gelieferte angesprochen wird. Durch 'pTarget==0' wird SID_REPEAT f"ur diese SfxShell disabled. Die Instanz '*pTarget' mu\s so lange leben, wie sie angemeldet ist. [Anmerkung] Eine Ableitung von oder einer ihrer Subklassen von ist nicht zu empfehlen, da Compiler-Fehler provoziert werden (wegen Call-to-Pointer-to-Member-Function to subclass). */ { pImp->pRepeatTarget = pTarget; } //-------------------------------------------------------------------- void SfxShell::Invalidate ( sal_uInt16 nId /* Zu invalidierende Slot-Id oder Which-Id. Falls diese 0 ist (default), werden alle z.Zt. von dieser Shell bedienten Slot-Ids invalidiert. */ ) /* [Beschreibung] Mit dieser Methode k"onnen Slots der Subclasses "uber die Slot-Id oder alternativ "uber die Which-Id invalidiert werden. Slot-Ids, die von der Subclass ererbt sind, werden ebenfalls invalidert. [Querverweise] */ { if ( !GetViewShell() ) { DBG_ERROR( "wrong Invalidate method called!" ); return; } Invalidate_Impl( GetViewShell()->GetViewFrame()->GetBindings(), nId ); } void SfxShell::Invalidate_Impl( SfxBindings& rBindings, sal_uInt16 nId ) { if ( nId == 0 ) { rBindings.InvalidateShell( *this, sal_False ); } else { const SfxInterface *pIF = GetInterface(); do { const SfxSlot *pSlot = pIF->GetSlot(nId); if ( pSlot ) { // bei Enum-Slots ist der Master-Slot zu invalidieren if ( SFX_KIND_ENUM == pSlot->GetKind() ) pSlot = pSlot->GetLinkedSlot(); // den Slot selbst und ggf. auch alle Slave-Slots invalidieren rBindings.Invalidate( pSlot->GetSlotId() ); for ( const SfxSlot *pSlave = pSlot->GetLinkedSlot(); pSlave && pIF->ContainsSlot_Impl( pSlave ) && pSlave->GetLinkedSlot() == pSlot; ++pSlave ) rBindings.Invalidate( pSlave->GetSlotId() ); return; } pIF = pIF->GetGenoType(); } while ( pIF ); DBG_WARNING( "W3: invalidating slot-id unknown in shell" ); } } //-------------------------------------------------------------------- void SfxShell::DoActivate_Impl( SfxViewFrame *pFrame, sal_Bool bMDI ) /* [Beschreibung] Diese Methode steuert die Aktivierung der SfxShell-Instanz. Zun"achst wird durch Aufruf der virtuellen Methode der Subclass die M"oglichkeit gegeben, auf das Event zu reagieren. Bei bMDI == TRUE wird das zugeh"orige SbxObject 'scharfgeschaltet', so da\s Methoden des Objekts unqualifiziert (ohne den Namen des Objekts) vom BASIC gefunden werden. */ { #ifdef DBG_UTIL const SfxInterface *p_IF = GetInterface(); if ( !p_IF ) return; #endif #ifdef DBG_UTIL_VB String aMsg("SfxShell::DoActivate() "); aMsg += (long)this; aMsg += " "; aMsg += GetInterface()->GetName(); aMsg += " bMDI "; if ( bMDI ) aMsg += "MDI"; DbgTrace( aMsg.GetBuffer() ); #endif if ( bMDI ) { // Frame merken, in dem aktiviert wird pImp->pFrame = pFrame; pImp->bActive = sal_True; } // Subklasse benachrichtigen Activate(bMDI); } //-------------------------------------------------------------------- void SfxShell::DoDeactivate_Impl( SfxViewFrame *pFrame, sal_Bool bMDI ) /* [Beschreibung] Diese Methode steuert die Deaktivierung der SfxShell-Instanz. Bei bMDI == TRUE wird zun"achst das SbxObject in einen Status versetzt, so da\s Methoden vom BASIC aus nur noch qualifiziert gerufen werden k"onnen. Dann erh"alt in jedem Fall die Subclass durch Aufruf der virtuellen Methode die M"oglichkeit auf das Event zu reagieren. */ { #ifdef DBG_UTIL const SfxInterface *p_IF = GetInterface(); if ( !p_IF ) return; #endif #ifdef DBG_UTIL_VB String aMsg("SfxShell::DoDeactivate()"); aMsg += (long)this; aMsg += " "; aMsg += GetInterface()->GetName(); aMsg += " bMDI "; if ( bMDI ) aMsg += "MDI"; DbgTrace( aMsg.GetBuffer() ); #endif // nur wenn er vom Frame kommt (nicht z.B. pop der BASIC-IDE vom AppDisp) if ( bMDI && pImp->pFrame == pFrame ) { // austragen pImp->pFrame = 0; pImp->bActive = sal_False; } // Subklasse benachrichtigen Deactivate(bMDI); } //-------------------------------------------------------------------- sal_Bool SfxShell::IsActive() const { return pImp->bActive; } //-------------------------------------------------------------------- void SfxShell::Activate ( sal_Bool /*bMDI*/ /* TRUE der , auf dem die SfxShell sich befindet, ist aktiv geworden oder die SfxShell Instanz wurde auf einen aktiven SfxDispatcher gepusht. (vergl. SystemWindow::IsMDIActivate()) FALSE das zum , auf dessen SfxDispatcher sich die SfxShell Instanz befindet, wurde aktiviert. (z.B. durch einen geschlossenen Dialog) */ ) /* [Beschreibung] Virtuelle Methode, die beim Aktivieren der SfxShell Instanz gerufen wird, um den Subclasses die Gelegenheit zu geben, auf das Aktivieren zu reagieren. [Querverweise] StarView SystemWindow::Activate(sal_Bool) */ { BroadcastContextForActivation(true); } //-------------------------------------------------------------------- void SfxShell::Deactivate ( sal_Bool /*bMDI*/ /* TRUE der , auf dem die SfxShell sich befindet, ist inaktiv geworden oder die SfxShell Instanz wurde auf einen aktiven SfxDispatcher gepoppt. (vergl. SystemWindow::IsMDIActivate()) FALSE das zum , auf dessen SfxDispatcher sich die SfxShell Instanz befindet, wurde deaktiviert. (z.B. durch einen Dialog) */ ) /* [Beschreibung] Virtuelle Methode, die beim Deaktivieren der SfxShell Instanz gerufen wird, um den Subclasses die Gelegenheit zu geben, auf das Deaktivieren zu reagieren. [Querverweise] StarView SystemWindow::Dectivate(sal_Bool) */ { BroadcastContextForActivation(false); } void SfxShell::ParentActivate ( ) /* [Beschreibung] Ein Parent des , auf dem die SfxShell sich befindet, ist aktiv geworden, oder die SfxShell Instanz wurde auf einen gepusht, dessen parent aktiv ist. Die Basisimplementation ist leer und braucht nicht gerufen zu werden. [Querverweise] SfxShell::Activate() */ { } //-------------------------------------------------------------------- void SfxShell::ParentDeactivate ( ) /* [Beschreibung] Der aktive Parent des , auf dem die SfxShell sich befindet, ist deaktiviert worden. Die Basisimplementation ist leer und braucht nicht gerufen zu werden. [Querverweise] SfxShell::Deactivate() */ { } //-------------------------------------------------------------------- ResMgr* SfxShell::GetResMgr() const /* [Beschreibung] Diese Methode liefert den ResMgr der , die von der SfxShell-Instanz verwendet wird. Ist dies ein 0-Pointer, so ist der aktuelle Resource-Manager zu verwenden. */ { return GetInterface()->GetResMgr(); } //-------------------------------------------------------------------- bool SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot ) /* [Beschreibung] Diese Methode stellt durch Aufruf der Statusfunktion fest, ob 'rSlot' aktuell ausgef"uhrt werden kann. */ { // Slot-Status holen SfxItemPool &rPool = GetPool(); const sal_uInt16 nId = rSlot.GetWhich( rPool ); SfxItemSet aSet(rPool, nId, nId); SfxStateFunc pFunc = rSlot.GetStateFnc(); CallState( pFunc, aSet ); return aSet.GetItemState(nId) != SFX_ITEM_DISABLED; } //-------------------------------------------------------------------- long ShellCall_Impl( void* pObj, void* pArg ) { ((SfxShell* )pObj)->ExecuteSlot( *(SfxRequest*)pArg, (SfxInterface*)0L ); return 0; } /* [Beschreibung] Asynchrones ExecuteSlot fuer das RELOAD */ //-------------------------------------------------------------------- const SfxPoolItem* SfxShell::ExecuteSlot( SfxRequest& rReq, sal_Bool bAsync ) { if( !bAsync ) return ExecuteSlot( rReq, (SfxInterface*)0L ); else { if( !pImp->pExecuter ) pImp->pExecuter = new svtools::AsynchronLink( Link( this, ShellCall_Impl ) ); pImp->pExecuter->Call( new SfxRequest( rReq ) ); return 0; } } const SfxPoolItem* SfxShell::ExecuteSlot ( SfxRequest &rReq, // der weiterzuleitende const SfxInterface* pIF // default = 0 bedeutet virtuell besorgen ) /* [Beschreibung] Diese Methode erm"oglicht das Weiterleiten eines an die angegebene Basis-. [Beispiel] In einer von SfxViewShell abgeleiteten Klasse soll SID_PRINTDOCDIRECT abgefangen werden. Unter bestimmten Umst"anden soll vor dem Drucken eine Abfrage erscheinen, und der Request soll ggf. abgebrochen werden. Dazu ist in der IDL dieser Subklasse der o.g. Slot einzutragen. Die Execute-Methode enth"alt dann skizziert: void SubViewShell::Exec( SfxRequest &rReq ) { if ( rReq.GetSlot() == SID_PRINTDOCDIRECT ) { 'dialog' if ( 'condition' ) ExecuteSlot( rReq, SfxViewShell::GetInterface() ); } } Es braucht i.d.R. kein rReq.Done() gerufen zu werden, da das bereits die Implementierung der SfxViewShell erledigt bzw. abgebrochen wurde. [Querverweise] */ { if ( !pIF ) pIF = GetInterface(); sal_uInt16 nSlot = rReq.GetSlot(); const SfxSlot* pSlot = NULL; if ( nSlot >= SID_VERB_START && nSlot <= SID_VERB_END ) pSlot = GetVerbSlot_Impl(nSlot); if ( !pSlot ) pSlot = pIF->GetSlot(nSlot); DBG_ASSERT( pSlot, "slot not supported" ); SfxExecFunc pFunc = pSlot->GetExecFnc(); if ( pFunc ) CallExec( pFunc, rReq ); return rReq.GetReturnValue(); } //-------------------------------------------------------------------- const SfxPoolItem* SfxShell::GetSlotState ( sal_uInt16 nSlotId, // Slot-Id des zu befragenden Slots const SfxInterface* pIF, // default = 0 bedeutet virtuell besorgen SfxItemSet* pStateSet // SfxItemSet der Slot-State-Methode ) /* [Beschreibung] Diese Methode liefert den Status des Slots mit der angegebenen Slot-Id "uber das angegebene Interface. Ist der Slot disabled oder in dieser SfxShell (und deren Parent-Shells) nicht bekannt, wird ein 0-Pointer zur"uckgeliefert. Hat der Slot keinen Status, wird ein SfxVoidItem zur"uckgeliefert. Der Status wird bei pStateSet != 0 gleich in diesem Set gesetzt, so da\s -Subklassen Slots-"uberladen und auch bei der Status-Methode die Basis-Implementierung rufen k"onnen. [Beispiel] In einer von SfxViewShell abgeleiteten Klasse soll SID_PRINTDOCDIRECT abgefangen werden. Unter bestimmten Umst"anden soll vor dem Drucken eine Abfrage erscheinen, und der Request soll ggf. abgebrochen werden. Dazu ist in der IDL dieser Subklasse der o.g. Slot einzutragen. Die Status-Methode enth"alt dann skizziert: void SubViewShell::PrintState( SfxItemSet &rState ) { if ( rState.GetItemState( SID_PRINTDOCDIRECT ) != SFX_ITEM_UNKNOWN ) GetSlotState( SID_PRINTDOCDIRECT, SfxViewShell::GetInterface(), &rState ); ... } [Querverweise] */ { // Slot am angegebenen Interface besorgen if ( !pIF ) pIF = GetInterface(); SfxItemState eState; SfxItemPool &rPool = GetPool(); const SfxSlot* pSlot = NULL; if ( nSlotId >= SID_VERB_START && nSlotId <= SID_VERB_END ) pSlot = GetVerbSlot_Impl(nSlotId); if ( !pSlot ) pSlot = pIF->GetSlot(nSlotId); if ( pSlot ) // ggf. auf Which-Id mappen nSlotId = pSlot->GetWhich( rPool ); // Item und Item-Status besorgen const SfxPoolItem *pItem = NULL; SfxItemSet aSet( rPool, nSlotId, nSlotId ); // pItem stirbt sonst zu fr"uh if ( pSlot ) { // Status-Methode rufen SfxStateFunc pFunc = pSlot->GetStateFnc(); if ( pFunc ) CallState( pFunc, aSet ); eState = aSet.GetItemState( nSlotId, sal_True, &pItem ); // ggf. Default-Item besorgen if ( eState == SFX_ITEM_DEFAULT ) { if ( SfxItemPool::IsWhich(nSlotId) ) pItem = &rPool.GetDefaultItem(nSlotId); else eState = SFX_ITEM_DONTCARE; } } else eState = SFX_ITEM_UNKNOWN; // Item und Item-Status auswerten und ggf. in pStateSet mitpflegen SfxPoolItem *pRetItem = 0; if ( eState <= SFX_ITEM_DISABLED ) { if ( pStateSet ) pStateSet->DisableItem(nSlotId); return 0; } else if ( eState == SFX_ITEM_DONTCARE ) { if ( pStateSet ) pStateSet->ClearItem(nSlotId); pRetItem = new SfxVoidItem(0); } else { if ( pStateSet && pStateSet->Put( *pItem ) ) return &pStateSet->Get( pItem->Which() ); pRetItem = pItem->Clone(); } DeleteItemOnIdle(pRetItem); return pRetItem; } //-------------------------------------------------------------------- SFX_EXEC_STUB(SfxShell, VerbExec) SFX_STATE_STUB(SfxShell, VerbState) void SfxShell::SetVerbs(const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs) { SfxViewShell *pViewSh = PTR_CAST ( SfxViewShell, this); DBG_ASSERT(pViewSh, "SetVerbs nur an der ViewShell aufrufen!"); if ( !pViewSh ) return; // Zun"achst alle Statecaches dirty machen, damit keiner mehr versucht, // die Slots zu benutzen { SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()->GetBindings(); sal_uInt16 nCount = pImp->aSlotArr.Count(); for (sal_uInt16 n1=0; n1Invalidate(nId, sal_False, sal_True); } } sal_uInt16 nr=0; for (sal_Int32 n=0; n SID_VERB_END) break; SfxSlot *pNewSlot = new SfxSlot; pNewSlot->nSlotId = nSlotId; pNewSlot->nGroupId = 0; // Verb-Slots m"ussen asynchron ausgef"uhrt werden, da sie w"ahrend // des Ausf"uhrens zerst"ort werden k"onnten pNewSlot->nFlags = SFX_SLOT_ASYNCHRON | SFX_SLOT_CONTAINER; pNewSlot->nMasterSlotId = 0; pNewSlot->nValue = 0; pNewSlot->fnExec = SFX_STUB_PTR(SfxShell,VerbExec); pNewSlot->fnState = SFX_STUB_PTR(SfxShell,VerbState); pNewSlot->pType = 0; HACK(SFX_TYPE(SfxVoidItem)) pNewSlot->pName = OUStringToOString( aVerbs[n].VerbName, RTL_TEXTENCODING_UTF8).getStr(); // TODO: life time of temp is suspicious!!! pNewSlot->pLinkedSlot = 0; pNewSlot->nArgDefCount = 0; pNewSlot->pFirstArgDef = 0; pNewSlot->pUnoName = 0; if (pImp->aSlotArr.Count()) { SfxSlot *pSlot = (pImp->aSlotArr)[0]; pNewSlot->pNextSlot = pSlot->pNextSlot; pSlot->pNextSlot = pNewSlot; } else pNewSlot->pNextSlot = pNewSlot; pImp->aSlotArr.Insert(pNewSlot, (sal_uInt16) n); } pImp->aVerbList = aVerbs; if (pViewSh) { // Der Status von SID_OBJECT wird im Controller direkt an der Shell // abgeholt, es reicht also, ein neues StatusUpdate anzuregen SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()-> GetBindings(); pBindings->Invalidate( SID_OBJECT, sal_True, sal_True ); } } //-------------------------------------------------------------------- const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& SfxShell::GetVerbs() const { return pImp->aVerbList; } //-------------------------------------------------------------------- void SfxShell::VerbExec(SfxRequest& rReq) { sal_uInt16 nId = rReq.GetSlot(); SfxViewShell *pViewShell = GetViewShell(); if ( pViewShell ) { sal_Bool bReadOnly = pViewShell->GetObjectShell()->IsReadOnly(); com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aList = pViewShell->GetVerbs(); for (sal_Int32 n=0, nVerb=0; nDoVerb(aList[n].VerbID); rReq.Done(); return; } } } } //-------------------------------------------------------------------- void SfxShell::VerbState(SfxItemSet& ) { } //-------------------------------------------------------------------- const SfxSlot* SfxShell::GetVerbSlot_Impl(sal_uInt16 nId) const { com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > rList = pImp->aVerbList; DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Falsche VerbId!"); sal_uInt16 nIndex = nId - SID_VERB_START; DBG_ASSERT(nIndex < rList.getLength(),"Falsche VerbId!"); if (nIndex < rList.getLength()) return pImp->aSlotArr[nIndex]; else return 0; } //-------------------------------------------------------------------- void SfxShell::SetHelpId(sal_uIntPtr nId) { pImp->nHelpId = nId; } //-------------------------------------------------------------------- sal_uIntPtr SfxShell::GetHelpId() const { return pImp->nHelpId; } //-------------------------------------------------------------------- SfxObjectShell* SfxShell::GetObjectShell() { if ( GetViewShell() ) return GetViewShell()->GetViewFrame()->GetObjectShell(); else return NULL; } //-------------------------------------------------------------------- sal_Bool SfxShell::HasUIFeature( sal_uInt32 ) { return sal_False; } long DispatcherUpdate_Impl( void*, void* pArg ) { ((SfxDispatcher*) pArg)->Update_Impl( sal_True ); ((SfxDispatcher*) pArg)->GetBindings()->InvalidateAll(sal_False); return 0; } void SfxShell::UIFeatureChanged() { SfxViewFrame *pFrame = GetFrame(); if ( pFrame && pFrame->IsVisible() ) { // Auch dann Update erzwingen, wenn Dispatcher schon geupdated ist, // sonst bleibt evtl. irgendwas in den gebunkerten Tools stecken. // Asynchron aufrufen, um Rekursionen zu vermeiden if ( !pImp->pUpdater ) pImp->pUpdater = new svtools::AsynchronLink( Link( this, DispatcherUpdate_Impl ) ); // Mehrfachaufrufe gestattet pImp->pUpdater->Call( pFrame->GetDispatcher(), sal_True ); } } void SfxShell::SetDisableFlags( sal_uIntPtr nFlags ) { pImp->nDisableFlags = nFlags; } sal_uIntPtr SfxShell::GetDisableFlags() const { return pImp->nDisableFlags; } SfxItemSet* SfxShell::CreateItemSet( sal_uInt16 ) { return NULL; } void SfxShell::ApplyItemSet( sal_uInt16, const SfxItemSet& ) { } void SfxShell::SetContextName (const ::rtl::OUString& rsContextName) { pImp->maContextChangeBroadcaster.Initialize(rsContextName); } void SfxShell::SetViewShell_Impl( SfxViewShell* pView ) { pImp->pViewSh = pView; } void SfxShell::BroadcastContextForActivation (const bool bIsActivated) { SfxViewFrame* pViewFrame = GetFrame(); if (pViewFrame != NULL) if (bIsActivated) pImp->maContextChangeBroadcaster.Activate(pViewFrame->GetFrame().GetFrameInterface()); else pImp->maContextChangeBroadcaster.Deactivate(pViewFrame->GetFrame().GetFrameInterface()); } bool SfxShell::SetContextBroadcasterEnabled (const bool bIsEnabled) { return pImp->maContextChangeBroadcaster.SetBroadcasterEnabled(bIsEnabled); }