office-gobmx/sfx2/source/control/dispatch.cxx
Michael Stahl 3108a3dd38 sfx2: remove another DBG macro that arose from the grave
The callers in dispatch.cxx use methods that were removed by commit
a1ce4fb4f0 - not sure if this warning is
useful or not.

Change-Id: I8bb654de8e26c054318dd2037055a85d013c8bfa
2014-07-24 14:11:40 +02:00

2400 lines
73 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#include <config_features.h>
#include <algorithm>
#include <deque>
#include <vector>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <rtl/strbuf.hxx>
#include <sfx2/app.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/childwin.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/docfac.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/hintpost.hxx>
#include <sfx2/ipclient.hxx>
#include <sfx2/mnumgr.hxx>
#include <sfx2/module.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/request.hxx>
#include <sfx2/sfxhelp.hxx>
#include <sfx2/sfxuno.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <svl/eitem.hxx>
#include <svl/intitem.hxx>
#include <svl/itemiter.hxx>
#include <svl/itempool.hxx>
#include <svl/undo.hxx>
#include <svl/whiter.hxx>
#include <svtools/helpopt.hxx>
#include <vcl/wrkwin.hxx>
#include <appdata.hxx>
#include <sfxtypes.hxx>
#include <slotserv.hxx>
#include <workwin.hxx>
typedef std::vector<SfxShell*> SfxShellStack_Impl;
typedef std::vector<SfxRequest*> SfxRequestPtrArray;
struct SfxToDo_Impl
{
SfxShell* pCluster;
bool bPush;
bool bDelete;
bool bDeleted;
bool bUntil;
SfxToDo_Impl( bool bOpPush, bool bOpDelete, bool bOpUntil, SfxShell& rCluster )
: pCluster(&rCluster)
, bPush(bOpPush)
, bDelete(bOpDelete)
, bDeleted(false)
, bUntil(bOpUntil)
{}
};
struct SfxObjectBars_Impl
{
sal_uInt32 nResId; // Resource - and ConfigId of the Toolbox
sal_uInt16 nMode; // special visibility flags
OUString aName;
SfxInterface* pIFace;
SfxObjectBars_Impl() : nResId(0), nMode(0), pIFace(NULL) {}
};
struct SfxDispatcher_Impl
{
//When the dispatched is locked, SfxRequests accumulate in aReqArr for
//later dispatch when unlocked via Post
//The pointers are typically deleted in Post, only if we never get around
//to posting them do we delete the unposted requests.
SfxRequestPtrArray aReqArr;
~SfxDispatcher_Impl()
{
for (SfxRequestPtrArray::iterator aI = aReqArr.begin(), aEnd = aReqArr.end(); aI != aEnd; ++aI)
delete *aI;
}
const SfxSlotServer* pCachedServ1; // last called message
const SfxSlotServer* pCachedServ2; // penultimate called Message
SfxShellStack_Impl aStack; // active functionality
Timer aTimer; // for Flush
std::deque<SfxToDo_Impl> aToDoStack; // not processed Push/Pop
SfxViewFrame* pFrame; // NULL or associated Frame
SfxDispatcher* pParent; // AppDispatcher, NULL if possible
SfxHintPosterRef xPoster; // Execute asynchronous
bool bFlushing; // sal_True during Flush //?
bool bUpdated; // Update_Impl has run
bool bLocked; // No Execute
bool bInvalidateOnUnlock; // because someone asked
bool bActive; // not to be confused with set!
bool* pInCallAliveFlag; // view the Destructor Stack
SfxObjectBars_Impl aObjBars[SFX_OBJECTBAR_MAX];
SfxObjectBars_Impl aFixedObjBars[SFX_OBJECTBAR_MAX];
std::vector<sal_uInt32> aChildWins;
sal_uInt32 nEventId; // EventId UserEvent
bool bNoUI; // UI only from Parent Dispatcher
bool bReadOnly; // Document is ReadOnly
bool bQuiet; // Only use parent dispatcher
bool bModal; // Only slots from parent dispatcher
SfxSlotFilterState nFilterEnabling; // 1==filter enabled slots,
// 2==ReadOnlyDoc overturned
sal_uInt16 nFilterCount; // Number of SIDs in pFilterSIDs
const sal_uInt16* pFilterSIDs; // sorted Array of SIDs
sal_uInt32 nDisableFlags;
bool bFlushed;
std::deque< std::deque<SfxToDo_Impl> > aToDoCopyStack;
};
#define SFX_FLUSH_TIMEOUT 50
/** This method checks if the stack of the SfxDispatchers is flushed, or if
push- or pop- commands are pending.
*/
bool SfxDispatcher::IsFlushed() const
{
return pImp->bFlushed;
}
/** This method performs outstanding push- and pop- commands. For <SfxShell>s,
which are new on the stack, the <SfxShell::Activate(bool)> is invoked
with bMDI == sal_True, for SfxShells that are removed from the stack, the
<SfxShell::Deactivate(bool)> is invoked with bMDI == sal_True
*/
void SfxDispatcher::Flush()
{
if (!pImp->bFlushed) FlushImpl();
}
/** With this method, a <SfxShell> pushed on to the SfxDispatcher.
The SfxShell is first marked for push and a timer is set up.
First when the timer has couted down to zero the push
( <SfxDispatcher::Flush()> ) is actually performed and the
<SfxBindings> is invalidated. While the timer is counting down
the opposing push and pop commands on the same SfxShell are
leveled out.
*/
void SfxDispatcher::Push(SfxShell& rShell)
{
Pop( rShell, SFX_SHELL_PUSH );
}
/* This method checks whether a particular <SfxShell> instance is
on the SfxDispatcher.
@returns sal_True The SfxShell instance is on the SfxDispatcher.
sal_False The SfxShell instance is not on the SfxDispatcher.
*/
bool SfxDispatcher::IsActive(const SfxShell& rShell)
{
return CheckVirtualStack(rShell, true);
}
bool SfxDispatcher::IsLocked( sal_uInt16 ) const
/* [Description]
With this method it can be determined whether the SfxDispatcher is
locked or unlocked. A locked SfxDispatcher does not perform <SfxRequest>s
and no longer provides any status information. It behaves as if all the
slots are disabled.
The dispatcher is also marked as blocked, if all Dispatcher are locked
(<SfxApplication::LockDispatcher()>) or the associated top frame is in the
modal-mode and if the specified slot are handled as frame-specific
(ie, not served by the application).
*/
{
return pImp->bLocked;
}
bool SfxDispatcher::IsAppDispatcher() const
/* [Description]
With this method it can be determined if the SfxDispacher is the
applications dispatcher.
[Return value]
bool true it is the application dispatcher.
false it is a SfxViewFrame dispatcher.
*/
{
return !pImp->pFrame;
}
int SfxDispatcher::Call_Impl( SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, bool bRecord )
/* [Description]
Helper function to check whether a slot can be executed and
check the execution itself
*/
{
SFX_STACK(SfxDispatcher::Call_Impl);
// The slot may be called (meaning enabled)
if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
{
if ( GetFrame() )
{
// Recording may start
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("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() );
}
}
// Get all that is needed, because the slot may not have survived the
// Execute if it is a 'pseudo slot' for macros or verbs.
bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
// API-call parentheses and document-lock during the calls
{
// 'this' must respond in the Destructor
bool bThisDispatcherAlive = true;
bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
pImp->pInCallAliveFlag = &bThisDispatcherAlive;
SfxExecFunc pFunc = rSlot.GetExecFnc();
rShell.CallExec( pFunc, rReq );
// If 'this' is still alive
if ( bThisDispatcherAlive )
pImp->pInCallAliveFlag = pOldInCallAliveFlag;
else
{
if ( pOldInCallAliveFlag )
{
// also protect nested stack frames
*pOldInCallAliveFlag = false;
}
// do nothing after this object is dead
return rReq.IsDone() ? 1 : 0;
}
}
if ( rReq.IsDone() )
{
SfxBindings *pBindings = GetBindings();
// When AutoUpdate update immediately; "Pseudoslots" must not be
// Autoupdate!
if ( bAutoUpdate && pBindings )
{
const SfxSlot* pSlave = rSlot.GetLinkedSlot();
if (pSlave)
{
// When enum slots take any bound slave slot
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.reset(new SfxDispatcher_Impl);
pImp->bFlushed = true;
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
pImp->bFlushing = false;
pImp->bUpdated = false;
pImp->bLocked = false;
pImp->bActive = false;
pImp->pParent = NULL;
pImp->bNoUI = false;
pImp->bReadOnly = false;
pImp->bQuiet = false;
pImp->bModal = false;
pImp->pInCallAliveFlag = 0;
pImp->nFilterEnabling = SFX_SLOT_FILTER_DISABLED;
pImp->nFilterCount = 0;
pImp->pFilterSIDs = 0;
pImp->nDisableFlags = 0;
pImp->pParent = pParent;
pImp->bInvalidateOnUnlock = 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 )
/* [Description]
The constructor of the SfxDispatcher class places a stack of empty
<SfxShell> pointers. It is not initially locked and is considered flushed.
*/
{
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()
/* [Description]
The destructor of the SfxDispatcher class should not be called when the
SfxDispatcher instance is active. It may, however, still be a <SfxShell>
pointer on the stack.
*/
{
#ifdef DBG_UTIL
OStringBuffer sTemp("Delete Dispatcher ");
sTemp.append(reinterpret_cast<sal_Int64>(this));
OSL_TRACE("%s", sTemp.getStr());
DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
#endif
// So that no timer by Reschedule in PlugComm strikes the LeaveRegistrations
pImp->aTimer.Stop();
pImp->xPoster->SetEventHdl( Link() );
// Notify the stack varialbles in Call_Impl
if ( pImp->pInCallAliveFlag )
*pImp->pInCallAliveFlag = false;
// Get bindings and application
SfxApplication *pSfxApp = SfxGetpApp();
SfxBindings* pBindings = GetBindings();
// When not flushed, revive the bindings
if (pBindings && !pSfxApp->IsDowning() && !pImp->bFlushed)
pBindings->DLEAVEREGISTRATIONS();
// may unregister the bindings
while ( pBindings )
{
if ( pBindings->GetDispatcher_Impl() == this)
pBindings->SetDispatcher(0);
pBindings = pBindings->GetSubBindings_Impl();
}
}
void SfxDispatcher::Pop
(
SfxShell& rShell, /* the stack to take the SfxShell instance. */
sal_uInt16 nMode /* SFX_SHELL_POP_UNTIL
Also all 'rShell' of SfxShells are taken from the
stack.
SFX_SHELL_POP_DELETE
All SfxShells actually taken from the stack
will be deleted.
SFX_SHELL_PUSH (InPlace use only)
The Shell is pushed. */
)
/* [Description]
With this method, one or more <SfxShell> are poped from the SfxDispatcher.
The SfxShell is marked for popping and a timer is set up. Only when the
timer has reached the end, the pop is actually performed
( <SfxDispatcher::Flush()> ) and the <SfxBindings> is invalidated.
While the timer is running the opposing push and pop commands on one
SfxShell cancel each other out.
*/
{
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 = SfxGetpApp();
SAL_INFO(
"sfx.control",
"-SfxDispatcher(" << this << (bPush ? ")::Push(" : ")::Pop(")
<< (rShell.GetInterface()
? rShell.GetInterface()->GetClassName() : SAL_STREAM(&rShell))
<< (bDelete ? ") with delete" : ")")
<< (bUntil ? " (up to)" : ""));
// same shell as on top of the to-do stack?
if(pImp->aToDoStack.size() && pImp->aToDoStack.front().pCluster == &rShell)
{
// cancel inverse actions
if ( pImp->aToDoStack.front().bPush != bPush )
pImp->aToDoStack.pop_front();
else
{
DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
}
}
else
{
// Remember Action
pImp->aToDoStack.push_front( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
if (pImp->bFlushed)
{
OSL_TRACE("Unflushed dispatcher!");
pImp->bFlushed = false;
pImp->bUpdated = false;
// Put bindings to sleep
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->DENTERREGISTRATIONS();
}
}
if(!pSfxApp->IsDowning() && !pImp->aToDoStack.empty())
{
// No immediate update is requested
pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
pImp->aTimer.Start();
}
else
{
// but to do nothing
pImp->aTimer.Stop();
// Bindings may wake up again
if(pImp->aToDoStack.empty())
{
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->DLEAVEREGISTRATIONS();
}
}
}
IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
/* [Description]
This handler is called after <SfxDispatcher::Invalidate()> or after
changes on the stack (<SfxDispatcher::Push()> and <SfxDispatcher::Pop())
It flushes the Stack, if it is dirty, thus it actually excecutes the
pending Push and Pop commands.
*/
{
(void)pvoid; // unused
Flush();
Update_Impl();
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->StartUpdate_Impl(false);
return 0;
}
IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, bool bDeep )
/* [Description]
With this method it can be tested whether the <SfxShell> rShell is on the
stack, when it was flushed. This way the SfxDispatcher is not actually
flushed.
This method is intended among other things to make assertions possible
without the side effect of having to flush the SfxDispathcer.
*/
{
SFX_STACK(SfxDispatcher::CheckVirtualStack);
SfxShellStack_Impl aStack( pImp->aStack );
for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
{
if(i->bPush)
aStack.push_back(i->pCluster);
else
{
SfxShell* pPopped(NULL);
do
{
DBG_ASSERT( !aStack.empty(), "popping from empty stack" );
pPopped = aStack.back();
aStack.pop_back();
}
while(i->bUntil && pPopped != i->pCluster);
DBG_ASSERT(pPopped == i->pCluster, "popping unpushed SfxInterface");
}
}
bool bReturn;
if ( bDeep )
bReturn = std::find(aStack.begin(), aStack.end(), &rShell) != aStack.end();
else
bReturn = aStack.back() == &rShell;
return bReturn;
}
sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
/* [Description]
Determines the position of a given SfxShell in the stack of the dispatcher.
If possible this is flushed before.
[Return value]
sal_uInt16 == USRT_MAX
The SfxShell is not on this SfxDispatcher.
< USHRT_MAX
Position of the SfxShell on the Dispatcher
from the top count stating with 0.
*/
{
SFX_STACK(SfxDispatcher::GetShellLevel);
Flush();
for ( sal_uInt16 n = 0; n < pImp->aStack.size(); ++n )
if ( *( pImp->aStack.rbegin() + n ) == &rShell )
return n;
if ( pImp->pParent )
{
sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
if ( nRet == USHRT_MAX )
return nRet;
return nRet + pImp->aStack.size();
}
return USHRT_MAX;
}
SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
/* [Description]
Returns a pointer to the <SfxShell> which is at the position nIdx
(from the top, last pushed is 0) on the stack.
Thus the SfxDispatcher is not flushed.
Is the stack not deep enough a NULL-Pointer is returned.
*/
{
sal_uInt16 nShellCount = pImp->aStack.size();
if ( nIdx < nShellCount )
return *(pImp->aStack.rbegin() + nIdx);
else if ( pImp->pParent )
return pImp->pParent->GetShell( nIdx - nShellCount );
return 0;
}
SfxBindings* SfxDispatcher::GetBindings() const
/* [Description]
This method returns a pointer to the <SfxBinding> Instance on which the
SfxDispatcher is curretly bound. A SfxDispatcher is only bound to
the SfxBindings when it is <UI-aktiv>. If it is not UI-active,
a NULL-pointer is returned.
The returned pointer is only valid in the immediate context of the method
call.
*/
{
if ( pImp->pFrame )
return &pImp->pFrame->GetBindings();
else
return NULL;
}
SfxViewFrame* SfxDispatcher::GetFrame() const
/* [Description]
Returns a pointer to the <SfxViewFrame> instance, which belongs to
this SfxDispatcher. If it is about the application dispatcher,
a NULL-pointer is returned.
*/
{
return pImp->pFrame;
}
void SfxDispatcher::DoActivate_Impl( bool bMDI, SfxViewFrame* /* pOld */ )
/* [Description]
This method controls the activation of a dispatcher.
Since the application dispatcher is always active, either as a sub
dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
activated as a whole, instead only its individual <SfxShell>s at
<SfxDispatcher::Push(SfxShell&)>.
When activating a SfxDispatcher all of the SfxShells located on its stack
are called with the handler <SfxShell::Activate(bool)>, starting with
the lowest.
*/
{
SFX_STACK(SfxDispatcher::DoActivate);
if ( bMDI )
{
#ifdef DBG_UTIL
OStringBuffer sTemp("Activate Dispatcher ");
sTemp.append(reinterpret_cast<sal_Int64>(this));
OSL_TRACE("%s", sTemp.getStr());
DBG_ASSERT( !pImp->bActive, "Activation error" );
#endif
pImp->bActive = true;
pImp->bUpdated = false;
SfxBindings* pBindings = GetBindings();
if ( pBindings )
{
pBindings->SetDispatcher(this);
pBindings->SetActiveFrame( pImp->pFrame->GetFrame().GetFrameInterface() );
}
}
else
{
#ifdef DBG_UTIL
OStringBuffer sTemp("Non-MDI-Activate Dispatcher");
sTemp.append(reinterpret_cast<sal_Int64>(this));
OSL_TRACE("%s", sTemp.getStr());
#endif
}
if ( IsAppDispatcher() )
return;
for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
(*(pImp->aStack.rbegin() + i ))->DoActivate_Impl(pImp->pFrame, bMDI);
if ( bMDI && pImp->pFrame )
{
SfxBindings *pBind = GetBindings();
while ( pBind )
{
pBind->HidePopupCtrls_Impl( false );
pBind = pBind->GetSubBindings_Impl();
}
pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( false, false, 1 );
}
if(!pImp->aToDoStack.empty())
{
// No immediate update is requested
pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
pImp->aTimer.Start();
}
}
void SfxDispatcher::DoParentActivate_Impl()
{
for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
(*(pImp->aStack.rbegin() + i ))->ParentActivate();
}
void SfxDispatcher::DoDeactivate_Impl( bool bMDI, SfxViewFrame* pNew )
/* [Description]
This method controls the deactivation of a dispatcher.
Since the application dispatcher is always active, either as a sub
dispatcher of the <SfxViewFrame> dispatcher or as itself, it is never
deactivated as a whole, instead only its individual <SfxShell>s at
<SfxDispatcher::Pop(SfxShell&)>.
When deactivating a SfxDispatcher all of the SfxShells located on its stack
are called with the handler <SfxShell::Deactivate(bool)>, starting with
the lowest.
*/
{
SFX_STACK(SfxDispatcher::DoDeactivate);
SfxApplication *pSfxApp = SfxGetpApp();
if ( bMDI )
{
OSL_TRACE(OStringBuffer("Deactivate Dispatcher").append(reinterpret_cast<sal_Int64>(this)).getStr());
DBG_ASSERT( pImp->bActive, "Deactivate error" );
pImp->bActive = false;
if ( pImp->pFrame && !(pImp->pFrame->GetObjectShell()->IsInPlaceActive() ) )
{
SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
if ( pWorkWin )
{
for (size_t n=0; n<pImp->aChildWins.size();)
{
SfxChildWindow *pWin = pWorkWin->GetChildWindow_Impl( (sal_uInt16) ( pImp->aChildWins[n] & 0xFFFF ) );
if (!pWin || (pWin && pWin->GetAlignment() == SFX_ALIGN_NOALIGNMENT))
pImp->aChildWins.erase(pImp->aChildWins.begin()+n);
else
n++;
}
}
}
}
else {
OSL_TRACE(OStringBuffer("Non-MDI-DeActivate Dispatcher").append(reinterpret_cast<sal_Int64>(this)).getStr());
}
if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
return;
for ( sal_uInt16 i = 0; i < pImp->aStack.size(); ++i )
(*(pImp->aStack.rbegin() + i))->DoDeactivate_Impl(pImp->pFrame, bMDI);
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 = false;
}
if ( bHidePopups )
{
SfxBindings *pBind = GetBindings();
while ( pBind )
{
pBind->HidePopupCtrls_Impl( true );
pBind = pBind->GetSubBindings_Impl();
}
pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( true, false, 1 );
}
Flush();
}
void SfxDispatcher::DoParentDeactivate_Impl()
{
for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
(*(pImp->aStack.rbegin() + i))->ParentDeactivate();
}
int SfxDispatcher::GetShellAndSlot_Impl
(
sal_uInt16 nSlot, // the searchable Slot-Id
SfxShell** ppShell, // the SfxShell, which are currently handled
// the nSlot
const SfxSlot** ppSlot, // the SfxSlot, which are currently handled
// the nSlot
bool bOwnShellsOnly,
bool bModal, // ModalMode
bool bRealSlot
)
/* [Description]
This method searches in SfxDispatcher after <SfxShell> , from the Slot Id
nSlot currently being handled. For this, the dispatcher is first flushed.
[Return value]
int sal_True
The SfxShell was found, ppShell and ppSlot are valid.
sal_False
The SfxShell was not found, ppShell and ppSlot are invalid.
*/
{
SFX_STACK(SfxDispatcher::GetShellAndSlot_Impl);
Flush();
SfxSlotServer aSvr;
if ( _FindServer(nSlot, aSvr, bModal) )
{
if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.size() )
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;
return sal_True;
}
return sal_False;
}
void SfxDispatcher::_Execute
(
SfxShell& rShell, // to the calling <SfxShell>
const SfxSlot& rSlot, // to the calling <SfxSlot>
SfxRequest& rReq, // function to be performed
// (Id and optional parameters)
SfxCallMode eCallMode // Synchronously, asynchronously or as shown in
// the slot
)
/* [Description]
This method performs a request for a cached <Slot-Server>.
*/
{
DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
DBG_ASSERT( pImp->aToDoStack.empty(), "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.size();
for ( sal_uInt16 n=0; n<nShellCount; n++ )
{
if ( &rShell == *(pDispat->pImp->aStack.rbegin() + n) )
{
if ( eCallMode & SFX_CALLMODE_RECORD )
rReq.AllowRecording( true );
pDispat->pImp->xPoster->Post(new SfxRequest(rReq));
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 )
/* [Description]
Helper function to put from rItem below the Which-ID in the pool of the
Item Sets rSet.
*/
{
// Put with mapped Which-Id if possible
const SfxItemPool *pPool = rSet.GetPool();
sal_uInt16 nWhich = rItem.Which();
if ( SfxItemPool::IsSlot(nWhich) )
nWhich = pPool->GetWhich(nWhich);
rSet.Put( rItem, nWhich );
}
const SfxSlot* SfxDispatcher::GetSlot( const OUString& rCommand )
{
// Count the number of Shells on the linked Dispatcher
Flush();
sal_uInt16 nTotCount = pImp->aStack.size();
if ( pImp->pParent )
{
SfxDispatcher *pParent = pImp->pParent;
while ( pParent )
{
nTotCount = nTotCount + pParent->pImp->aStack.size();
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;
}
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, 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, // the Id of the executing function
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON
// or ..._SLOT
const SfxPoolItem **pArgs, // Zero teminated C-Array of Parameters
sal_uInt16 nModi,
const SfxPoolItem **pInternalArgs // Zero terminated C-Array of Parameters
)
/* [Description]
Method to excecute a <SfxSlot>s over the Slot-Id.
[Return value]
const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
though the Message-Loop, which contains the return
value.
Or a NULL-Pointer, when the function was not
executed (for example canceled by the user).
*/
{
if ( IsLocked(nSlot) )
return 0;
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, 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( SfxGetpApp()->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, // the Id of the executing function
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON or ..._SLOT
const SfxItemSet &rArgs // <SfxItemSet> with the parameters
)
/* [Description]
Method to excecute a <SfxSlot>s over the Slot-Id.
[Return value]
const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
though the Message-Loop, which contains the return
value.
Or a NULL-Pointer, when the function was not
executed (for example canceled by the user).
*/
{
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, 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, // the Id of the executing function
SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON or
// ..._SLOT
const SfxPoolItem* pArg1, // First parameter
... // Zero terminated list of parameters
)
/* [Description]
Method to excecute a <SfxSlot>s over the Slot-Id.
[Note]
The parameters are copied, can therefore be passed on as the address
of stack objects.
[Return value]
const SfxPoolItem* Pointer to the SfxPoolItem valid to the next run
though the Message-Loop, which contains the return
value.
Or a NULL-Pointer, when the function was not
executed (for example canceled by the user).
[Example]
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, 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 )
/* [Description]
Helper method to receive the asynchronously executed <SfxRequest>s.
*/
{
DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
SFX_STACK(SfxDispatcher::PostMsgHandler);
// Has also the Pool not yet died?
if ( !pReq->IsCancelled() )
{
if ( !IsLocked(pReq->GetSlot()) )
{
Flush();
SfxSlotServer aSvr;
if ( _FindServer(pReq->GetSlot(), aSvr, true ) ) // HACK(x), whatever that was supposed to mean
{
const SfxSlot *pSlot = aSvr.GetSlot();
SfxShell *pSh = GetShell(aSvr.GetShellLevel());
// When the pSlot is a "Pseudoslot" for macros or Verbs, it can
// be destroyed in the Call_Impl, thus do not use it anymore!
pReq->SetSynchronCall( false );
Call_Impl( *pSh, *pSlot, *pReq, pReq->AllowsRecording() ); //! why bRecord?
}
}
else
{
if ( pImp->bLocked )
pImp->aReqArr.push_back(new SfxRequest(*pReq));
else
pImp->xPoster->Post(new SfxRequest(*pReq));
}
}
delete pReq;
return 0;
}
void SfxDispatcher::SetMenu_Impl()
{
#if HAVE_FEATURE_DESKTOP
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("LayoutManager");
aValue >>= xLayoutManager;
if ( xLayoutManager.is() )
{
OUString aMenuBarURL( "private:resource/menubar/menubar" );
if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
xLayoutManager->createElement( aMenuBarURL );
}
}
}
}
}
#endif
}
void SfxDispatcher::Update_Impl( bool bForce )
{
SFX_STACK(SfxDispatcher::Update_Impl);
Flush();
if ( !pImp->pFrame )
return;
SfxGetpApp(); // -Wall is this required???
SfxDispatcher *pDisp = this;
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 = true;
}
else
break;
pDisp = pDisp->pImp->pParent;
}
if ( !bUpdate || pImp->pFrame->GetFrame().IsClosing_Impl() )
return;
SfxViewFrame* pTop = pImp->pFrame ? pImp->pFrame->GetTopViewFrame() : NULL;
bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
// keep own tools internally for collecting
GetBindings()->GetDispatcher()->pImp->bUpdated = false;
com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame;
SfxBindings* pBindings = GetBindings();
if (pBindings)
{
pBindings->DENTERREGISTRATIONS();
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("LayoutManager");
aValue >>= xLayoutManager;
}
catch (const com::sun::star::uno::Exception&)
{
}
}
if ( xLayoutManager.is() )
xLayoutManager->lock();
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;
}
bool bIsActive = false;
SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
pDispat = this;
while ( pActDispat && !bIsActive )
{
if ( pDispat == pActDispat )
bIsActive = 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( bool bUIActive, bool bIsMDIApp, bool bIsIPOwner, SfxWorkWindow *pTaskWin )
{
SfxGetpApp();
SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
bool bIsActive = false;
bool bIsTaskActive = false;
SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
SfxDispatcher *pDispat = this;
while ( pActDispat && !bIsActive )
{
if ( pDispat == pActDispat )
bIsActive = 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.clear();
// 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.size();
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"
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 whether 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)
{
bool bViewerTbx = SFX_VISIBILITY_VIEWER == ( nPos & SFX_VISIBILITY_VIEWER );
SfxObjectShell* pSh = pImp->pFrame->GetObjectShell();
SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, false );
bool bIsViewer = pItem && pItem->GetValue();
if ( bIsViewer != bViewerTbx )
continue;
}
// always register toolbars, allows to switch them on
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 OUString *pName = pIFace->GetObjectBarName(nNo);
if ( pName )
rBar.aName = *pName;
else
rBar.aName = "";
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 );
SAL_WARN_IF( !pSlot, "sfx.control", "Childwindow slot missing: " << nId );
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 whether 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, true, nMode );
if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
pImp->aChildWins.push_back( nId );
}
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 = 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()
/* [Description]
Helper method to execute the outstanding push and pop commands.
*/
{
SFX_STACK(SfxDispatcher::FlushImpl);
OSL_TRACE("Flushing dispatcher!");
pImp->aTimer.Stop();
if ( pImp->pParent )
pImp->pParent->Flush();
pImp->bFlushing = !pImp->bFlushing;
if ( !pImp->bFlushing )
{
pImp->bFlushing = true;
return;
}
SfxApplication *pSfxApp = SfxGetpApp();
// Re-build the true stack in the first round
std::deque<SfxToDo_Impl> aToDoCopy;
bool bModify = false;
for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
{
bModify = true;
if(i->bPush)
{
// Actually push
DBG_ASSERT( std::find(pImp->aStack.begin(), pImp->aStack.end(), i->pCluster) == pImp->aStack.end(),
"pushed SfxShell already on stack" );
pImp->aStack.push_back(i->pCluster);
i->pCluster->SetDisableFlags(pImp->nDisableFlags);
// Mark the moved shell
aToDoCopy.push_front(*i);
}
else
{
// Actually pop
SfxShell* pPopped = 0;
bool bFound = false;
do
{
DBG_ASSERT( !pImp->aStack.empty(), "popping from empty stack" );
pPopped = pImp->aStack.back();
pImp->aStack.pop_back();
pPopped->SetDisableFlags( 0 );
bFound = (pPopped == i->pCluster);
// Mark the moved Shell
aToDoCopy.push_front(SfxToDo_Impl(false, i->bDelete, false, *pPopped));
}
while(i->bUntil && !bFound);
DBG_ASSERT( bFound, "wrong SfxShell popped" );
}
}
pImp->aToDoStack.clear();
// Invalidate bindings, if possible
if ( !pSfxApp->IsDowning() )
{
if ( bModify )
{
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
}
InvalidateBindings_Impl( bModify );
}
pImp->bFlushing = false;
pImp->bUpdated = false; // not only when bModify, if Doc/Template-Config
pImp->bFlushed = true;
OSL_TRACE("Successfully flushed dispatcher!");
//fdo#70703 FlushImpl may call back into itself so use aToDoCopyStack to talk
//to outer levels of ourself. If DoActivate_Impl/DoDeactivate_Impl deletes
//an entry, then they will walk back up aToDoCopyStack and set outer
//levels's entries to bDeleted
pImp->aToDoCopyStack.push_back(aToDoCopy);
std::deque<SfxToDo_Impl>& rToDoCopy = pImp->aToDoCopyStack.back();
// Activate the Shells and possible delete them in the 2nd round
for(std::deque<SfxToDo_Impl>::reverse_iterator i = rToDoCopy.rbegin(); i != rToDoCopy.rend(); ++i)
{
if (i->bDeleted)
continue;
if (!pImp->bActive)
continue;
if (i->bPush)
i->pCluster->DoActivate_Impl(pImp->pFrame, true);
else
i->pCluster->DoDeactivate_Impl(pImp->pFrame, true);
}
aToDoCopy = pImp->aToDoCopyStack.back();
pImp->aToDoCopyStack.pop_back();
for(std::deque<SfxToDo_Impl>::reverse_iterator i = aToDoCopy.rbegin(); i != aToDoCopy.rend(); ++i)
{
if (i->bDelete && !i->bDeleted)
{
if (!pImp->aToDoCopyStack.empty())
{
//fdo#70703 if there is an outer FlushImpl then inform it that
//we have deleted this cluster
for (std::deque< std::deque<SfxToDo_Impl> >::iterator aI = pImp->aToDoCopyStack.begin();
aI != pImp->aToDoCopyStack.end(); ++aI)
{
std::deque<SfxToDo_Impl> &v = *aI;
for(std::deque<SfxToDo_Impl>::iterator aJ = v.begin(); aJ != v.end(); ++aJ)
{
if (aJ->pCluster == i->pCluster)
aJ->bDeleted = true;
}
}
}
delete i->pCluster;
}
}
bool bAwakeBindings = !aToDoCopy.empty();
if( bAwakeBindings )
aToDoCopy.clear();
// If more changes have occurred on the stach when
// Activate/Deactivate/Delete:
if (!pImp->bFlushed)
// If Push/Pop hs been called by someone, theb also EnterReg was called!
FlushImpl();
if( bAwakeBindings && GetBindings() )
GetBindings()->DLEAVEREGISTRATIONS();
for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
pImp->aFixedObjBars[n].nResId = 0;
SAL_INFO("sfx.control", "SfxDispatcher(" << this << ")::Flush() done");
}
void SfxDispatcher::SetSlotFilter
(
// HACK(hier muss mal ein enum rein) ???
SfxSlotFilterState nEnable, /* 1==true:
only enable specified slots,
disable all other
0==false:
disable specified slots,
first enable all other
*/
sal_uInt16 nCount, // Number of SIDs in the following Array
const sal_uInt16* pSIDs // sorted Array of 'nCount' SIDs
)
/* [Description]
With this method a filter set, the target slots can be enabled or disabled.
The passed array must be retained until the destructor or the next
<SetSlotFilter()>, it is not deleted from the dispatcher, so it can thus be
static.
In read-only documents the quasi ReadOnlyDoc Flag of slots can be
overturned by the use of 'bEnable == 2', so this will be displayed again.
On the other slots it has no effect.
[Example]
Targeted disabling of Slots 1, 2 and 3:
static sal_uInt16 const pSIDs[] = { 1, 2, 3 };
pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
only permit Slots 5, 6 and 7:
static sal_uInt16 const pSIDs[] = { 5, 6, 7 };
pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
Turn-off Filter:
pDisp->SetSlotFilter();
*/
{
#ifdef DBG_UTIL
// Check Array
for ( sal_uInt16 n = 1; n < nCount; ++n )
DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sorted" );
#endif
if ( pImp->pFilterSIDs )
pImp->pFilterSIDs = 0;
pImp->nFilterEnabling = nEnable;
pImp->nFilterCount = nCount;
pImp->pFilterSIDs = pSIDs;
GetBindings()->InvalidateAll(true);
}
extern "C"
#ifdef WNT
int _cdecl
#else
int
#endif
SfxCompareSIDs_Impl( const void* pSmaller, const void* pBigger )
{
return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
}
SfxSlotFilterState SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
/* [Description]
Searches for 'nSID' in the Filter set by <SetSlotFilter()> and
returns sal_True, if the SIDis allowed, or sal_False, if it is
disabled by the Filter.
[Return value]
int 0 => disabled
1 => enabled
2 => enabled even if ReadOnlyDoc
*/
{
// no filter?
if ( 0 == pImp->nFilterCount )
// => all SIDs allowed
return SFX_SLOT_FILTER_ENABLED;
// search
bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
sizeof(sal_uInt16), SfxCompareSIDs_Impl );
// even if ReadOnlyDoc
if ( SFX_SLOT_FILTER_ENABLED_READONLY == pImp->nFilterEnabling )
return bFound ? SFX_SLOT_FILTER_ENABLED_READONLY : SFX_SLOT_FILTER_ENABLED;
// Otherwise after Negative/Positive Filter
else if ( SFX_SLOT_FILTER_ENABLED == pImp->nFilterEnabling )
return bFound ? SFX_SLOT_FILTER_ENABLED : SFX_SLOT_FILTER_DISABLED;
else
return bFound ? SFX_SLOT_FILTER_DISABLED : SFX_SLOT_FILTER_ENABLED;
}
bool SfxDispatcher::_TryIntercept_Impl
(
sal_uInt16 nSlot, // Slot-Id to search for
SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
bool bSelf
)
{
// Maybe the parent is also belongs to a component
SfxDispatcher *pParent = pImp->pParent;
sal_uInt16 nLevels = pImp->aStack.size();
while ( pParent && pParent->pImp->pFrame )
{
if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
{
// Components may be intercepted
if ( pParent->_TryIntercept_Impl( nSlot, rServer, true ) )
{
// The own shells are added to the Shell Level
rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
return true;
}
else
// No further Interception
break;
}
else
nLevels = nLevels + pParent->pImp->aStack.size();
pParent = pParent->pImp->pParent;
}
if ( bSelf )
{
// Query the ComponentViewShell
Flush();
SfxShell *pObjShell = GetShell(0);
SfxInterface *pIFace = pObjShell->GetInterface();
const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
if ( pSlot )
{
rServer.SetSlot(pSlot);
rServer.SetShellLevel(0);
return true;
}
}
return false;
}
bool SfxDispatcher::_FindServer
(
sal_uInt16 nSlot, // Slot-Id to search for
SfxSlotServer& rServer, // <SfxSlotServer>-Instance to fill
bool bModal // Dispite ModalMode
)
/* [Description]
This helper method searches for the <Slot-Server> which currently serves
the nSlot. As the result, rServe is filled accordingly.
If known the SfxInterface which is currently served by nSlot can be
passed along.
The SfxDispatcher is flushed while searching for nSlot.
[Return value]
bool true
The Slot was found, rServer is valid.
false
The Slot is currently not served, rServer is invalid.
*/
{
SFX_STACK(SfxDispatcher::_FindServer);
// Dispatcher locked? (nevertheless let SID_HELP_PI through)
if ( IsLocked(nSlot) )
{
pImp->bInvalidateOnUnlock = true;
return false;
}
// Count the number of Shells in the linked dispatchers.
Flush();
sal_uInt16 nTotCount = pImp->aStack.size();
if ( pImp->pParent )
{
SfxDispatcher *pParent = pImp->pParent;
while ( pParent )
{
nTotCount = nTotCount + pParent->pImp->aStack.size();
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 check against set filter
SfxSlotFilterState nSlotEnableMode = SFX_SLOT_FILTER_DISABLED;
if ( pImp->pFrame )
{
nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
if ( SFX_SLOT_FILTER_DISABLED == nSlotEnableMode )
return false;
}
// In Quiet-Mode only Parent-Dispatcher
if ( pImp->bQuiet )
{
if ( pImp->pParent )
{
bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
rServer.SetShellLevel
( rServer.GetShellLevel() + pImp->aStack.size() );
return bRet;
}
else
return false;
}
bool bReadOnly = ( SFX_SLOT_FILTER_ENABLED_READONLY != nSlotEnableMode && pImp->bReadOnly );
// search through all the shells of the chained dispatchers
// from top to bottom
sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.size() : 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 false;
if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
return false;
if ( pSlot )
{
// Slot belongs to Container?
bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
// Shell belongs to Server?
// AppDispatcher or IPFrame-Dispatcher
bool bIsServerShell = !pImp->pFrame || bIsInPlace;
// Of course ShellServer-Slots are also executable even when it is
// excecuted on a container dispatcher without a IPClient.
if ( !bIsServerShell )
{
SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
}
// Shell belongs to Container?
// AppDispatcher or no IPFrameDispatcher
bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
// Shell and Slot match
if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
( !bIsContainerSlot && bIsServerShell ) ) )
pSlot = 0;
}
if ( pSlot )
{
rServer.SetSlot(pSlot);
rServer.SetShellLevel(i);
return true;
}
}
return false;
}
bool SfxDispatcher::_FillState
(
const SfxSlotServer& rSvr, // <Slot-Server> to query
SfxItemSet& rState, // <SfxItemSet> to be filled
const SfxSlot* pRealSlot // The actual Slot if possible
)
/* [Description]
Helper method to obtain the status of the <Slot-Server>s rSvr.
The required slots IDs (partly converted to Which-IDs of the pool)
must be present in rstate.
The SfxDispatcher is flushed before the query.
*/
{
SFX_STACK(SfxDispatcher::_FillState);
const SfxSlot *pSlot = rSvr.GetSlot();
if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
{
pImp->bInvalidateOnUnlock = true;
return false;
}
if ( pSlot )
{
DBG_ASSERT(pImp->bFlushed,
"Dispatcher not flushed after retrieving slot servers!");
if (!pImp->bFlushed)
return false;
// Determine the object and call the Message of this object
SfxShell *pSh = GetShell(rSvr.GetShellLevel());
DBG_ASSERT(pSh, "ObjectShell not found");
SfxStateFunc pFunc;
if (pRealSlot)
pFunc = pRealSlot->GetStateFnc();
else
pFunc = pSlot->GetStateFnc();
pSh->CallState( pFunc, rState );
#ifdef DBG_UTIL
// To examine the conformity of IDL (SlotMap) and current Items
if ( 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());
SAL_INFO_IF(
!pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()),
"sfx.control",
"item-type unequal to IDL (=> no BASIC) with SID: "
<< nSlotId << " in " << pIF->GetClassName());
}
}
}
#endif
return true;
}
return false;
}
SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, const Point *pPos )
{
SfxDispatcher &rDisp = *SfxGetpApp()->GetDispatcher_Impl();
sal_uInt16 nShLevel = 0;
SfxShell *pSh;
if ( rDisp.pImp->bQuiet )
{
nConfigId = 0;
nShLevel = rDisp.pImp->aStack.size();
}
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 = *SfxGetpApp()->GetDispatcher_Impl();
sal_uInt16 nShLevel = 0;
SfxShell *pSh;
if ( rDisp.pImp->bQuiet )
{
nConfigId = 0;
nShLevel = rDisp.pImp->aStack.size();
}
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::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::ExecutePopup( rId, GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
}
void SfxDispatcher::Lock( bool bLock )
/* [Description]
With this method the SfxDispatcher can be locked and released. A locked
SfxDispatcher does not perform <SfxRequest>s and does no longer provide
status information. It behaves as if all the slots were disabled.
*/
{
SfxBindings* pBindings = GetBindings();
if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
{
if ( pBindings )
pBindings->InvalidateAll(true);
pImp->bInvalidateOnUnlock = false;
}
else if ( pBindings )
pBindings->InvalidateAll(false);
pImp->bLocked = bLock;
if ( !bLock )
{
for(size_t i = 0; i < pImp->aReqArr.size(); ++i)
pImp->xPoster->Post(pImp->aReqArr[i]);
pImp->aReqArr.clear();
}
}
sal_uInt32 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
{
return pImp->aObjBars[nPos].nResId;
}
void SfxDispatcher::HideUI( bool bHide )
{
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("LayoutManager");
aValue >>= xLayoutManager;
if ( xLayoutManager.is() )
xLayoutManager->setVisible( !bHide );
}
}
}
}
if ( bHide != bWasHidden )
Update_Impl( true );
}
void SfxDispatcher::SetReadOnly_Impl( bool bOn )
{
pImp->bReadOnly = bOn;
}
bool SfxDispatcher::GetReadOnly_Impl() const
{
return pImp->bReadOnly;
}
void SfxDispatcher::SetQuietMode_Impl( bool bOn )
/* [Description]
With 'bOn' the Dispatcher is quasi dead and transfers everything to the
Parent-Dispatcher.
*/
{
pImp->bQuiet = bOn;
SfxBindings* pBindings = GetBindings();
if ( pBindings )
pBindings->InvalidateAll(true);
}
SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
{
SfxShell *pShell = 0;
const SfxSlot *pSlot = 0;
if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, false, 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, false, 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;
}
bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
{
sal_uInt16 nShellCount = pImp->aStack.size();
if ( nShell < nShellCount )
{
SfxShell* pShell = *( pImp->aStack.rbegin() + nShell );
if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
return false;
else
return pImp->bReadOnly;
}
else if ( pImp->pParent )
return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
return true;
}
void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
{
Flush();
sal_uInt16 nCount = pImp->aStack.size();
for ( sal_uInt16 n=0; n<nCount; ++n )
{
if ( pImp->aStack[n] == &rShell )
{
pImp->aStack.erase( pImp->aStack.begin() + n );
rShell.SetDisableFlags( 0 );
rShell.DoDeactivate_Impl(pImp->pFrame, true);
break;
}
}
if ( !SfxGetpApp()->IsDowning() )
{
pImp->bUpdated = false;
pImp->pCachedServ1 = 0;
pImp->pCachedServ2 = 0;
InvalidateBindings_Impl(true);
}
}
void SfxDispatcher::InvalidateBindings_Impl( 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;
}
}
}
bool SfxDispatcher::IsUpdated_Impl() const
{
return pImp->bUpdated;
}
void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
{
pImp->nDisableFlags = nFlags;
for ( SfxShellStack_Impl::reverse_iterator it = pImp->aStack.rbegin(); it != pImp->aStack.rend(); ++it )
(*it)->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;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */