sdk-examples/trunk/cpp/components/StatusbarController/ModifiedStatusbarController/StatusbarController.cxx (443 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 "StatusbarController.hxx"
#include "defines.hxx"
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/ui/ItemStyle.hpp>
#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
#include <functional>
#include <algorithm>
using namespace framework::statusbar_controller_modified;
using namespace com::sun::star;
using namespace com::sun::star::ui;
using namespace com::sun::star::util;
using namespace com::sun::star::uno;
using namespace com::sun::star::awt;
using namespace com::sun::star::frame;
using namespace com::sun::star::beans;
using rtl::OUString;
using com::sun::star::ucb::AlreadyInitializedException;
namespace
{
template< class MAP >
struct lcl_StatusListenerRemove
: public std::unary_function< typename MAP::value_type &, void >
{
private:
Reference< XStatusListener > xListener;
Reference< XURLTransformer > xURLTransformer;
public:
explicit lcl_StatusListenerRemove(
const Reference< XStatusListener > &rxListener,
const Reference< XURLTransformer > &rxTransformer )
: xListener( rxListener )
, xURLTransformer( rxTransformer ) {}
void operator()( typename MAP::value_type &rPair ) const
{
if ( !rPair.second.is() )
return;
try
{
URL aURL;
aURL.Complete = rPair.first;
xURLTransformer->parseStrict( aURL );
rPair.second->removeStatusListener( xListener, aURL );
}
catch ( ... )
{
}
rPair.second.clear();
}
};
}
StatusbarController::StatusbarController()
: StatusbarController_Base( m_aMutex )
, m_bInitialized( false )
, m_bOwnerDraw( false )
{
OSL_TRACE( "sbctlmodif::StatusbarController::StatusbarController" );
}
StatusbarController::~StatusbarController()
{
OSL_TRACE( "sbctlmodif::StatusbarController::~StatusbarController" );
}
void SAL_CALL
StatusbarController::dispose()
throw ( RuntimeException )
{
OSL_TRACE( "sbctlmodif::StatusbarController::dispose" );
osl::ClearableMutexGuard aGuard( m_aMutex );
ThrowIfDisposed();
UnbindListeners();
m_xFrame.clear();
m_xStatusbarWindow.clear();
m_xStatusbarItem.clear();
m_xURLTransformer.clear();
m_aListenerMap.clear();
aGuard.clear();
StatusbarController_Base::dispose();
}
void SAL_CALL
StatusbarController::initialize(
const Sequence< Any > &aArguments )
throw ( Exception, RuntimeException )
{
OSL_TRACE( "sbctlmodif::StatusbarController::initialize" );
bool bInitialized( true );
osl::ResettableMutexGuard aGuard( m_aMutex );
bInitialized = m_bInitialized;
aGuard.clear();
if ( bInitialized )
throw AlreadyInitializedException();
Reference< XFrame > xFrame;
Reference< XWindow > xStatusbarWindow;
Reference< XStatusbarItem > xStatusbarItem;
OUString sCommand, sModuleId;
bool bOwnerDraw( false );
PropertyValue aPropVal;
for ( const Any *pAny = aArguments.getConstArray(),
*pEnd = pAny + aArguments.getLength();
pAny != pEnd;
pAny++ )
{
if ( *pAny >>= aPropVal )
{
if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Frame" ) ) )
aPropVal.Value >>= xFrame;
else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CommandURL" ) ) )
aPropVal.Value >>= sCommand;
else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ParentWindow" ) ) )
aPropVal.Value >>= xStatusbarWindow;
else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ModuleName" ) ) )
aPropVal.Value >>= sModuleId;
else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StatusbarItem" ) ) )
aPropVal.Value >>= xStatusbarItem;
}
}
if ( ( xStatusbarItem->getStyle() & ItemStyle::OWNER_DRAW ) == ItemStyle::OWNER_DRAW )
bOwnerDraw = true;
aGuard.reset();
m_bInitialized = true;
m_xFrame = xFrame;
m_xStatusbarItem = xStatusbarItem;
m_xStatusbarWindow = xStatusbarWindow;
m_sModuleIdentifier = sModuleId;
m_sCommandURL = sCommand;
m_bOwnerDraw = bOwnerDraw;
if ( m_sCommandURL.getLength() )
m_aListenerMap.insert( URLToDispatchMap::value_type( m_sCommandURL, Reference< XDispatch >() ) );
aGuard.clear();
}
void StatusbarController::BindListeners()
{
OSL_TRACE( "sbctlmodif::StatusbarController::BindListeners" );
std::vector< Listener > aListeners;
Reference< XStatusListener > xStatusListener;
OUString sOwnCommandURL;
osl::ClearableMutexGuard aGuard( m_aMutex );
if ( !m_bInitialized )
return;
sOwnCommandURL = m_sCommandURL;
xStatusListener.set( static_cast< cppu::OWeakObject *>( this ), UNO_QUERY );
Reference< XDispatchProvider > xProvider( m_xFrame, UNO_QUERY );
if ( xProvider.is() )
{
for ( URLToDispatchMap::iterator it = m_aListenerMap.begin();
it != m_aListenerMap.end(); it++ )
{
Reference< XURLTransformer > xURLTransformer = GetURLTransformer();
URL aURL;
aURL.Complete = it->first;
xURLTransformer->parseStrict( aURL );
// remove
if ( it->second.is() )
{
try
{
it->second->removeStatusListener( xStatusListener, aURL );
}
catch ( ... ) {}
it->second.clear();
}
// requery
try
{
it->second = xProvider->queryDispatch( aURL, OUString(), 0 );
}
catch ( ... ) {}
aListeners.push_back( Listener( aURL, it->second ) );
}
}
aGuard.clear();
if ( !xStatusListener.is() || aListeners.empty() )
return;
for ( std::vector< Listener >::const_iterator it = aListeners.begin();
it != aListeners.end(); it++ )
{
try
{
if ( it->xDispatch.is() )
it->xDispatch->addStatusListener( xStatusListener, it->aURL );
else if ( it->aURL.Complete.equals( sOwnCommandURL ) )
{
// no dispatch for our own command,
// send an update with the Feature disabled
FeatureStateEvent aFeatureState;
aFeatureState.FeatureURL = it->aURL;
aFeatureState.IsEnabled = sal_False;
aFeatureState.Source = xStatusListener;
xStatusListener->statusChanged( aFeatureState );
}
}
catch ( ... )
{}
}
}
void StatusbarController::UnbindListeners()
{
OSL_TRACE( "sbctlmodif::StatusbarController::UnbindListeners" );
Reference< XStatusListener > xStatusListener( static_cast< cppu::OWeakObject * >( this ), UNO_QUERY );
std::for_each( m_aListenerMap.begin(),
m_aListenerMap.end(),
lcl_StatusListenerRemove< URLToDispatchMap >( xStatusListener, GetURLTransformer() ) );
}
bool StatusbarController::IsBound() const
{
OSL_TRACE( "sbctlmodif::StatusbarController::IsBound" );
osl::MutexGuard aGuard( m_aMutex );
if ( !m_bInitialized )
return false;
const URLToDispatchMap::const_iterator it = m_aListenerMap.find( m_sCommandURL );
return it != m_aListenerMap.end() && it->second.is();
}
Reference< XURLTransformer > StatusbarController::GetURLTransformer()
{
osl::MutexGuard aGuard( m_aMutex );
if ( !m_xURLTransformer.is() && m_xContext.is() )
{
try
{
m_xURLTransformer.set(
m_xContext->getServiceManager()->createInstanceWithContext(
OUSTR_SERVICENAME_URLTRANSFORMER, m_xContext ), UNO_QUERY_THROW );
}
catch ( ... )
{}
}
return m_xURLTransformer;
}
void
StatusbarController::ThrowIfDisposed( ) throw ( RuntimeException )
{
if ( rBHelper.bDisposed || rBHelper.bInDispose )
throw lang::DisposedException( );
}
void StatusbarController::Execute(
const Sequence< PropertyValue > &aArgs )
{
OSL_TRACE( "sbctlmodif::StatusbarController::Execute" );
Reference< XDispatch > xDispatch;
Reference< XURLTransformer > xURLParser;
OUString sCommandURL;
osl::ClearableMutexGuard aGuard( m_aMutex );
ThrowIfDisposed();
if ( m_bInitialized && m_sCommandURL.getLength() )
{
sCommandURL = m_sCommandURL;
xURLParser = GetURLTransformer();
const URLToDispatchMap::const_iterator it = m_aListenerMap.find( m_sCommandURL );
if ( it != m_aListenerMap.end() )
xDispatch = it->second;
}
aGuard.clear();
if ( xDispatch.is() && xURLParser.is() )
{
try
{
URL aURL;
aURL.Complete = sCommandURL;
xURLParser->parseStrict( aURL );
xDispatch->dispatch( aURL, aArgs );
}
catch ( ... )
{}
}
}
void StatusbarController::Execute(
const OUString &rCommandURL,
const Sequence< PropertyValue > &aArgs )
{
OSL_TRACE( "sbctlmodif::StatusbarController::Execute" );
Reference< XDispatch > xDispatch;
URL aURL;
aURL.Complete = rCommandURL;
osl::ClearableMutexGuard aGuard( m_aMutex );
ThrowIfDisposed();
if ( m_bInitialized && rCommandURL.getLength() )
{
Reference< XURLTransformer > xURLParser = GetURLTransformer();
xURLParser->parseStrict( aURL );
const URLToDispatchMap::const_iterator it = m_aListenerMap.find( rCommandURL );
if ( it != m_aListenerMap.end() )
xDispatch = it->second;
if ( !xDispatch.is() )
{
try
{
Reference< XDispatchProvider > xProvider( m_xFrame, UNO_QUERY_THROW );
xDispatch = xProvider->queryDispatch( aURL, OUString(), 0 );
}
catch ( ... )
{}
}
}
aGuard.clear();
if ( xDispatch.is() )
{
try
{
xDispatch->dispatch( aURL, aArgs );
}
catch ( ... )
{}
}
}
void StatusbarController::UpdateStatus()
{
BindListeners();
}
void StatusbarController::UpdateStatus( const OUString &rCommand )
{
OSL_TRACE( "sbctlmodif::StatusbarController::UpdateStatus" );
Reference< XStatusListener > xStatusListener;
Reference< XDispatch > xDispatch;
URL aURL;
aURL.Complete = rCommand;
osl::ClearableMutexGuard aGuard( m_aMutex );
Reference< XDispatchProvider > xProvider( m_xFrame, UNO_QUERY );
Reference< XURLTransformer > xURLParser = GetURLTransformer();
xStatusListener.set( static_cast< cppu::OWeakObject * >( this ), UNO_QUERY );
if ( !xProvider.is() || !xURLParser.is() )
return;
try
{
xURLParser->parseStrict( aURL );
xDispatch = xProvider->queryDispatch( aURL, OUString(), 0 );
}
catch ( ... )
{}
aGuard.clear();
if ( !xStatusListener.is() || !xDispatch.is() )
return;
try
{
xDispatch->addStatusListener( xStatusListener, aURL );
xDispatch->removeStatusListener( xStatusListener, aURL );
}
catch ( ... )
{}
}
void SAL_CALL
StatusbarController::statusChanged(
const FeatureStateEvent &aFeatureState )
throw ( RuntimeException )
{
OSL_TRACE( "sbctlmodif::StatusbarController::statusChanged" );
osl::ClearableMutexGuard aGuard( m_aMutex );
if ( rBHelper.bInDispose || rBHelper.bDisposed )
return;
if ( aFeatureState.FeatureURL.Complete.equals( m_sCommandURL ) )
{
OUString aStrVal;
if ( aFeatureState.State >>= aStrVal )
{
m_xStatusbarItem->setText( aStrVal );
}
else if ( !aFeatureState.State.hasValue() && !aFeatureState.IsEnabled )
m_xStatusbarItem->setText( OUString() );
}
}
void SAL_CALL
StatusbarController::disposing(
const lang::EventObject &Source )
throw ( RuntimeException )
{
OSL_TRACE( "sbctlmodif::StatusbarController::disposing" );
osl::MutexGuard aGuard( m_aMutex );
if ( rBHelper.bInDispose || rBHelper.bDisposed )
return;
Reference< XFrame > xFrame( Source.Source, UNO_QUERY );
if ( xFrame.is() )
{
if ( xFrame == m_xFrame )
m_xFrame.clear();
return;
}
Reference< XDispatch > xDispatch( Source.Source, UNO_QUERY );
if ( !xDispatch.is() )
return;
URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
while ( pIter != m_aListenerMap.end() )
{
// Compare references and release dispatch references if they are equal.
if ( xDispatch == pIter->second )
pIter->second.clear();
pIter++;
}
}
void SAL_CALL
StatusbarController::update()
throw ( RuntimeException )
{
OSL_TRACE( "sbctlmodif::StatusbarController::update" );
osl::ClearableMutexGuard aGuard( m_aMutex );
ThrowIfDisposed();
aGuard.clear();
BindListeners();
}
::sal_Bool SAL_CALL
StatusbarController::mouseButtonDown( const MouseEvent &/*aMouseEvent*/ )
throw ( RuntimeException )
{
return sal_False;
}
::sal_Bool SAL_CALL
StatusbarController::mouseMove( const MouseEvent &/*aMouseEvent*/ )
throw ( RuntimeException )
{
return sal_False;
}
::sal_Bool SAL_CALL
StatusbarController::mouseButtonUp( const MouseEvent &/*aMouseEvent*/ )
throw ( RuntimeException )
{
return sal_False;
}
void SAL_CALL
StatusbarController::command(
const Point &/*aPos*/,
::sal_Int32 /*nCommand*/,
::sal_Bool /*bMouseEvent*/,
const Any &/*aData*/ )
throw ( RuntimeException )
{
}
void SAL_CALL
StatusbarController::paint(
const Reference< XGraphics > &/*xGraphics*/,
const Rectangle &/*rOutputRectangle*/,
::sal_Int32 /*nStyle*/ )
throw ( RuntimeException )
{
}
void SAL_CALL
StatusbarController::click( const ::com::sun::star::awt::Point &/*aPos*/ )
throw ( RuntimeException )
{
}
void SAL_CALL
StatusbarController::doubleClick( const ::com::sun::star::awt::Point &/*aPos*/ )
throw ( RuntimeException )
{
OSL_TRACE( "sbctlmodif::StatusbarController::doubleClick" );
osl::ClearableMutexGuard aGuard( m_aMutex );
if ( rBHelper.bDisposed || rBHelper.bInDispose )
return;
aGuard.clear();
Sequence< PropertyValue > aDummyArgs;
Execute( aDummyArgs );
}