blob: 1c39a2278852de33aebbf863db0ecf2d1b4d7c69 [file] [log] [blame]
/**************************************************************
*
* 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 <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <svl/itempool.hxx>
#include <svl/itemiter.hxx>
#include <svl/whiter.hxx>
#include <svl/intitem.hxx>
#ifndef _SFXEITEM_HXX //autogen
#include <svl/eitem.hxx>
#endif
#include <svl/undo.hxx>
#ifndef _WRKWIN_HXX //autogen
#include <vcl/wrkwin.hxx>
#endif
#include <svtools/ttprops.hxx>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h> // wg. bsearch
#define _SVSTDARR_ULONGS
#include <svl/svstdarr.hxx>
#include <svtools/helpopt.hxx>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#ifndef GCC
#endif
// wg. nAutoPageID
#include "appdata.hxx"
#include "sfx2/sfxhelp.hxx"
#include <sfx2/dispatch.hxx>
#include <sfx2/minstack.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/request.hxx>
#include <sfx2/app.hxx>
#include <sfx2/hintpost.hxx>
#include "slotserv.hxx"
#include <sfx2/ipclient.hxx>
#include "sfxtypes.hxx"
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/childwin.hxx>
#include <sfx2/docfac.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/module.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/sfxuno.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/mnumgr.hxx>
#include "workwin.hxx"
namespace css = ::com::sun::star;
//==================================================================
DBG_NAME(SfxDispatcherFlush)
DBG_NAME(SfxDispatcherFillState)
//==================================================================
typedef SfxRequest* SfxRequestPtr;
SV_IMPL_PTRARR( SfxItemPtrArray, SfxPoolItemPtr );
SV_DECL_PTRARR_DEL( SfxRequestPtrArray, SfxRequestPtr, 4, 4 )
SV_IMPL_PTRARR( SfxRequestPtrArray, SfxRequestPtr );
DECL_PTRSTACK(SfxShellStack_Impl, SfxShell*, 8, 4 );
//==================================================================
struct SfxToDo_Impl
{
SfxShell* pCluster;
bool bPush;
bool bDelete;
bool bUntil;
SfxToDo_Impl()
: pCluster(0)
, bPush(false)
, bDelete(false)
, bUntil(false)
{}
SfxToDo_Impl( bool bOpPush, bool bOpDelete, bool bOpUntil, SfxShell& rCluster )
: pCluster(&rCluster)
, bPush(bOpPush)
, bDelete(bOpDelete)
, bUntil(bOpUntil)
{}
~SfxToDo_Impl(){}
bool operator==( const SfxToDo_Impl& rWith ) const
{ return pCluster==rWith.pCluster && bPush==rWith.bPush; }
};
DECL_OBJSTACK(SfxToDoStack_Impl, SfxToDo_Impl, 8, 4);
IMPL_OBJSTACK(SfxToDoStack_Impl, SfxToDo_Impl);
struct SfxObjectBars_Impl
{
sal_uInt32 nResId; // Resource - und ConfigId der Toolbox
sal_uInt16 nMode; // spezielle Sichtbarkeitsflags
String aName;
SfxInterface* pIFace;
SfxObjectBars_Impl() :
nResId( 0 )
{}
};
//------------------------------------------------------------------
struct SfxDispatcher_Impl
{
SfxRequestPtrArray aReqArr;
const SfxSlotServer* pCachedServ1; // zuletzt gerufene Message
const SfxSlotServer* pCachedServ2; // vorletzt gerufene Message
SfxShellStack_Impl aStack; // aktive Funktionalitaet
Timer aTimer; // fuers flushen
SfxToDoStack_Impl aToDoStack; // nicht abgearb. Push/Pop
SfxViewFrame* pFrame; // 0 oder zugeh"or. Frame
SfxDispatcher* pParent; // z.B. AppDispatcher, ggf. 0
SfxHintPosterRef xPoster; // asynchrones Execute
sal_Bool bFlushing; // sal_True waehrend Flush //?
sal_Bool bUpdated; // Update_Impl gelaufen
sal_Bool bLocked; // kein Execute
sal_Bool bInvalidateOnUnlock;// da fragte jemand
sal_Bool bActive; // nicht verwechseln mit gesetzt!
sal_Bool* pInCallAliveFlag; // dem Stack den Dtor anzeigen
SfxObjectBars_Impl aObjBars[SFX_OBJECTBAR_MAX];
SfxObjectBars_Impl aFixedObjBars[SFX_OBJECTBAR_MAX];
SvULongs aChildWins;
sal_uInt32 nEventId; // EventId UserEvent
sal_Bool bUILocked; // Update abgeklemmt (!zappeln)
sal_Bool bNoUI; // UI nur vom Parent Dispatcher
sal_Bool bReadOnly; // Dokument ist ReadOnly
sal_Bool bQuiet; // nur parent dispatcher verwenden
sal_Bool bModal; // nur Slots vom Parent-Dispatcher
sal_Bool bFilterEnabling; // sal_True=filter enabled slots, 2==ReadOnlyDoc uebersteuert
sal_uInt16 nFilterCount; // Anzahl der SIDs in pFilterSIDs
const sal_uInt16* pFilterSIDs; // sortiertes Array von SIDs
sal_uInt16 nStandardMode; // ExecuteMode f. PlugInDispatcher
SvUShorts* pDisableList;
sal_uInt32 nDisableFlags;
};
#define NO_OBJECTBAR 0
#define OWN_OBJECTBAR 1
#define OTHER_OBJECTBAR 2
//------------------------------------------------------------------
#define SFX_FLUSH_TIMEOUT 50
//====================================================================
sal_Bool SfxDispatcher::IsLocked( sal_uInt16 ) const
/* [Beschreibung]
Mit dieser Methode kann festgestellt werden, ob der SfxDispatcher
gesperrt oder freigegeben ist. Ein gesperrter SfxDispatcher
f"uhrt keine <SfxRequest>s mehr aus und liefert keine
Status-Informationen mehr. Er verh"alt sich so als w"aren alle
Slots disabled.
Der Dispatcher gilt auch als gesperrt, wenn alle Dispatcher
gelockt sind (<SfxApplication::LockDispatcher()>) oder der zugeh"orige
Top-Frame im modal-mode ist und der angegebene Slot Frame-spezifisch
(also nicht von der Application) bedient wird.
*/
{
return pImp->bLocked;
}
//--------------------------------------------------------------------
sal_Bool SfxDispatcher::IsAppDispatcher() const
/* [Beschreibung]
Mit dieser Methode l"a\st sich festellen, ob der SfxDispacher der
Applikations-Dispatcher ist.
[R"uckgabewert]
sal_Bool sal_True
Es ist der Applikations-Dispatcher.
sal_False
Es ist ein Dispatcher eines SfxViewFrame.
*/
{
return !pImp->pFrame;
}
//--------------------------------------------------------------------
int SfxDispatcher::Call_Impl( SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, sal_Bool bRecord )
/* [Beschreibung]
Hilfsfunktion zum pr"ufen, ob ein Slot executed werden darf und
der Execution selbst.
*/
{
SFX_STACK(SfxDispatcher::Call_Impl);
// darf der Slot gerufen werden (i.S.v. enabled)
if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
{
if ( GetFrame() )
{
// ggf. Recording anwerfen
com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame(
GetFrame()->GetFrame().GetFrameInterface(),
com::sun::star::uno::UNO_QUERY);
com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
xFrame,
com::sun::star::uno::UNO_QUERY);
if ( xSet.is() )
{
com::sun::star::uno::Any aProp = xSet->getPropertyValue(::rtl::OUString::createFromAscii("DispatchRecorderSupplier"));
com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
aProp >>= xSupplier;
if(xSupplier.is())
xRecorder = xSupplier->getDispatchRecorder();
if ( bRecord && xRecorder.is() && !rSlot.IsMode(SFX_SLOT_NORECORD) )
rReq.Record_Impl( rShell, rSlot, xRecorder, GetFrame() );
}
}
// Alles holen, was gebraucht wird, da der Slot den Execute evtl. nicht
// "uberlebt, falls es ein 'Pseudoslot' f"ur Macros oder Verben ist
sal_Bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
// API-Call-Klammerung und Document-Lock w"ahrend des Calls
{
// 'this' mu\s im Dtor bescheid sagen
sal_Bool bThisDispatcherAlive = sal_True;
sal_Bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
pImp->pInCallAliveFlag = &bThisDispatcherAlive;
SfxViewFrame* pView = GetFrame();
if ( !pView )
pView = SfxViewFrame::Current();
if ( pView )
{
rtl::OString aCmd(".uno:");
aCmd += rSlot.GetUnoName();
SfxHelp::OpenHelpAgent( &pView->GetFrame(), aCmd );
}
SfxExecFunc pFunc = rSlot.GetExecFnc();
rShell.CallExec( pFunc, rReq );
// falls 'this' noch lebt
if ( bThisDispatcherAlive )
pImp->pInCallAliveFlag = pOldInCallAliveFlag;
else
{
if ( pOldInCallAliveFlag )
{
// auch verschachtelte Stack-Frames sch"utzen
*pOldInCallAliveFlag = sal_False;
}
// do nothing after this object is dead
return rReq.IsDone();
}
}
if ( rReq.IsDone() )
{
SfxBindings *pBindings = GetBindings();
// bei AutoUpdate sofort updaten; "Pseudoslots" d"urfen nicht
// Autoupdate sein!
if ( bAutoUpdate && pBindings )
{
const SfxSlot* pSlave = rSlot.GetLinkedSlot();
if (pSlave)
{
// bei Enum-Slots irgendeinen gebundenen Slave-Slot nehmen
while (!pBindings->IsBound(pSlave->GetSlotId()) && pSlave != &rSlot )
pSlave = pSlave->GetLinkedSlot();
pBindings->Invalidate(pSlave->GetSlotId());
pBindings->Update(pSlave->GetSlotId());
}
else
{
pBindings->Invalidate(rSlot.GetSlotId());
pBindings->Update(rSlot.GetSlotId());
}
}
return sal_True;
}
}
return sal_False;
}
//====================================================================
void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
{
pImp = new SfxDispatcher_Impl;
bFlushed = sal_True;
SfxApplication *pSfxApp = SFX_APP();
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
pImp->bFlushing = sal_False;
pImp->bUpdated = sal_False;
pImp->bLocked = sal_False;
pImp->bActive = sal_False;
pImp->pParent = NULL;
pImp->bUILocked = sal_False;
pImp->bNoUI = sal_False;
pImp->bReadOnly = sal_False;
pImp->bQuiet = sal_False;
pImp->bModal = sal_False;
pImp->pInCallAliveFlag = 0;
pImp->bFilterEnabling = sal_False;
pImp->nFilterCount = 0;
pImp->pFilterSIDs = 0;
pImp->nStandardMode = 0;
pImp->pDisableList = pSfxApp->GetDisabledSlotList_Impl();
pImp->nDisableFlags = 0;
pImp->pParent = pParent;
pImp->bInvalidateOnUnlock = sal_False;
for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
pImp->aObjBars[n].nResId = 0;
GenLink aGenLink( LINK(this, SfxDispatcher, PostMsgHandler) );
pImp->xPoster = new SfxHintPoster(aGenLink);
pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
}
SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
{
Construct_Impl( pParent );
pImp->pFrame = 0;
}
SfxDispatcher::SfxDispatcher( SfxViewFrame *pViewFrame )
/* [Beschreibung]
Der Konstruktor der Klasse SfxDispatcher legt einen leeren Stack
von <SfxShell>-Pointern an. Er ist initial nicht gelockt und gilt als
geflusht.
*/
{
if ( pViewFrame )
{
SfxViewFrame *pFrame = pViewFrame->GetParentViewFrame();
if ( pFrame )
Construct_Impl( pFrame->GetDispatcher() );
else
Construct_Impl( 0 );
}
else
Construct_Impl( 0 );
pImp->pFrame = pViewFrame;
}
//====================================================================
SfxDispatcher::~SfxDispatcher()
/* [Beschreibung]
Der Destruktor der Klasse SfxDispatcher darf nicht gerufen werden,
wenn die SfxDispatcher-Instanz aktiv ist. Es d"urfen sich allerdings
noch <SfxShell>-Pointer auf dem Stack befinden.
*/
{
#ifdef DBG_UTIL
ByteString sTemp( "Delete Dispatcher " );
sTemp += ByteString::CreateFromInt64( (sal_uIntPtr)this );
DBG_TRACE( sTemp.GetBuffer() );
DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
#endif
// Damit in LeaveRegistrations kein Timer per Reschedule in PlugComm
// zuschlaegt
pImp->aTimer.Stop();
pImp->xPoster->SetEventHdl( Link() );
// die Stack-Varialblem in Call_Impl benachrichtigen
if ( pImp->pInCallAliveFlag )
*pImp->pInCallAliveFlag = sal_False;
// Bindings und App besorgen
SfxApplication *pSfxApp = SFX_APP();
SfxBindings* pBindings = GetBindings();
// if (pImp->nEventId)
// pSfxApp->RemoveEventHdl(pImp->nEventId);
// wenn noch nicht flushed, die Bindings wiederbeleben
if ( pBindings && !pSfxApp->IsDowning() && !bFlushed )
pBindings->DLEAVEREGISTRATIONS();
// ggf. bei den Bindings abmelden
while ( pBindings )
{
if ( pBindings->GetDispatcher_Impl() == this)
pBindings->SetDispatcher(0);
pBindings = pBindings->GetSubBindings_Impl();
}
delete pImp;
}
//====================================================================
void SfxDispatcher::Pop
(
SfxShell& rShell, /* Die vom Stack zu nehmende SfxShell-Instanz. */
sal_uInt16 nMode /* SFX_SHELL_POP_UNTIL
Es werden auch alle "uber 'rShell' liegenenden
SfxShell's vom Stack genommen.
SFX_SHELL_POP_DELETE
Alle tats"achlich vom Stack genommenen
SfxShells werden gel"oscht.
SFX_SHELL_PUSH (InPlace use only)
Die Shell wird gepusht. */
)
/* [Beschreibung]
Mit dieser Methode wird eine oder mehrere <SfxShell> vom SfxDispatcher
gepoppt. Die SfxShell wird zun"achst zum poppen vermerkt und
es wird ein Timer aufgesetzt. Erst bei Ablauf des Timers wird
tats"achlich gepoppt (<SfxDispatcher::Flush()>) und die <SfxBindings>
werden invalidiert. W"ahrend der Timer l"auft gleichen sich
entgegengesetzte Push und Pop Befehle mit derselben SfxShell aus.
*/
{
DBG_MEMTEST();
DBG_ASSERT( rShell.GetInterface(),
"pushing SfxShell without previous RegisterInterface()" );
bool bDelete = (nMode & SFX_SHELL_POP_DELETE) == SFX_SHELL_POP_DELETE;
bool bUntil = (nMode & SFX_SHELL_POP_UNTIL) == SFX_SHELL_POP_UNTIL;
bool bPush = (nMode & SFX_SHELL_PUSH) == SFX_SHELL_PUSH;
SfxApplication *pSfxApp = SFX_APP();
#ifdef DBG_UTIL
ByteString aMsg( "-SfxDispatcher(" );
aMsg += ByteString::CreateFromInt64( (sal_uIntPtr) this );
aMsg += bPush ? ")::Push(" : ")::Pop(";
if ( rShell.GetInterface() )
aMsg += rShell.GetInterface()->GetClassName();
else
aMsg += ByteString::CreateFromInt64( (sal_uIntPtr) &rShell );
aMsg += bDelete ? ") with delete" : ")";
if ( bUntil ) aMsg += " (up to)";
DbgTrace( aMsg.GetBuffer() );
#endif
// gleiche Shell wie on-Top des ToDo-Stacks?
if ( pImp->aToDoStack.Count() && pImp->aToDoStack.Top().pCluster == &rShell )
{
// inverse Actions heben sich auf
if ( pImp->aToDoStack.Top().bPush != bPush )
pImp->aToDoStack.Pop();
else
{
DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
}
}
else
{
// ::com::sun::star::chaos::Action merken
pImp->aToDoStack.Push( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
if ( bFlushed )
{
DBG_TRACE("Unflushed dispatcher!");
bFlushed = sal_False;
pImp->bUpdated = sal_False;
// Bindings schlafen legen
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->DENTERREGISTRATIONS();
}
}
if ( !pSfxApp->IsDowning() && pImp->aToDoStack.Count() )
{
//! if (SFX_APP()->AnyInput(INPUT_KEYBOARD | INPUT_MOUSE) )
//! AnyInput haut nicht hin; hier muss noch ein Kriterium gefunden
//! werden. Solange wieder immer mit Timer.
if (sal_True)
{
// Kein sofortiges Update gewuenscht
pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
pImp->aTimer.Start();
}
else
{
// Schnellstmoegliches Update (sollte Normalfall sein)
pImp->aTimer.Stop();
GetpApp()->PostUserEvent(pImp->nEventId, (void*)0);
}
}
else
{
// doch nichts zu tun
pImp->aTimer.Stop();
// ggf. Bindings wieder aufwecken
if ( !pImp->aToDoStack.Count() )
{
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->DLEAVEREGISTRATIONS();
}
}
}
//--------------------------------------------------------------------
IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
/* [Beschreibung]
Dieser Handler wird nach <SfxDispatcher::Invalidate()> oder Bewegungen
auf dem Stack (<SfxDispatcher::Push()> und <SfxDispatcher::Pop()) gerufen.
Er flusht den Stack, falls er dirty ist, f"uhrt also die ausstehenden
Push und Pop Befehle tats"achlich aus.
*/
{
(void)pvoid; // unused
DBG_MEMTEST();
Flush();
Update_Impl();
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->StartUpdate_Impl(sal_False);
return 0;
}
IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
//--------------------------------------------------------------------
sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDeep )
/* [Beschreibung]
Mit dieser Methode kann gepr"uft werden, ob sich die <SfxShell> rShell
auf dem Stack befindet, wenn er geflusht w"are. Dabei wird der
SfxDispatcher jedoch nicht tats"achlich geflusht.
Diese Methode ist u.a. dazu gedacht, Assertions zu erm"oglichen, ohne
als Seiteneffekt den SfxDispathcer flushen zu m"ussen.
*/
{
DBG_MEMTEST();
SFX_STACK(SfxDispatcher::CheckVirtualStack);
SfxShellStack_Impl aStack( pImp->aStack );
for ( short nToDo = pImp->aToDoStack.Count()-1; nToDo >= 0; --nToDo )
{
SfxToDo_Impl aToDo( pImp->aToDoStack.Top(nToDo) );
if ( aToDo.bPush )
aStack.Push( (SfxShell*) aToDo.pCluster );
else
{
SfxShell* pPopped = 0;
do
{
DBG_ASSERT( aStack.Count(), "popping from empty stack" );
pPopped = aStack.Pop();
}
while ( aToDo.bUntil && pPopped != aToDo.pCluster );
DBG_ASSERT( pPopped == aToDo.pCluster, "popping unpushed SfxInterface" );
}
}
sal_Bool bReturn;
if ( bDeep )
bReturn = aStack.Contains(&rShell);
else
bReturn = aStack.Top() == &rShell;
return bReturn;
}
//--------------------------------------------------------------------
sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
/* [Beschreibung]
Ermittelt die Position einer SfxShell im Stack des Dispatchers.
Dazu wird dieser ggf. zuvor geflusht.
[Rueckgabewert]
sal_uInt16 == USRT_MAX
Die SfxShell befindet sich nicht auf
diesem SfxDispatcher.
< USHRT_MAX
Position der SfxShell auf dem Dispatcher
von oben mit 0 beginnend gez"ahlt.
*/
{
DBG_MEMTEST();
SFX_STACK(SfxDispatcher::GetShellLevel);
Flush();
for ( sal_uInt16 n = 0; n < pImp->aStack.Count(); ++n )
if ( pImp->aStack.Top( n ) == &rShell )
return n;
if ( pImp->pParent )
{
sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
if ( nRet == USHRT_MAX )
return nRet;
return nRet + pImp->aStack.Count();
}
return USHRT_MAX;
}
//--------------------------------------------------------------------
SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
/* [Beschreibung]
Liefert einen Pointer auf die <SfxShell>, welche sich an der Position
nIdx (von oben, letzt-gepushte liegt bei 0) auf dem Stack befindet.
Dabei wird der SfxDispatcher nicht geflusht.
Ist der Stack nicht tief genug, wird ein 0-Pointer zur"uckgegeben.
*/
{
DBG_MEMTEST();
sal_uInt16 nShellCount = pImp->aStack.Count();
if ( nIdx < nShellCount )
return pImp->aStack.Top(nIdx);
else if ( pImp->pParent )
return pImp->pParent->GetShell( nIdx - nShellCount );
return 0;
}
//--------------------------------------------------------------------
SfxBindings* SfxDispatcher::GetBindings() const
/* [Beschreibung]
Diese Methode liefert einen Pointer auf die <SfxBindings> Instanz
zur"uck, an die der SfxDispatcher gerade gebunden ist. Ein SfxDispatcher
ist nur dann an SfxBindings gebunden, wenn er <UI-aktiv> ist. Ist
er nicht UI-aktiv, wird ein 0-Pointer zur"uckgegeben.
Der zur"uckgegebene Pointer ist nur im <unmittelbaren Kontext> des
Methodenaufrufs g"ultig.
*/
{
if ( pImp->pFrame )
return &pImp->pFrame->GetBindings();
else
return NULL;
}
//--------------------------------------------------------------------
SfxViewFrame* SfxDispatcher::GetFrame() const
/* [Beschreibung]
Liefert einen Pointer auf die <SfxViewFrame> Instanz, der dieser
SfxDispatcher geh"ort. Falls es sich um den Applikations-Dispatcher
handelt, wird ein 0-Pointer zur"uckgegeben.
*/
{
DBG_MEMTEST();
return pImp->pFrame;
}
//--------------------------------------------------------------------
void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ )
/* [Beschreibung]
Diese Methode steuert das Aktivieren eines Dispatchers.
Da der Applikations-Dispatcher immer aktiv ist, entweder als
Unterdispatcher des <SfxViewFrame>-Dispatchers oder selbst, wird
er nie als ganzes Aktiviert, sondern nur seine einzelnen <SfxShell>s
bei <SfxDispatcher::Push(SfxShell&)>.
Beim Aktivieren eines SfxDispatchers wird an allen auf seinem
Stack befindlichen SfxShells, beginnend mit der untersten, der Handler
<SfxShell::Activate(sal_Bool)> gerufen.
*/
{
DBG_MEMTEST();
SFX_STACK(SfxDispatcher::DoActivate);
if ( bMDI )
{
#ifdef DBG_UTIL
ByteString sTemp("Activate Dispatcher ");
sTemp += ByteString::CreateFromInt64( (sal_uIntPtr) this );
DBG_TRACE(sTemp.GetBuffer());
DBG_ASSERT( !pImp->bActive, "Activate-Fehler" );
#endif
pImp->bActive = sal_True;
pImp->bUpdated = sal_False;
SfxBindings* pBindings = GetBindings();
if ( pBindings )
{
pBindings->SetDispatcher(this);
pBindings->SetActiveFrame( pImp->pFrame->GetFrame().GetFrameInterface() );
}
}
else
{
#ifdef DBG_UTIL
ByteString sTemp("Non-MDI-Activate Dispatcher");
sTemp += ByteString::CreateFromInt64( (sal_uIntPtr) this );
DBG_TRACE( sTemp.GetBuffer() );
#endif
}
if ( IsAppDispatcher() )
return;
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->DoActivate_Impl(pImp->pFrame, bMDI);
if ( bMDI && pImp->pFrame )
{
//SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
SfxBindings *pBind = GetBindings();
while ( pBind )
{
pBind->HidePopupCtrls_Impl( sal_False );
pBind = pBind->GetSubBindings_Impl();
}
pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( sal_False, sal_False, 1 );
}
if ( pImp->aToDoStack.Count() )
{
if (sal_True)
{
// Kein sofortiges Update gewuenscht
pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
pImp->aTimer.Start();
}
else
{
// Schnellstmoegliches Update (sollte Normalfall sein)
pImp->aTimer.Stop();
GetpApp()->PostUserEvent(pImp->nEventId, (void*)0);
}
}
}
void SfxDispatcher::DoParentActivate_Impl()
{
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->ParentActivate();
}
//--------------------------------------------------------------------
void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew )
/* [Beschreibung]
Diese Methode steuert das Deaktivieren eines Dispatchers.
Da der Applikations-Dispatcher immer aktiv ist, entweder als
Unterdispatcher des <SfxViewFrame>-Dispatchers oder selbst, wird
er nie als ganzes Deaktiviert, sondern nur seine einzelnen <SfxShell>s
bei <SfxDispatcher::Pop(SfxShell&)>.
Beim Deaktivieren eines SfxDispatchers wird an allen auf seinem
Stack befindlichen SfxShells, beginnend mit der obersten, der Handler
<SfxShell::Deactivate(sal_Bool)> gerufen.
*/
{
DBG_MEMTEST();
SFX_STACK(SfxDispatcher::DoDeactivate);
SfxApplication *pSfxApp = SFX_APP();
if ( bMDI )
{
DBG_TRACE(ByteString("Deactivate Dispatcher ").Append(ByteString::CreateFromInt64( (sal_uIntPtr) this )).GetBuffer());
DBG_ASSERT( pImp->bActive, "Deactivate-Fehler" );
pImp->bActive = sal_False;
if ( pImp->pFrame && !(pImp->pFrame->GetObjectShell()->IsInPlaceActive() ) )
{
SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
if ( pWorkWin )
{
for (sal_uInt16 n=0; n<pImp->aChildWins.Count();)
{
SfxChildWindow *pWin = pWorkWin->GetChildWindow_Impl( (sal_uInt16) ( pImp->aChildWins[n] & 0xFFFF ) );
if (!pWin || (pWin && pWin->GetAlignment() == SFX_ALIGN_NOALIGNMENT))
pImp->aChildWins.Remove(n);
else
n++;
}
}
}
}
else {
DBG_TRACE( ByteString ("Non-MDI-DeActivate Dispatcher").Append(ByteString::CreateFromInt64( (sal_uIntPtr) this )).GetBuffer() );
}
if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
return;
for ( sal_uInt16 i = 0; i < pImp->aStack.Count(); ++i )
pImp->aStack.Top(i)->DoDeactivate_Impl(pImp->pFrame, bMDI);
sal_Bool bHidePopups = bMDI && pImp->pFrame;
if ( pNew && pImp->pFrame )
{
com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xOldFrame(
pNew->GetFrame().GetFrameInterface()->getCreator(), com::sun::star::uno::UNO_QUERY );
com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xMyFrame(
GetFrame()->GetFrame().GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
if ( xOldFrame == xMyFrame )
bHidePopups = sal_False;
}
if ( bHidePopups )
{
//SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
SfxBindings *pBind = GetBindings();
while ( pBind )
{
pBind->HidePopupCtrls_Impl( sal_True );
pBind = pBind->GetSubBindings_Impl();
}
pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( sal_True, sal_False, 1 );
}
Flush();
}
void SfxDispatcher::DoParentDeactivate_Impl()
{
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->ParentDeactivate();
}
//--------------------------------------------------------------------
int SfxDispatcher::GetShellAndSlot_Impl
(
sal_uInt16 nSlot, // die zu suchende Slot-Id
SfxShell** ppShell, // die SfxShell, welche nSlot z.Zt. bedient
const SfxSlot** ppSlot, // der SfxSlot, welcher nSlot z.Zt. bedient
sal_Bool bOwnShellsOnly,
sal_Bool bModal, // trotz ModalMode
sal_Bool bRealSlot
)
/* [Beschreibung]
Diese Methode sucht im SfxDispatcher nach der <SfxShell>, von der
die Slot-Id nSlot zur Zeit bedient wird. Dazu wird der Dispatcher
zuvor geflusht.
[R"uckgabewert]
int sal_True
Die SfxShell wurde gefunden, ppShell und ppSlot
sind g"ultig.
sal_True
Die SfxShell wurde nicht gefunden, ppShell und ppSlot
sind ung"ultig.
*/
{
SFX_STACK(SfxDispatcher::GetShellAndSlot_Impl);
Flush();
SfxSlotServer aSvr;
if ( _FindServer(nSlot, aSvr, bModal) )
{
if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.Count() )
return sal_False;
*ppShell = GetShell(aSvr.GetShellLevel());
*ppSlot = aSvr.GetSlot();
if ( 0 == (*ppSlot)->GetExecFnc() && bRealSlot )
*ppSlot = (*ppShell)->GetInterface()->GetRealSlot(*ppSlot);
// Check only real slots as enum slots don't have an execute function!
if ( bRealSlot && ((0 == *ppSlot) || (0 == (*ppSlot)->GetExecFnc()) ))
return sal_False;
#ifdef DBG_UTILx
ByteString aMsg( nSlot );
aMsg += " found in ";
aMsg += (*ppShell)->GetInterface()->GetClassName();
DbgTrace( aMsg.GetBuffer() );
#endif
return sal_True;
}
#ifdef DBG_UTILx
ByteString aMsg( nSlot );
aMsg += " not found";
DbgTrace( aMsg.GetBuffer() );
#endif
return sal_False;
}
/*
struct Executer : public SfxHint
{
SfxRequest *pRequest;
const SfxSlot* pSlot;
sal_uInt16 nLevel;
Executer( SfxRequest* pReq, const SfxSlot* p, sal_uInt16 n )
: pRequest( pReq )
, pSlot(p)
, nLevel(n)
{}
~Executer()
{delete pRequest;}
};
*/
//--------------------------------------------------------------------
void SfxDispatcher::_Execute
(
SfxShell& rShell, // zu rufende <SfxShell>
const SfxSlot& rSlot, // zu rufender <SfxSlot>
SfxRequest& rReq, // auszuf"uhrende Funktion (Id und optional Parameter)
SfxCallMode eCallMode // synchron, asynchron oder wie beim Slot angegeben
)
/* [Beschreibung]
Diese Methode f"uhrt einen Request "uber einen gecachten <Slot-Server>
aus.
*/
{
DBG_MEMTEST();
DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
DBG_ASSERT( !pImp->aToDoStack.Count(), "unprepared InPlace _Execute" );
if ( IsLocked( rSlot.GetSlotId() ) )
return;
if ( (eCallMode & SFX_CALLMODE_ASYNCHRON) ||
( !(eCallMode & SFX_CALLMODE_SYNCHRON) &&
rSlot.IsMode(SFX_SLOT_ASYNCHRON) ) )
{
SfxDispatcher *pDispat = this;
while ( pDispat )
{
sal_uInt16 nShellCount = pDispat->pImp->aStack.Count();
for ( sal_uInt16 n=0; n<nShellCount; n++ )
{
if ( &rShell == pDispat->pImp->aStack.Top(n) )
{
if ( eCallMode & SFX_CALLMODE_RECORD )
rReq.AllowRecording( sal_True );
pDispat->pImp->xPoster->Post(new SfxRequest(rReq));
// pDispat->pImp->xPoster->Post(new Executer(new SfxRequest(rReq), &rSlot, n ));
return;
}
}
pDispat = pDispat->pImp->pParent;
}
}
else
Call_Impl( rShell, rSlot, rReq, SFX_CALLMODE_RECORD==(eCallMode&SFX_CALLMODE_RECORD) );
}
//--------------------------------------------------------------------
void MappedPut_Impl( SfxAllItemSet &rSet, const SfxPoolItem &rItem )
/* [Beschreibung]
Hilfsfunktion zum putten von rItem unter der im Pool des Item-Sets
rSet geltenden Which-Id.
*/
{
// mit ggf. gemappter Which-Id putten
const SfxItemPool *pPool = rSet.GetPool();
sal_uInt16 nWhich = rItem.Which();
#ifdef TF_POOLABLE
if ( pPool->IsSlot(nWhich) )
#else
if ( pPool->HasMap() && pPool->IsSlot(nWhich) )
#endif
nWhich = pPool->GetWhich(nWhich);
rSet.Put( rItem, nWhich );
}
//--------------------------------------------------------------------
#ifndef SFX_USE_BINDINGS
#define SFX_USE_BINDINGS 0x8000
#endif
sal_uInt16 SfxDispatcher::ExecuteFunction( sal_uInt16 nSlot, SfxPoolItem **pArgs,
sal_uInt16 nMode )
{
if ( !nMode )
nMode = pImp->nStandardMode;
// via Bindings/Interceptor? (dann ist der Returnwert nicht exakt)
sal_Bool bViaBindings = SFX_USE_BINDINGS == ( nMode & SFX_USE_BINDINGS );
nMode &= ~sal_uInt16(SFX_USE_BINDINGS);
if ( bViaBindings && GetBindings() )
return GetBindings()->Execute( nSlot, (const SfxPoolItem **) pArgs, nMode )
? EXECUTE_POSSIBLE
: EXECUTE_NO;
// sonst via Dispatcher
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
SfxCallMode eCall = SFX_CALLMODE_SYNCHRON;
sal_uInt16 nRet = EXECUTE_NO;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
{
// Ausf"uhrbarkeit vorher testen
if ( pSlot->IsMode( SFX_SLOT_FASTCALL ) ||
pShell->CanExecuteSlot_Impl( *pSlot ) )
nRet = EXECUTE_POSSIBLE;
if ( nMode == EXECUTEMODE_ASYNCHRON )
eCall = SFX_CALLMODE_ASYNCHRON;
else if ( nMode == EXECUTEMODE_DIALOGASYNCHRON && pSlot->IsMode( SFX_SLOT_HASDIALOG ) )
eCall = SFX_CALLMODE_ASYNCHRON;
else if ( pSlot->GetMode() & SFX_SLOT_ASYNCHRON )
eCall = SFX_CALLMODE_ASYNCHRON;
sal_Bool bDone = sal_False;
if ( pArgs && *pArgs )
{
SfxAllItemSet aSet( pShell->GetPool() );
for ( SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
MappedPut_Impl( aSet, **pArg );
SfxRequest aReq( nSlot, eCall, aSet );
_Execute( *pShell, *pSlot, aReq, eCall );
bDone = aReq.IsDone();
}
else
{
SfxRequest aReq( nSlot, eCall, pShell->GetPool() );
_Execute( *pShell, *pSlot, aReq, eCall );
bDone = aReq.IsDone();
}
}
return nRet;
}
sal_uInt16 SfxDispatcher::ExecuteFunction( sal_uInt16 nSlot, const SfxItemSet& rArgs,
sal_uInt16 nMode )
{
if ( !nMode )
nMode = pImp->nStandardMode;
/*
// at the moment not implemented
// via Bindings/Interceptor? (dann ist der Returnwert nicht exakt)
sal_Bool bViaBindings = SFX_USE_BINDINGS == ( nMode & SFX_USE_BINDINGS );
nMode &= ~sal_uInt16(SFX_USE_BINDINGS);
if ( bViaBindings && GetBindings() )
return GetBindings()->Execute( nSlot, rArgs, nMode )
? EXECUTE_POSSIBLE
: EXECUTE_NO;
*/
// sonst via Dispatcher
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
SfxCallMode eCall = SFX_CALLMODE_SYNCHRON;
sal_uInt16 nRet = EXECUTE_NO;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
{
// Ausf"uhrbarkeit vorher testen
if ( pSlot->IsMode( SFX_SLOT_FASTCALL ) ||
pShell->CanExecuteSlot_Impl( *pSlot ) )
nRet = EXECUTE_POSSIBLE;
if ( nMode == EXECUTEMODE_ASYNCHRON )
eCall = SFX_CALLMODE_ASYNCHRON;
else if ( nMode == EXECUTEMODE_DIALOGASYNCHRON && pSlot->IsMode( SFX_SLOT_HASDIALOG ) )
eCall = SFX_CALLMODE_ASYNCHRON;
else if ( pSlot->GetMode() & SFX_SLOT_ASYNCHRON )
eCall = SFX_CALLMODE_ASYNCHRON;
sal_Bool bDone = sal_False;
SfxRequest aReq( nSlot, eCall, rArgs );
_Execute( *pShell, *pSlot, aReq, eCall );
bDone = aReq.IsDone();
}
return nRet;
}
sal_uInt16 SfxDispatcher::GetSlotId( const String& rCommand )
{
const SfxSlot *pSlot = GetSlot( rCommand );
if ( pSlot )
return pSlot->GetSlotId();
return 0;
}
const SfxSlot* SfxDispatcher::GetSlot( const String& rCommand )
{
// Anzahl der Shells auf den verkettenten Dispatchern z"ahlen
Flush();
sal_uInt16 nTotCount = pImp->aStack.Count();
if ( pImp->pParent )
{
SfxDispatcher *pParent = pImp->pParent;
while ( pParent )
{
nTotCount = nTotCount + pParent->pImp->aStack.Count();
pParent = pParent->pImp->pParent;
}
}
const SfxSlot *pSlot=NULL;
sal_uInt16 nFirstShell = 0;
for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
{
SfxShell *pObjShell = GetShell(i);
SfxInterface *pIFace = pObjShell->GetInterface();
pSlot = pIFace->GetSlot( rCommand );
if ( pSlot )
return pSlot;
}
return 0;
}
//--------------------------------------------------------------------
int SfxExecuteItem::operator==( const SfxPoolItem& rItem ) const
{
SfxExecuteItem& rArg = (SfxExecuteItem& )rItem;
sal_uInt16 nCount = Count();
if( nCount != rArg.Count() )
return sal_False;
while( nCount -- )
if( *GetObject( nCount ) != *rArg.GetObject( nCount ) )
return sal_False;
return eCall == rArg.eCall;
}
//--------------------------------------------------------------------
SfxPoolItem* SfxExecuteItem::Clone( SfxItemPool* ) const
{
return new SfxExecuteItem( *this );
}
//--------------------------------------------------------------------
SfxExecuteItem::SfxExecuteItem( const SfxExecuteItem& rArg )
: SfxItemPtrArray(), SfxPoolItem( rArg ), nModifier( 0 )
{
eCall = rArg.eCall;
nSlot = rArg.nSlot;
sal_uInt16 nCount = rArg.Count();
for( sal_uInt16 nPos = 0; nPos < nCount; nPos++ )
Insert( rArg[ nPos ]->Clone(), nPos );
}
//--------------------------------------------------------------------
SfxExecuteItem::SfxExecuteItem(
sal_uInt16 nWhichId, sal_uInt16 nSlotP, SfxCallMode eModeP,
const SfxPoolItem* pArg1, ... ) :
SfxPoolItem( nWhichId ), nSlot( nSlotP ), eCall( eModeP ), nModifier( 0 )
{
va_list pVarArgs;
va_start( pVarArgs, pArg1 );
for ( const SfxPoolItem *pArg = pArg1; pArg;
pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
Insert( pArg->Clone(), Count() );
va_end(pVarArgs);
}
//--------------------------------------------------------------------
SfxExecuteItem::SfxExecuteItem(
sal_uInt16 nWhichId, sal_uInt16 nSlotP, SfxCallMode eModeP )
: SfxPoolItem( nWhichId ), nSlot( nSlotP ), eCall( eModeP ), nModifier( 0 )
{
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::Execute( const SfxExecuteItem& rItem )
{
const SfxPoolItem** pPtr = new const SfxPoolItem*[ rItem.Count() + 1 ];
for( sal_uInt16 nPos = rItem.Count(); nPos--; )
pPtr[ nPos ] = rItem.GetObject( nPos );
pPtr[ rItem.Count() ] = 0;
const SfxPoolItem* pRet = Execute(
rItem.GetSlot(), rItem.GetCallMode(), pPtr, rItem.GetModifier() );
delete [] (SfxPoolItem**)pPtr;
return pRet;
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::Execute(
sal_uInt16 nSlot,
SfxCallMode nCall,
SfxItemSet* pArgs,
SfxItemSet* pInternalArgs,
sal_uInt16 nModi)
{
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
SFX_CALLMODE_MODAL==(nCall&SFX_CALLMODE_MODAL) ) )
{
SfxAllItemSet aSet( pShell->GetPool() );
if ( pArgs )
{
SfxItemIter aIter(*pArgs);
for ( const SfxPoolItem *pArg = aIter.FirstItem();
pArg;
pArg = aIter.NextItem() )
MappedPut_Impl( aSet, *pArg );
}
SfxRequest aReq( nSlot, nCall, aSet );
if (pInternalArgs)
aReq.SetInternalArgs_Impl( *pInternalArgs );
aReq.SetModifier( nModi );
_Execute( *pShell, *pSlot, aReq, nCall );
return aReq.GetReturnValue();
}
return 0;
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::Execute
(
sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
const SfxPoolItem **pArgs, // 0-terminiertes C-Array von Parametern
sal_uInt16 nModi,
const SfxPoolItem **pInternalArgs // 0-terminiertes C-Array von Parametern
)
/* [Beschreibung]
Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
[R"uckgabewert]
const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
der Message-Loop g"ultiges SfxPoolItem,
welches den R"uckgabewert enth"alt.
Oder ein 0-Pointer, wenn die Funktion nicht
ausgef"uhrt wurde (z.B. Abbruch durch den
Benutzer).
*/
{
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
{
SfxRequest* pReq;
if ( pArgs && *pArgs )
{
SfxAllItemSet aSet( pShell->GetPool() );
for ( const SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
MappedPut_Impl( aSet, **pArg );
pReq = new SfxRequest( nSlot, eCall, aSet );
}
else
pReq = new SfxRequest( nSlot, eCall, pShell->GetPool() );
pReq->SetModifier( nModi );
if( pInternalArgs && *pInternalArgs)
{
SfxAllItemSet aSet( SFX_APP()->GetPool() );
for ( const SfxPoolItem **pArg = pInternalArgs; *pArg; ++pArg )
aSet.Put( **pArg );
pReq->SetInternalArgs_Impl( aSet );
}
_Execute( *pShell, *pSlot, *pReq, eCall );
const SfxPoolItem* pRet = pReq->GetReturnValue();
delete pReq; return pRet;
}
return 0;
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::Execute
(
sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
const SfxItemSet &rArgs // <SfxItemSet> mit Parametern
)
/* [Beschreibung]
Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
[R"uckgabewert]
const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
der Message-Loop g"ultiges SfxPoolItem,
welches den R"uckgabewert enth"alt.
Oder ein 0-Pointer, wenn die Funktion nicht
ausgef"uhrt wurde (z.B. Abbruch durch den
Benutzer).
*/
{
return Execute( nSlot, eCall, 0, rArgs );
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::Execute
(
sal_uInt16 nSlot,
SfxCallMode eCall,
sal_uInt16 nModi,
const SfxItemSet &rArgs
)
{
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
{
SfxAllItemSet aSet( pShell->GetPool() );
SfxItemIter aIter(rArgs);
for ( const SfxPoolItem *pArg = aIter.FirstItem();
pArg;
pArg = aIter.NextItem() )
MappedPut_Impl( aSet, *pArg );
SfxRequest aReq( nSlot, eCall, aSet );
aReq.SetModifier( nModi );
_Execute( *pShell, *pSlot, aReq, eCall );
return aReq.GetReturnValue();
}
return 0;
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::_Execute
(
sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
va_list pVarArgs, // Parameterliste ab 2. Parameter
const SfxPoolItem* pArg1 // erster Parameter
)
/* [Beschreibung]
Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
[R"uckgabewert]
const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
der Message-Loop g"ultiges SfxPoolItem,
welches den R"uckgabewert enth"alt.
Oder ein 0-Pointer, wenn die Funktion nicht
ausgef"uhrt wurde (z.B. Abbruch durch den
Benutzer).
*/
{
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
{
SfxAllItemSet aSet( pShell->GetPool() );
for ( const SfxPoolItem *pArg = pArg1;
pArg;
pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
MappedPut_Impl( aSet, *pArg );
SfxRequest aReq( nSlot, eCall, aSet );
_Execute( *pShell, *pSlot, aReq, eCall );
return aReq.GetReturnValue();
}
return 0;
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::Execute
(
sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
const SfxPoolItem* pArg1, // erster Parameter
... // 0-terminiertes Liste Parametern
)
/* [Beschreibung]
Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
[Anmerkung]
Die Parameter werden kopiert, k"onnen daher als Adresse von
Stack-Objekten "ubergeben werden.
[R"uckgabewert]
const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
der Message-Loop g"ultiges SfxPoolItem,
welches den R"uckgabewert enth"alt.
Oder ein 0-Pointer, wenn die Funktion nicht
ausgef"uhrt wurde (z.B. Abbruch durch den
Benutzer).
[Beispiel]
pDispatcher->Execute( SID_OPENDOCUMENT, SFX_CALLMODE_SYNCHRON,
&SfxStringItem( SID_FILE_NAME, "\\tmp\\temp.sdd" ),
&SfxStringItem( SID_FILTER_NAME, "StarDraw Presentation" ),
&SfxBoolItem( SID_DOC_READONLY, sal_False ),
0L );
*/
{
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
{
SfxAllItemSet aSet( pShell->GetPool() );
va_list pVarArgs;
va_start( pVarArgs, pArg1 );
for ( const SfxPoolItem *pArg = pArg1;
pArg;
pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
MappedPut_Impl( aSet, *pArg );
va_end(pVarArgs);
SfxRequest aReq( nSlot, eCall, aSet );
_Execute( *pShell, *pSlot, aReq, eCall );
return aReq.GetReturnValue();
}
return 0;
}
//--------------------------------------------------------------------
IMPL_LINK( SfxDispatcher, PostMsgHandler, SfxRequest*, pReq )
/* [Beschreibung]
Hilfsmethode zum Empfangen der asynchron auszuf"uhrenden <SfxRequest>s.
*/
{
DBG_MEMTEST();
DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
SFX_STACK(SfxDispatcher::PostMsgHandler);
// ist auch der Pool noch nicht gestorben?
// SfxRequest* pReq = pExec->pRequest;
if ( !pReq->IsCancelled() )
{
if ( !IsLocked(pReq->GetSlot()) )
{
Flush();
SfxSlotServer aSvr;
if ( _FindServer(pReq->GetSlot(), aSvr, HACK(x) sal_True ) )
// SfxShell *pShell = GetShell(pExec->nLevel);
// if ( pShell && pShell->GetInterface()->GetSlot( pExec->pSlot->GetSlotId() ) )
{
const SfxSlot *pSlot = aSvr.GetSlot();
SfxShell *pSh = GetShell(aSvr.GetShellLevel());
DBG( SfxApplication *pSfxApp = SFX_APP() );
DBG( pSfxApp->EnterAsynchronCall_Impl() );
// Wenn pSlot ein "Pseudoslot" f"ur Macros oder Verben ist, kann
// er im Call_Impl zerst"ort werden, also nicht mehr benutzen!
pReq->SetSynchronCall( sal_False );
Call_Impl( *pSh, *pSlot, *pReq, pReq->AllowsRecording() ); //! woher bRecord?
// Call_Impl( *pShell, *pExec->pSlot, *pReq, sal_True ); //! woher bRecord?
DBG( pSfxApp->LeaveAsynchronCall_Impl() );
}
// delete pExec;
}
else
{
// pImp->xPoster->Post(pExec);
if ( pImp->bLocked )
pImp->aReqArr.Insert( new SfxRequest(*pReq), pImp->aReqArr.Count() );
else
pImp->xPoster->Post(new SfxRequest(*pReq));
}
}
// else
// delete pExec;
delete pReq;
return 0;
}
//--------------------------------------------------------------------
void SfxDispatcher::SetMenu_Impl()
{
if ( pImp->pFrame )
{
SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
if ( pTop && pTop->GetBindings().GetDispatcher() == this )
{
SfxFrame& rFrame = pTop->GetFrame();
if ( rFrame.IsMenuBarOn_Impl() )
{
com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
if ( xPropSet.is() )
{
com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )));
aValue >>= xLayoutManager;
if ( xLayoutManager.is() )
{
rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
xLayoutManager->createElement( aMenuBarURL );
}
}
}
}
}
}
//--------------------------------------------------------------------
void SfxDispatcher::Update_Impl( sal_Bool bForce )
{
SFX_STACK(SfxDispatcher::Update_Impl);
Flush();
if ( !pImp->pFrame || pImp->bUILocked )
return;
SFX_APP(); // -Wall is this required???
SfxDispatcher *pDisp = this;
sal_Bool bUpdate = bForce;
while ( pDisp && pDisp->pImp->pFrame )
{
SfxWorkWindow *pWork = pDisp->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
if ( pAct == pDisp || pAct == this )
{
if ( !bUpdate )
bUpdate = !pDisp->pImp->bUpdated;
pDisp->pImp->bUpdated = sal_True;
}
else
break;
pDisp = pDisp->pImp->pParent;
}
if ( !bUpdate || pImp->pFrame->GetFrame().IsClosing_Impl() )
return;
SfxViewFrame* pTop = pImp->pFrame ? pImp->pFrame->GetTopViewFrame() : NULL;
sal_Bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
// keep own tools internally for collecting
GetBindings()->GetDispatcher()->pImp->bUpdated = sal_False;
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->DENTERREGISTRATIONS();
com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame = pBindings->GetActiveFrame();
com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, com::sun::star::uno::UNO_QUERY );
com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
if ( xPropSet.is() )
{
try
{
com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )) );
aValue >>= xLayoutManager;
}
catch ( com::sun::star::uno::Exception& )
{
}
}
if ( xLayoutManager.is() )
xLayoutManager->lock();
sal_Bool bIsIPActive = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
SfxInPlaceClient *pClient = pImp->pFrame ? pImp->pFrame->GetViewShell()->GetUIActiveClient() : NULL;
if ( bUIActive && /* !bIsIPActive && */ ( !pClient || !pClient->IsObjectUIActive() ) )
SetMenu_Impl();
SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
SfxWorkWindow *pTaskWin = pImp->pFrame->GetTopFrame().GetWorkWindow_Impl();
pTaskWin->ResetStatusBar_Impl();
SfxDispatcher *pDispat = this;
while ( pDispat )
{
SfxWorkWindow *pWork = pDispat->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
if ( pAct == pDispat || pAct == this )
{
pWork->ResetObjectBars_Impl();
pWork->ResetChildWindows_Impl();
}
pDispat = pDispat->pImp->pParent;
}
sal_Bool bIsActive = sal_False;
SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
pDispat = this;
while ( pActDispat && !bIsActive )
{
if ( pDispat == pActDispat )
bIsActive = sal_True;
pActDispat = pActDispat->pImp->pParent;
}
_Update_Impl( bUIActive, !bIsIPActive, bIsIPActive, pTaskWin );
if ( bUIActive || bIsActive )
pWorkWin->UpdateObjectBars_Impl();
if ( pBindings )
pBindings->DLEAVEREGISTRATIONS();
if ( xLayoutManager.is() )
xLayoutManager->unlock();
return;
}
void SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp, sal_Bool bIsIPOwner, SfxWorkWindow *pTaskWin )
{
SFX_APP();
SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
sal_Bool bIsActive = sal_False;
sal_Bool bIsTaskActive = sal_False;
SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
SfxDispatcher *pDispat = this;
while ( pActDispat && !bIsActive )
{
if ( pDispat == pActDispat )
bIsActive = sal_True;
pActDispat = pActDispat->pImp->pParent;
}
if ( pImp->pParent && !pImp->bQuiet /* && bUIActive */ )
pImp->pParent->_Update_Impl( bUIActive, bIsMDIApp, bIsIPOwner, pTaskWin );
for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
pImp->aObjBars[n].nResId = 0;
pImp->aChildWins.Remove(0, pImp->aChildWins.Count());
// bQuiet : own shells aren't considered for UI and SlotServer
// bNoUI: own Shells aren't considered fors UI
if ( pImp->bQuiet || pImp->bNoUI || (pImp->pFrame && pImp->pFrame->GetObjectShell()->IsPreview()) )
return;
sal_uInt32 nStatBarId=0;
SfxShell *pStatusBarShell = NULL;
SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() );
sal_uInt16 nTotCount = pImp->aStack.Count();
for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
{
SfxShell *pShell = GetShell( nShell-1 );
SfxInterface *pIFace = pShell->GetInterface();
// don't consider shells if "Hidden" oder "Quiet"
sal_Bool bReadOnlyShell = IsReadOnlyShell_Impl( nShell-1 );
sal_uInt16 nNo;
for ( nNo = 0; pIFace && nNo<pIFace->GetObjectBarCount(); ++nNo )
{
sal_uInt16 nPos = pIFace->GetObjectBarPos(nNo);
if ( bReadOnlyShell && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
continue;
// check wether toolbar needs activation of a special feature
sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
if ( nFeature && !pShell->HasUIFeature( nFeature ) )
continue;
// check for toolboxes that are exclusively for a viewer
if ( pImp->pFrame)
{
sal_Bool bViewerTbx = SFX_VISIBILITY_VIEWER == ( nPos & SFX_VISIBILITY_VIEWER );
SfxObjectShell* pSh = pImp->pFrame->GetObjectShell();
SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, sal_False );
sal_Bool bIsViewer = pItem && pItem->GetValue();
if ( bIsViewer != bViewerTbx )
continue;
}
// always register toolbars, allows to switch them on
sal_Bool bVisible = pIFace->IsObjectBarVisible(nNo);
if ( !bVisible )
nPos &= SFX_POSITION_MASK;
SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
rBar.nMode = nPos;
rBar.nResId = pIFace->GetObjectBarResId(nNo).GetId();
const String *pName = pIFace->GetObjectBarName(nNo);
if ( pName )
rBar.aName = *pName;
else
rBar.aName.Erase();
rBar.pIFace = pIFace;
if ( bUIActive || bIsActive )
{
pWorkWin->SetObjectBar_Impl(
nPos, rBar.nResId, rBar.pIFace, &rBar.aName );
}
if ( !bVisible )
rBar.nResId = 0;
}
for ( nNo=0; pIFace && nNo<pIFace->GetChildWindowCount(); nNo++ )
{
sal_uInt32 nId = pIFace->GetChildWindowId(nNo);
const SfxSlot *pSlot = pSlotPool->GetSlot( (sal_uInt16) nId );
DBG_ASSERT( pSlot, "Childwindow slot missing!");
if ( bReadOnlyShell )
{
// only show ChildWindows if their slot is allowed for readonly documents
if ( pSlot && !pSlot->IsMode( SFX_SLOT_READONLYDOC ) )
continue;
}
sal_uInt32 nFeature = pIFace->GetChildWindowFeature(nNo);
if ( nFeature && !pShell->HasUIFeature( nFeature ) )
continue;
// slot decides wether a ChildWindow is shown when document is OLE server or OLE client
sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
if( pSlot )
{
if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
{
if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
nMode |= SFX_VISIBILITY_CLIENT;
}
else
{
if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
nMode |= SFX_VISIBILITY_SERVER;
}
}
if ( bUIActive || bIsActive )
pWorkWin->SetChildWindowVisible_Impl( nId, sal_True, nMode );
if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
pImp->aChildWins.Insert( nId, pImp->aChildWins.Count());
}
if ( bIsMDIApp || bIsIPOwner )
{
sal_uInt32 nId = pIFace->GetStatusBarResId().GetId();
if ( nId )
{
nStatBarId = nId;
pStatusBarShell = pShell;
}
}
}
for ( sal_uInt16 nPos=0; nPos<SFX_OBJECTBAR_MAX; nPos++ )
{
SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos];
if ( rFixed.nResId )
{
SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos];
rBar = rFixed;
pWorkWin->SetObjectBar_Impl( rFixed.nMode,
rFixed.nResId, rFixed.pIFace, &rFixed.aName );
}
}
if ( pTaskWin && ( bIsMDIApp || bIsIPOwner ) )
{
SfxDispatcher *pActDispatcher = pTaskWin->GetBindings().GetDispatcher_Impl();
SfxDispatcher *pDispatcher = this;
while ( pActDispatcher && !bIsTaskActive )
{
if ( pDispatcher == pActDispatcher )
bIsTaskActive = sal_True;
pActDispatcher = pActDispatcher->pImp->pParent;
}
if ( bIsTaskActive && nStatBarId && pImp->pFrame )
{
// internal frames also may control statusbar
SfxBindings& rBindings = pImp->pFrame->GetBindings();
pImp->pFrame->GetFrame().GetWorkWindow_Impl()->SetStatusBar_Impl( nStatBarId, pStatusBarShell, rBindings );
}
}
}
//--------------------------------------------------------------------
void SfxDispatcher::FlushImpl()
/* [Beschreibung]
Hilfsmethode zum Ausf"uhren der ausstehenden Push- und Pop-Befehle.
*/
{
DBG_PROFSTART(SfxDispatcherFlush);
DBG_MEMTEST();
SFX_STACK(SfxDispatcher::FlushImpl);
DBG_TRACE("Flushing dispatcher!");
#ifdef DBG_UTIL
ByteString aMsg( "SfxDispatcher(" );
aMsg += ByteString::CreateFromInt64( (sal_uIntPtr) this );
aMsg += ")::Flush()";
#endif
pImp->aTimer.Stop();
if ( pImp->pParent )
pImp->pParent->Flush();
// if ( pImp->bQuiet )
// return;
pImp->bFlushing = !pImp->bFlushing;
if ( !pImp->bFlushing )
{
pImp->bFlushing = sal_True;
DBG_PROFSTOP(SfxDispatcherFlush);
//!
#ifdef DBG_UTIL_MESSEHACK_AUSKOMMENT
DBG_ERROR( "reentering SfxDispatcher::Flush()" );
aMsg += " reentering, aborted";
DbgTrace( aMsg.GetBuffer() );
#endif
return;
}
SfxApplication *pSfxApp = SFX_APP();
// in der 1. Runde den echten Stack 'um'bauen
SfxToDoStack_Impl aToDoCopy;
sal_Bool bModify = sal_False;
short nToDo;
for ( nToDo = pImp->aToDoStack.Count()-1; nToDo >= 0; --nToDo )
{
bModify = sal_True;
SfxToDo_Impl aToDo( pImp->aToDoStack.Top(nToDo) );
if ( aToDo.bPush )
{
// tats"aechlich pushen
DBG_ASSERT( !pImp->aStack.Contains( aToDo.pCluster ),
"pushed SfxShell already on stack" );
pImp->aStack.Push( aToDo.pCluster );
aToDo.pCluster->SetDisableFlags( pImp->nDisableFlags );
// die bewegte Shell merken
aToDoCopy.Push( aToDo );
}
else
{
// tats"aechlich poppen
SfxShell* pPopped = 0;
bool bFound = sal_False;
do
{
DBG_ASSERT( pImp->aStack.Count(), "popping from empty stack" );
pPopped = pImp->aStack.Pop();
pPopped->SetDisableFlags( 0 );
bFound = pPopped == aToDo.pCluster;
// die bewegte Shell merken
aToDoCopy.Push( SfxToDo_Impl( sal_False, aToDo.bDelete, sal_False, *pPopped) );
}
while ( aToDo.bUntil && !bFound );
DBG_ASSERT( bFound, "wrong SfxShell popped" );
}
if ( nToDo == 0 )
pImp->aToDoStack.Clear();
}
// ggf. Bindings invalidieren
if ( !pSfxApp->IsDowning() )
{
if ( bModify )
{
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
}
InvalidateBindings_Impl( bModify );
}
pImp->bFlushing = sal_False;
pImp->bUpdated = sal_False; // nicht nur bei bModify, falls Doc/Template-Config
bFlushed = sal_True;
DBG_TRACE("Successfully flushed dispatcher!");
// in der 2. Runde die Shells aktivieren und ggf. l"oschen
for ( nToDo = aToDoCopy.Count()-1; nToDo >= 0; --nToDo )
{
SfxToDo_Impl aToDo( aToDoCopy.Top(nToDo) );
if ( aToDo.bPush )
{
if ( pImp->bActive )
aToDo.pCluster->DoActivate_Impl(pImp->pFrame, sal_True);
}
else
if ( pImp->bActive )
aToDo.pCluster->DoDeactivate_Impl(pImp->pFrame, sal_True);
}
for ( nToDo = aToDoCopy.Count()-1; nToDo >= 0; --nToDo )
{
SfxToDo_Impl aToDo( aToDoCopy.Top(nToDo) );
if ( aToDo.bDelete ) delete aToDo.pCluster;
}
sal_Bool bAwakeBindings = aToDoCopy.Count() != 0;
if( bAwakeBindings )
aToDoCopy.Clear();
// Wenn bei Activate/Deactivate/Delete weitere Stackbewegungen erfolgt sind :
if (!bFlushed)
// falls jemand Push/Pop gerufen hat, wurde auch EnterReg gerufen!
FlushImpl();
if( bAwakeBindings && GetBindings() )
GetBindings()->DLEAVEREGISTRATIONS();
DBG_PROFSTOP(SfxDispatcherFlush);
for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
pImp->aFixedObjBars[n].nResId = 0;
#ifdef DBG_UTIL
aMsg += " done";
DbgTrace( aMsg.GetBuffer() );
#endif
}
//--------------------------------------------------------------------
void SfxDispatcher::SetSlotFilter
(
HACK(hier muss mal ein enum rein)
sal_Bool bEnable, /* sal_True:
nur angegebene Slots enablen,
alle anderen disablen
sal_False:
die angegebenen Slots disablen,
alle anderen zun"achst enablen
*/
sal_uInt16 nCount, // Anzahl der SIDs im folgenden Array
const sal_uInt16* pSIDs // sortiertes Array von 'nCount' SIDs
)
/* [Beschreibung]
Mit dieser Methode wird ein Filter gesetzt, mit dem gezielt Slots
enabled bzw. disabled werden k"onnen. Das "ubergebene Array mu\s
bis zum Dtor bzw. n"achsten <SetSlotFilter()> erhalten bleiben, es
wird nicht vom Dispatcher gel"oscht, es kann daher static sein.
In ReadOnly-Dokumenten kann man mit 'bEnable==2' quasi das ReadOnlyDoc
Flag von Slots "ubersteuern, dieser werden also wieder gefunden. Auf
andere Slots hat das dann keine Auswirkung.
[Beispiel]
gezieltes disablen der Slots 1, 2 und 3:
static sal_uInt16 __READONLY_DATA pSIDs[] = { 1, 2, 3 };
pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
nur die Slots 5, 6 und 7 zulassen:
static sal_uInt16 __READONLY_DATA pSIDs[] = { 5, 6, 7 };
pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
Filter ausschalten:
pDisp->SetSlotFilter();
*/
{
#ifdef DBG_UTIL
// Array "uberpr"ufen
for ( sal_uInt16 n = 1; n < nCount; ++n )
DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sortet" );
#endif
if ( pImp->pFilterSIDs )
pImp->pFilterSIDs = 0;
pImp->bFilterEnabling = bEnable;
pImp->nFilterCount = nCount;
pImp->pFilterSIDs = pSIDs;
GetBindings()->InvalidateAll(sal_True);
}
//--------------------------------------------------------------------
EXTERN_C
#if defined( PM2 ) && (!defined( CSET ) && !defined ( MTW ) && !defined( WTC ))
int _stdcall
#else
#ifdef WNT
int _cdecl
#else
int
#endif
#endif
SfxCompareSIDs_Impl( const void* pSmaller, const void* pBigger )
{
DBG_MEMTEST();
return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
}
//--------------------------------------------------------------------
sal_Bool SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
/* [Beschreibung]
Sucht 'nSID' in dem mit <SetSlotFilter()> gesetzten Filter und
liefert sal_True, falls die SID erlaubt ist, bzw. sal_False, falls sie
durch den Filter disabled ist.
[R"uckgabewert]
sal_Bool 0 => disabled
1 => enabled
2 => enabled even if ReadOnlyDoc
*/
{
// kein Filter?
if ( 0 == pImp->nFilterCount )
// => alle SIDs erlaubt
return sal_True;
// suchen
sal_Bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
sizeof(sal_uInt16), SfxCompareSIDs_Impl );
// even if ReadOnlyDoc
if ( 2 == pImp->bFilterEnabling )
return bFound ? 2 : 1;
// sonst je nach Negativ/Positiv Filter
return pImp->bFilterEnabling ? bFound : !bFound;
}
//--------------------------------------------------------------------
sal_Bool SfxDispatcher::_TryIntercept_Impl
(
sal_uInt16 nSlot, // zu suchende Slot-Id
SfxSlotServer& rServer, // zu f"uellende <SfxSlotServer>-Instanz
sal_Bool bSelf
)
{
// Eventuell geh"ort der parent auch zu einer Komponente
SfxDispatcher *pParent = pImp->pParent;
sal_uInt16 nLevels = pImp->aStack.Count();
while ( pParent && pParent->pImp->pFrame )
{
if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
{
// Components d"urfen intercepten
if ( pParent->_TryIntercept_Impl( nSlot, rServer, sal_True ) )
{
// Die eigenen Shells zum Shelllevel hinzuz"ahlen
rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
return sal_True;
}
else
// Keine weitere Interception
break;
}
else
nLevels = nLevels + pParent->pImp->aStack.Count();
pParent = pParent->pImp->pParent;
}
if ( bSelf )
{
// Die ComponentViewShell befragen
Flush();
SfxShell *pObjShell = GetShell(0);
SfxInterface *pIFace = pObjShell->GetInterface();
const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
if ( pSlot )
{
rServer.SetSlot(pSlot);
rServer.SetShellLevel(0);
#ifdef DBG_UTILx
String aMsg( nSlot );
aMsg += " intercepted";
DbgTrace( aMsg.GetBuffer() );
#endif
return sal_True;
}
}
return sal_False;
}
sal_Bool SfxDispatcher::_FindServer
(
sal_uInt16 nSlot, // zu suchende Slot-Id
SfxSlotServer& rServer, // zu f"uellnde <SfxSlotServer>-Instanz
sal_Bool bModal // trotz ModalMode
)
/* [Beschreibung]
Diese Hilfsmethode sucht den <Slot-Server>, der nSlot zur Zeit bedient.
Als Ergebnis wird rServer entsprechend gef"ullt.
Falls bekannt, kann das SfxInterface mitgegeben werden, von welchem
nSlot momentan bedient wird.
Vor der Suche nach nSlot wird der SfxDispatcher geflusht.
[R"uckgabewert]
sal_Bool sal_True
Der Slot wurde gefunden, rServer ist g"ultig.
sal_False
Der Slot wird momentan nicht bedient, rServer
ist ung"ultig.
*/
{
SFX_STACK(SfxDispatcher::_FindServer);
// Dispatcher gelockt? (SID_HELP_PI trotzdem durchlassen)
if ( IsLocked(nSlot) )
{
pImp->bInvalidateOnUnlock = sal_True;
return sal_False;
}
// Anzahl der Shells auf den verkettenten Dispatchern z"ahlen
Flush();
sal_uInt16 nTotCount = pImp->aStack.Count();
if ( pImp->pParent )
{
SfxDispatcher *pParent = pImp->pParent;
while ( pParent )
{
nTotCount = nTotCount + pParent->pImp->aStack.Count();
pParent = pParent->pImp->pParent;
}
}
// Verb-Slot?
if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
{
for ( sal_uInt16 nShell = 0;; ++nShell )
{
SfxShell *pSh = GetShell(nShell);
if ( pSh == NULL )
return false;
if ( pSh->ISA(SfxViewShell) )
{
const SfxSlot* pSlot = pSh->GetVerbSlot_Impl(nSlot);
if ( pSlot )
{
rServer.SetShellLevel(nShell);
rServer.SetSlot( pSlot );
return true;
}
}
}
}
// SID gegen gesetzten Filter pr"ufen
sal_uInt16 nSlotEnableMode=0;
if ( pImp->pFrame )
{
nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
if ( 0 == nSlotEnableMode )
return sal_False;
}
// im Quiet-Mode nur Parent-Dispatcher
if ( pImp->bQuiet )
{
if ( pImp->pParent )
{
sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
rServer.SetShellLevel
( rServer.GetShellLevel() + pImp->aStack.Count() );
return bRet;
}
else
return sal_False;
}
sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly );
// ( pImp->pFrame && pImp->pFrame->GetObjectShell() );
// pImp->pFrame->GetObjectShell()->IsLoading() );
// durch alle Shells der verketteten Dispatchern von oben nach unten suchen
#ifdef DBG_UTILx
String aStack( "Stack:" );
#endif
sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.Count() : 0;
for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
{
SfxShell *pObjShell = GetShell(i);
SfxInterface *pIFace = pObjShell->GetInterface();
const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
return sal_False;
if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
return sal_False;
if ( pSlot )
{
// Slot geh"ort zum Container?
bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
// Shell geh"ort zum Server?
// AppDispatcher oder IPFrame-Dispatcher
bool bIsServerShell = !pImp->pFrame || bIsInPlace;
// Nat"urlich sind ServerShell-Slots auch ausf"uhrbar, wenn sie auf
// einem Container-Dispatcher ohne IPClient ausgef"uhrt werden sollen.
if ( !bIsServerShell )
{
SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
}
// Shell geh"ort zum Container?
// AppDispatcher oder kein IPFrameDispatcher
bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
// Shell und Slot passen zusammen
if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
( !bIsContainerSlot && bIsServerShell ) ) )
pSlot = 0;
}
#ifdef DBG_UTILx
if ( pSlot )
{
String aMsg( nSlot );
aMsg += " found in ";
aMsg += pObjShell->GetInterface()->GetClassName();
DbgTrace( aMsg.GetBuffer() );
}
else
{
aStack += " ";
aStack += pObjShell->GetInterface()->GetClassName();
}
#endif
if ( pSlot && !IsAllowed( nSlot ) )
{
pSlot = NULL;
}
if ( pSlot )
{
rServer.SetSlot(pSlot);
rServer.SetShellLevel(i);
return sal_True;
}
}
#ifdef DBG_UTILx
String aMsg( nSlot );
aMsg += " not found in ";
aMsg += aStack;
DbgTrace( aMsg.GetBuffer() );
#endif
return sal_False;
}
sal_Bool SfxDispatcher::HasSlot_Impl( sal_uInt16 nSlot )
{
Flush();
sal_uInt16 nTotCount = pImp->aStack.Count();
if ( pImp->pParent && !pImp->pParent->pImp->pFrame )
{
// the last frame also uses the AppDispatcher
nTotCount = nTotCount + pImp->aStack.Count();
}
if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
{
// Verb-Slot?
for ( sal_uInt16 nShell = 0;; ++nShell )
{
SfxShell *pSh = GetShell(nShell);
if ( pSh == NULL )
return false;
if ( pSh->ISA(SfxViewShell) )
return true;
}
}
// SID gegen gesetzten Filter pr"ufen
sal_uInt16 nSlotEnableMode=0;
if ( pImp->pFrame )
{
nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
if ( 0 == nSlotEnableMode )
return sal_False;
}
// im Quiet-Mode nur Parent-Dispatcher
if ( pImp->bQuiet )
return sal_False;
sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly );
// ( pImp->pFrame && pImp->pFrame->GetObjectShell());
// pImp->pFrame->GetObjectShell()->IsLoading() );
for ( sal_uInt16 i=0 ; i < nTotCount; ++i )
{
SfxShell *pObjShell = GetShell(i);
SfxInterface *pIFace = pObjShell->GetInterface();
const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
return sal_False;
if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
return sal_False;
if ( pSlot )
{
// Slot geh"ort zum Container?
bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
// Shell geh"ort zum Server?
// AppDispatcher oder IPFrame-Dispatcher
bool bIsServerShell = !pImp->pFrame || bIsInPlace;
// Nat"urlich sind ServerShell-Slots auch ausf"uhrbar, wenn sie auf
// einem Container-Dispatcher ohne IPClient ausgef"uhrt werden sollen.
if ( !bIsServerShell )
{
SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
}
// Shell geh"ort zum Container?
// AppDispatcher oder kein IPFrameDispatcher
bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
// Shell und Slot passen zusammen
if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
( !bIsContainerSlot && bIsServerShell ) ) )
pSlot = 0;
}
if ( pSlot && !IsAllowed( nSlot ) )
pSlot = NULL;
if ( pSlot )
return sal_True;
}
return sal_False;
}
//--------------------------------------------------------------------
sal_Bool SfxDispatcher::_FillState
(
const SfxSlotServer& rSvr, // abzufragende <Slot-Server>
SfxItemSet& rState, // zu f"ullendes <SfxItemSet>
const SfxSlot* pRealSlot // ggf. der tats"achliche Slot
)
/* [Beschreibung]
Hilfsmethode zum Abfragen des Status des <Slot-Server>s rSvr.
In rState m"ussen die gew"unschten Slots-Ids (teilweise in Which-Ids
des betreffenden Pools umgewandelt) vorhanden sein.
Der SfxDispatcher wird vor der Abfrage geflusht.
*/
{
SFX_STACK(SfxDispatcher::_FillState);
DBG_PROFSTART(SfxDispatcherFillState);
const SfxSlot *pSlot = rSvr.GetSlot();
if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
{
pImp->bInvalidateOnUnlock = sal_True;
DBG_PROFSTOP(SfxDispatcherFillState);
return sal_False;
}
if ( pSlot )
{
DBG_ASSERT(bFlushed, "Dispatcher not flushed after retrieving slot servers!");
if ( !bFlushed )
return sal_False;
// Flush();
// Objekt ermitteln und Message an diesem Objekt aufrufen
SfxShell *pSh = GetShell(rSvr.GetShellLevel());
DBG_ASSERT(pSh, "ObjektShell nicht gefunden");
SfxStateFunc pFunc;
if (pRealSlot)
pFunc = pRealSlot->GetStateFnc();
else
pFunc = pSlot->GetStateFnc();
pSh->CallState( pFunc, rState );
#ifdef DBG_UTIL
// pr"ufen, ob IDL (SlotMap) und aktuelle Items "ubereinstimmen
if ( DbgIsAssertWarning() && rState.Count() )
{
SfxInterface *pIF = pSh->GetInterface();
SfxItemIter aIter( rState );
for ( const SfxPoolItem *pItem = aIter.FirstItem();
pItem;
pItem = aIter.NextItem() )
if ( !IsInvalidItem(pItem) && !pItem->ISA(SfxVoidItem) )
{
sal_uInt16 nSlotId = rState.GetPool()->GetSlotId(pItem->Which());
if ( !pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()) )
{
ByteString aMsg( "item-type unequal to IDL (=> no BASIC)" );
aMsg += "\nwith SID: ";
aMsg += ByteString::CreateFromInt32( nSlotId );
aMsg += "\nin ";
aMsg += pIF->GetClassName();
DbgOut( aMsg.GetBuffer(), DBG_OUT_ERROR, __FILE__, __LINE__);
}
}
}
#endif
DBG_PROFSTOP(SfxDispatcherFillState);
return sal_True;
}
DBG_PROFSTOP(SfxDispatcherFillState);
return sal_False;
}
//--------------------------------------------------------------------
const SfxPoolItem* SfxDispatcher::_Execute( const SfxSlotServer &rSvr )
/* [Beschreibung]
Diese Methode f"uhrt einen Request "uber einen gecachten <Slot-Server>
aus.
*/
{
const SfxSlot *pSlot = rSvr.GetSlot();
if ( IsLocked( pSlot->GetSlotId() ) )
return 0;
if ( pSlot )
{
Flush();
if ( pSlot->IsMode(SFX_SLOT_ASYNCHRON) )
//! ignoriert rSvr
{
SfxShell *pShell = GetShell( rSvr.GetShellLevel() );
SfxDispatcher *pDispat = this;
while ( pDispat )
{
sal_uInt16 nShellCount = pDispat->pImp->aStack.Count();
for ( sal_uInt16 n=0; n<nShellCount; n++ )
if ( pShell == pDispat->pImp->aStack.Top(n) )
{
pDispat->pImp->xPoster->Post(
new SfxRequest( pSlot->GetSlotId(),
SFX_CALLMODE_RECORD, pShell->GetPool() ) );
// pDispat->pImp->xPoster->Post(new Executer(
// new SfxRequest( pSlot->GetSlotId(),
// SFX_CALLMODE_RECORD, pShell->GetPool() ),
// pSlot, n ));
return 0;
}
}
}
else
{
// Objekt ermitteln und Message an diesem Objekt aufrufen
SfxShell *pSh = GetShell(rSvr.GetShellLevel());
SfxRequest aReq( pSlot->GetSlotId(), SFX_CALLMODE_RECORD, pSh->GetPool() );
if ( Call_Impl( *pSh, *pSlot, aReq, sal_True ) ) // von Bindings immer recorden
return aReq.GetReturnValue();
}
}
return 0;
}
//----------------------------------------------------------------------
void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId,
Window *pWin, const Point *pPos,
const SfxPoolItem *, ... )
{
ExecutePopup( nConfigId, pWin, pPos );
}
SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, const Point *pPos )
{
SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
sal_uInt16 nShLevel = 0;
SfxShell *pSh;
nShLevel=0;
if ( rDisp.pImp->bQuiet )
{
nConfigId = 0;
nShLevel = rDisp.pImp->aStack.Count();
}
Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
{
const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
{
return SfxPopupMenuManager::Popup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
}
}
return 0;
}
//----------------------------------------------------------------------
void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, Window *pWin, const Point *pPos )
{
SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
sal_uInt16 nShLevel = 0;
SfxShell *pSh;
/*
const SvVerbList *pVerbList = 0;
sal_uInt16 nMaxShellLevel = rDisp.pImp->aStack.Count();
for ( pSh = rDisp.GetShell(nShLevel);
pSh && nShLevel < nMaxShellLevel ;
++nShLevel, pSh = rDisp.GetShell(nShLevel) )
{
if ( pSh->GetVerbs() )
{
pVerbList = pSh->GetVerbs();
break;
}
}
*/
nShLevel=0;
if ( rDisp.pImp->bQuiet )
{
nConfigId = 0;
nShLevel = rDisp.pImp->aStack.Count();
}
Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
{
const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
{
//SfxPopupMenuManager aPop( rResId.GetId(), *rDisp.GetBindings() );
//aPop.SetResMgr(rResId.GetResMgr());
//aPop.AddClipboardFunctions();
//aPop.Initialize();
//if ( pVerbList && pVerbList->Count() )
// aPop.InsertVerbs(pVerbList);
//aPop.RemoveDisabledEntries();
//aPop.Execute( pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
SfxPopupMenuManager::ExecutePopup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
return;
}
}
}
//----------------------------------------------------------------------
void SfxDispatcher::ExecutePopup( const ResId &rId, Window *pWin, const Point *pPos )
{
Window *pWindow = pWin ? pWin : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
/*
SfxPopupMenuManager aPop( rId, *GetBindings() );
aPop.AddClipboardFunctions();
aPop.Initialize();
aPop.RemoveDisabledEntries();
aPop.Execute( pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
*/
SfxPopupMenuManager::ExecutePopup( rId, GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
}
//--------------------------------------------------------------------
void SfxDispatcher::Lock( sal_Bool bLock )
/* [Beschreibung]
Mit dieser Methode kann der SfxDispatcher gesperrt und freigegeben
werden. Ein gesperrter SfxDispatcher f"uhrt keine <SfxRequest>s mehr
aus und liefert keine Status-Informationen mehr. Er verh"alt sich
so als w"aren alle Slots disabled.
*/
{
SfxBindings* pBindings = GetBindings();
if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
{
if ( pBindings )
pBindings->InvalidateAll(sal_True);
pImp->bInvalidateOnUnlock = sal_False;
}
else if ( pBindings )
pBindings->InvalidateAll(sal_False);
pImp->bLocked = bLock;
if ( !bLock )
{
sal_uInt16 nCount = pImp->aReqArr.Count();
for ( sal_uInt16 i=0; i<nCount; i++ )
pImp->xPoster->Post( pImp->aReqArr[i] );
pImp->aReqArr.Remove( 0, nCount );
}
}
sal_uInt32 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
{
return pImp->aObjBars[nPos].nResId;
}
//--------------------------------------------------------------------
void SfxDispatcher::ResetObjectBars_Impl()
/* [Beschreibung]
Mit dieser Methode werden alle Objectbar-Anforderungen, die dieser
Dispatcher an das AppWindow hat, beseitigt.
*/
{
for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
pImp->aObjBars[n].nResId = 0;
pImp->aChildWins.Remove(0, pImp->aChildWins.Count());
}
//--------------------------------------------------------------------
void SfxDispatcher::DebugOutput_Impl() const
{
#ifdef DBG_UTIL
sal_uInt16 nOld = (sal_uInt16) DbgGetData()->nTraceOut;
DbgGetData()->nTraceOut = DBG_OUT_FILE;
if (bFlushed)
DBG_TRACE("Flushed");
if (pImp->bUpdated)
DBG_TRACE("Updated");
for ( sal_uInt16 nShell = pImp->aStack.Count(); nShell > 0; --nShell )
{
SfxShell *pShell = GetShell(nShell-1);
const SfxInterface *pIFace = pShell->GetInterface();
DBG_TRACE (pIFace->GetClassName());
}
DbgGetData()->nTraceOut = nOld;
#endif
}
void SfxDispatcher::LockUI_Impl( sal_Bool bLock )
{
sal_Bool bWasLocked = pImp->bUILocked;
pImp->bUILocked = bLock;
if ( !bLock && bWasLocked )
Update_Impl( sal_True );
}
//-------------------------------------------------------------------------
void SfxDispatcher::HideUI( sal_Bool bHide )
{
// if ( !bHide && pImp->bReadOnly )
// bHide = sal_True;
sal_Bool bWasHidden = pImp->bNoUI;
pImp->bNoUI = bHide;
if ( pImp->pFrame )
{
SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
if ( pTop && pTop->GetBindings().GetDispatcher() == this )
{
SfxFrame& rFrame = pTop->GetFrame();
if ( rFrame.IsMenuBarOn_Impl() )
{
com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
if ( xPropSet.is() )
{
com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )));
aValue >>= xLayoutManager;
if ( xLayoutManager.is() )
xLayoutManager->setVisible( !bHide );
}
}
}
}
if ( bHide != bWasHidden )
Update_Impl( sal_True );
}
void SfxDispatcher::SetReadOnly_Impl( sal_Bool bOn )
{
pImp->bReadOnly = bOn;
// pImp->bNoUI = bOn;
}
sal_Bool SfxDispatcher::GetReadOnly_Impl() const
{
return pImp->bReadOnly;
}
//-------------------------------------------------------------------------
void SfxDispatcher::SetQuietMode_Impl( sal_Bool bOn )
/* [Beschreibung]
Bei 'bOn' stellt sich dieser Dispatcher quasi tot und leitet alles
an den Parent-Dispatcher weiter.
*/
{
pImp->bQuiet = bOn;
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->InvalidateAll(sal_True);
}
//-------------------------------------------------------------------------
void SfxDispatcher::SetModalMode_Impl( sal_Bool bOn )
/* [Beschreibung]
Bei 'bOn' werden nur noch Slots des Parent-Dispatchers gefunden.
*/
{
pImp->bModal = bOn;
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->InvalidateAll(sal_True);
}
void SfxDispatcher::SetExecuteMode( sal_uInt16 nMode )
{
pImp->nStandardMode = nMode;
}
SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
{
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
{
rpState = pShell->GetSlotState(nSlot);
if ( !rpState )
return SFX_ITEM_DISABLED;
else
return SFX_ITEM_AVAILABLE;
}
return SFX_ITEM_DISABLED;
}
SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno::Any& rAny )
{
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSID, &pShell, &pSlot, sal_False, sal_False ) )
{
const SfxPoolItem* pItem( 0 );
pItem = pShell->GetSlotState( nSID );
if ( !pItem )
return SFX_ITEM_DISABLED;
else
{
::com::sun::star::uno::Any aState;
if ( !pItem->ISA(SfxVoidItem) )
{
sal_uInt16 nSubId( 0 );
SfxItemPool& rPool = pShell->GetPool();
sal_uInt16 nWhich = rPool.GetWhich( nSID );
if ( rPool.GetMetric( nWhich ) == SFX_MAPUNIT_TWIP )
nSubId |= CONVERT_TWIPS;
pItem->QueryValue( aState, (sal_uInt8)nSubId );
}
rAny = aState;
return SFX_ITEM_AVAILABLE;
}
}
return SFX_ITEM_DISABLED;
}
sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
{
sal_uInt16 nShellCount = pImp->aStack.Count();
if ( nShell < nShellCount )
{
SfxShell* pShell = pImp->aStack.Top( nShell );
if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
return sal_False;
else
return pImp->bReadOnly;
}
else if ( pImp->pParent )
return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
return sal_True;
}
// Ein dirty trick, um an die Methoden der private base class von
// SfxShellStack_Impl heranzukommen
class StackAccess_Impl : public SfxShellStack_Implarr_
{};
void SfxDispatcher::InsertShell_Impl( SfxShell& rShell, sal_uInt16 nPos )
{
Flush();
// Der cast geht, weil SfxShellStack_Impl keine eigenen member hat
((StackAccess_Impl*) (&pImp->aStack))->Insert( nPos, &rShell );
rShell.SetDisableFlags( pImp->nDisableFlags );
rShell.DoActivate_Impl(pImp->pFrame, sal_True);
if ( !SFX_APP()->IsDowning() )
{
pImp->bUpdated = sal_False;
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
InvalidateBindings_Impl(sal_True);
}
}
void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
{
Flush();
// Der cast geht, weil SfxShellStack_Impl keine eigenen member hat
StackAccess_Impl& rStack = *((StackAccess_Impl*) (&pImp->aStack));
sal_uInt16 nCount = rStack.Count();
for ( sal_uInt16 n=0; n<nCount; ++n )
{
if ( rStack[n] == &rShell )
{
rStack.Remove( n );
rShell.SetDisableFlags( 0 );
rShell.DoDeactivate_Impl(pImp->pFrame, sal_True);
break;
}
}
if ( !SFX_APP()->IsDowning() )
{
pImp->bUpdated = sal_False;
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
InvalidateBindings_Impl(sal_True);
}
}
sal_Bool SfxDispatcher::IsAllowed
(
sal_uInt16 nSlot
) const
/*
[Beschreibung]
Die Methode prueft, ob der Zugriff auf diese Schnittstelle erlaubt ist.
*/
{
if ( !pImp->pDisableList )
{
return sal_True;
}
// BinSearch in der DisableListe
SvUShorts& rList = *pImp->pDisableList;
sal_uInt16 nCount = rList.Count();
sal_uInt16 nLow = 0, nMid = 0, nHigh;
sal_Bool bFound = sal_False;
nHigh = nCount - 1;
while ( !bFound && nLow <= nHigh )
{
nMid = (nLow + nHigh) >> 1;
DBG_ASSERT( nMid < nCount, "bsearch ist buggy" );
int nDiff = (int) nSlot - (int) rList[nMid];
if ( nDiff < 0)
{
if ( nMid == 0 )
break;
nHigh = nMid - 1;
}
else if ( nDiff > 0 )
{
nLow = nMid + 1;
if ( nLow == 0 )
break;
}
else
bFound = sal_True;
}
#ifdef _DEBUG
// Slot in der Liste gefunden ?
sal_uInt16 nPos = bFound ? nMid : nLow;
DBG_ASSERT( nPos <= nCount, "" );
DBG_ASSERT( nPos == nCount || nSlot <= rList[nPos], "" );
DBG_ASSERT( nPos == 0 || nSlot > rList[nPos-1], "" );
DBG_ASSERT( ( (nPos+1) >= nCount ) || nSlot < rList[nPos+1], "" );
#endif
return !bFound;
}
void SfxDispatcher::InvalidateBindings_Impl( sal_Bool bModify )
{
// App-Dispatcher?
if ( IsAppDispatcher() )
{
for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst();
pFrame;
pFrame = SfxViewFrame::GetNext( *pFrame ) )
pFrame->GetBindings().InvalidateAll(bModify);
}
else
{
SfxDispatcher *pDisp = GetBindings()->GetDispatcher_Impl();
while ( pDisp )
{
if ( pDisp == this )
{
GetBindings()->InvalidateAll( bModify );
break;
}
pDisp = pDisp->pImp->pParent;
}
}
}
sal_Bool SfxDispatcher::IsUpdated_Impl() const
{
return pImp->bUpdated;
}
void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
{
pImp->nDisableFlags = nFlags;
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->SetDisableFlags( nFlags );
}
sal_uInt32 SfxDispatcher::GetDisableFlags() const
{
return pImp->nDisableFlags;
}
SfxModule* SfxDispatcher::GetModule() const
{
for ( sal_uInt16 nShell = 0;; ++nShell )
{
SfxShell *pSh = GetShell(nShell);
if ( pSh == NULL )
return 0;
if ( pSh->ISA(SfxModule) )
return (SfxModule*) pSh;
}
}