sdk-examples/trunk/cpp/components/StatusbarController/WordCountStatusbarController/DispatchPool.cxx (230 lines of code) (raw):
/**************************************************************
*
* 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.
*
*************************************************************/
#include "DispatchPool.hxx"
#include "WordCountDispatch.hxx"
#include "defines.hxx"
#include <com/sun/star/util/XCloseable.hpp>
#include <rtl/instance.hxx>
#include <rtl/ref.hxx>
#include <map>
#include <set>
#include <algorithm>
using namespace framework::statusbar_controller_wordcount;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
using namespace com::sun::star::frame;
using namespace com::sun::star::util;
using rtl::OUString;
namespace
{
struct CommandDispatchInfo
{
Reference< XComponent > Component;
Reference< XDispatch > Dispatch;
explicit CommandDispatchInfo(
const Reference< XComponent > &xComponent,
const Reference< XDispatch > &xDispatch )
: Component( xComponent )
, Dispatch( xDispatch ) {}
};
typedef std::map< OUString, CommandDispatchInfo > CommandDispatchMap;
typedef std::map< Reference< XFrame >, CommandDispatchMap > FrameDispatchMap;
struct StaticFrameDispatchMap
: public rtl::Static< FrameDispatchMap, StaticFrameDispatchMap > {};
struct TheDispatchPool
: public rtl::StaticWithInit< rtl::Reference< DispatchPool >, TheDispatchPool >
{
rtl::Reference< DispatchPool >
operator()()
{
OSL_TRACE( "sbctlwc: Initializing static DispatchPool" );
return rtl::Reference< DispatchPool >( DispatchPool::Create() );
}
};
typedef Reference< XDispatch > ( *CreateFnPtr )(
const Reference<XComponentContext> &,
const Reference<XFrame> &,
const OUString & );
typedef bool ( *SupportsURLFnPtr )( const URL &, const OUString & );
struct DispatchQueryInfo
{
SupportsURLFnPtr Supports;
CreateFnPtr Create;
DispatchQueryInfo( SupportsURLFnPtr supports, CreateFnPtr create )
: Supports( supports )
, Create( create ) {}
bool operator<( const DispatchQueryInfo &other ) const
{
return Supports < other.Supports;
}
};
typedef std::set< DispatchQueryInfo > DispatchInfoSet;
struct StaticDispatchInfoInit
{
DispatchInfoSet *operator()()
{
static DispatchInfoSet aSet;
lcl_InitSet( aSet );
return &aSet;
}
private:
void lcl_InitSet( DispatchInfoSet &aSet )
{
aSet.insert( DispatchInfoSet::value_type(
&WordCountDispatch::SupportsURL,
&WordCountDispatch::Create ) );
}
};
struct DispatchQuery :
public rtl::StaticAggregate< DispatchInfoSet, StaticDispatchInfoInit > {};
struct lcl_QueryDispatch
: public std::unary_function< const DispatchQueryInfo &, bool>
{
private:
URL aURL;
OUString sMoudleIdetnifier;
public:
lcl_QueryDispatch( const URL &_aURL, const OUString &_sModuleId )
: aURL( _aURL )
, sMoudleIdetnifier( _sModuleId ) {}
bool operator()( const DispatchQueryInfo &aDispatch )
{
return ( *aDispatch.Supports )( aURL, sMoudleIdetnifier );
}
};
}
DispatchPool *
DispatchPool::Create()
{
return new DispatchPool();
}
DispatchPool::DispatchPool()
: DipatchPool_Base()
{
OSL_TRACE( "sbctlwc::DispatchPool::DispatchPool" );
}
DispatchPool::~DispatchPool( )
{
OSL_TRACE( "sbctlwc::DispatchPool::~DispatchPool" );
}
void SAL_CALL
DispatchPool::disposing(
const EventObject &aEventObject )
throw ( RuntimeException )
{
Reference< XFrame > xFrame( aEventObject.Source, UNO_QUERY );
if ( xFrame.is( ) )
{
FrameDispatchMap &aMap = StaticFrameDispatchMap::get( );
FrameDispatchMap::iterator it = aMap.find( xFrame );
if ( it != aMap.end( ) )
{
OSL_TRACE( "sbctlwc::DispatchPool::disposing : disposing dispatches for this XFrame" );
CommandDispatchMap &aCmds = it->second;
for ( CommandDispatchMap::iterator aCmdIt = aCmds.begin( );
aCmdIt != aCmds.end( );
aCmdIt++ )
{
CommandDispatchInfo &aInfo = aCmdIt->second;
if ( aInfo.Dispatch.is( ) )
{
Reference< XComponent > xComp( aInfo.Dispatch, UNO_QUERY );
if ( xComp.is( ) )
xComp->dispose( );
aInfo.Dispatch.clear();
aInfo.Component.clear();
}
}
aCmds.clear();
aMap.erase( it );
}
return;
}
Reference< XComponent > xComponent( aEventObject.Source, UNO_QUERY );
if ( xComponent.is() )
{
FrameDispatchMap &aFrames = StaticFrameDispatchMap::get( );
for ( FrameDispatchMap::iterator aFrameIt = aFrames.begin();
aFrameIt != aFrames.end();
aFrameIt++ )
{
CommandDispatchMap &aCommands = aFrameIt->second;
for ( CommandDispatchMap::iterator aCommandIt = aCommands.begin();
aCommandIt != aCommands.end();
aCommandIt++ )
{
CommandDispatchInfo &aInfo = aCommandIt->second;
if ( xComponent == aInfo.Component )
{
Reference< XComponent> xComp( aInfo.Dispatch, UNO_QUERY );
if ( xComp.is( ) )
xComp->dispose( );
aInfo.Component.clear();
aInfo.Dispatch.clear();
aCommands.erase( aCommandIt );
}
}
}
}
}
Reference< XDispatch >
DispatchPool::GetDispatch(
const Reference<XComponentContext> &xContext,
const Reference< XFrame > &xFrame,
const URL &rCommandURL,
const rtl::OUString &rModuleIdentifier )
{
OSL_ENSURE( xFrame.is(), "DispatchPool::GetDispatch - no XFrame!" );
Reference< XDispatch > xRet;
const DispatchInfoSet &aDispatchInfo = *DispatchQuery::get();
const DispatchInfoSet::const_iterator pDispatchInfo = std::find_if(
aDispatchInfo.begin(),
aDispatchInfo.end(),
lcl_QueryDispatch( rCommandURL, rModuleIdentifier ) );
if ( pDispatchInfo == aDispatchInfo.end() )
return xRet;
Reference< XComponent > xComponent;
bool bListen = false;
const OUString sCommandURLPath = rCommandURL.Path;
const rtl::Reference<DispatchPool> &aPool = TheDispatchPool::get();
FrameDispatchMap &aFrames = StaticFrameDispatchMap::get();
Reference< XController > xController( xFrame->getController() );
if ( xController.is() )
{
Reference< XModel > xModel( xController->getModel(), UNO_QUERY );
if ( xModel.is() )
xComponent.set( xModel, UNO_QUERY );
else
xComponent.set( xController, UNO_QUERY );
}
FrameDispatchMap::iterator aFramesIt = aFrames.find( xFrame );
if ( aFramesIt == aFrames.end() )
{
CommandDispatchMap aMap;
xRet.set( ( * pDispatchInfo->Create )( xContext, xFrame, rModuleIdentifier ) );
aMap.insert( CommandDispatchMap::value_type( sCommandURLPath, CommandDispatchInfo( xComponent, xRet ) ) );
aFrames[xFrame] = aMap;
xFrame->addEventListener( aPool.get() );
bListen = true;
}
else
{
// found XFrame
CommandDispatchMap &aMap = aFramesIt->second;
// find Command
const CommandDispatchMap::iterator &aDispatchesIt = aMap.find( sCommandURLPath );
if ( aDispatchesIt == aMap.end() )
{
// Command not found, create dispatch
xRet.set( ( * pDispatchInfo->Create )( xContext, xFrame, rModuleIdentifier ) );
aMap.insert( CommandDispatchMap::value_type( sCommandURLPath, CommandDispatchInfo( xComponent, xRet ) ) );
bListen = true;
}
else
{
// command found
CommandDispatchInfo &aInfo = aDispatchesIt->second;
OSL_ENSURE( aInfo.Component == xComponent, "Requesting a dispatch for a different component!" );
xRet.set( aInfo.Dispatch );
}
}
if ( bListen )
{
xComponent->addEventListener( aPool.get() );
}
return xRet;
}