03a9f139bd
...and some further clean-up. Change-Id: If5dce53e382b56390c502d0d0d93fc06cbfe33ea
623 lines
19 KiB
C++
623 lines
19 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include <svtools/statusbarcontroller.hxx>
|
|
#include <com/sun/star/beans/PropertyValue.hpp>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/frame/XDispatchProvider.hpp>
|
|
#include <com/sun/star/lang/DisposedException.hpp>
|
|
#include <com/sun/star/frame/XLayoutManager.hpp>
|
|
#include <com/sun/star/util/URLTransformer.hpp>
|
|
#include <osl/mutex.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/window.hxx>
|
|
#include <vcl/status.hxx>
|
|
#include <svtools/imgdef.hxx>
|
|
#include <svtools/miscopt.hxx>
|
|
#include <toolkit/unohlp.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
|
|
using namespace ::cppu;
|
|
using namespace ::com::sun::star::awt;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::util;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::frame;
|
|
using namespace ::com::sun::star::frame;
|
|
|
|
namespace svt
|
|
{
|
|
|
|
StatusbarController::StatusbarController(
|
|
const Reference< XMultiServiceFactory >& rServiceManager,
|
|
const Reference< XFrame >& xFrame,
|
|
const ::rtl::OUString& aCommandURL,
|
|
unsigned short nID ) :
|
|
OWeakObject()
|
|
, m_bInitialized( sal_False )
|
|
, m_bDisposed( sal_False )
|
|
, m_nID( nID )
|
|
, m_xFrame( xFrame )
|
|
, m_xServiceManager( rServiceManager )
|
|
, m_aCommandURL( aCommandURL )
|
|
, m_aListenerContainer( m_aMutex )
|
|
{
|
|
}
|
|
|
|
StatusbarController::StatusbarController() :
|
|
OWeakObject()
|
|
, m_bInitialized( sal_False )
|
|
, m_bDisposed( sal_False )
|
|
, m_nID( 0 )
|
|
, m_aListenerContainer( m_aMutex )
|
|
{
|
|
}
|
|
|
|
StatusbarController::~StatusbarController()
|
|
{
|
|
}
|
|
|
|
Reference< XFrame > StatusbarController::getFrameInterface() const
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
return m_xFrame;
|
|
}
|
|
|
|
Reference< XURLTransformer > StatusbarController::getURLTransformer() const
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
if ( !m_xURLTransformer.is() && m_xServiceManager.is() )
|
|
{
|
|
m_xURLTransformer = com::sun::star::util::URLTransformer::create( ::comphelper::getComponentContext(m_xServiceManager) );
|
|
}
|
|
|
|
return m_xURLTransformer;
|
|
}
|
|
|
|
// XInterface
|
|
Any SAL_CALL StatusbarController::queryInterface( const Type& rType )
|
|
throw ( RuntimeException )
|
|
{
|
|
Any a = ::cppu::queryInterface(
|
|
rType ,
|
|
static_cast< XStatusbarController* >( this ),
|
|
static_cast< XStatusListener* >( this ),
|
|
static_cast< XEventListener* >( this ),
|
|
static_cast< XInitialization* >( this ),
|
|
static_cast< XComponent* >( this ),
|
|
static_cast< XUpdatable* >( this ));
|
|
|
|
if ( a.hasValue() )
|
|
return a;
|
|
|
|
return OWeakObject::queryInterface( rType );
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::acquire() throw ()
|
|
{
|
|
OWeakObject::acquire();
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::release() throw ()
|
|
{
|
|
OWeakObject::release();
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::initialize( const Sequence< Any >& aArguments )
|
|
throw ( Exception, RuntimeException )
|
|
{
|
|
bool bInitialized( true );
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
throw DisposedException();
|
|
|
|
bInitialized = m_bInitialized;
|
|
}
|
|
|
|
if ( !bInitialized )
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
m_bInitialized = sal_True;
|
|
|
|
PropertyValue aPropValue;
|
|
for ( int i = 0; i < aArguments.getLength(); i++ )
|
|
{
|
|
if ( aArguments[i] >>= aPropValue )
|
|
{
|
|
if ( aPropValue.Name == "Frame" )
|
|
aPropValue.Value >>= m_xFrame;
|
|
else if ( aPropValue.Name == "CommandURL" )
|
|
aPropValue.Value >>= m_aCommandURL;
|
|
else if ( aPropValue.Name == "ServiceManager" )
|
|
aPropValue.Value >>= m_xServiceManager;
|
|
else if ( aPropValue.Name == "ParentWindow" )
|
|
aPropValue.Value >>= m_xParentWindow;
|
|
else if ( aPropValue.Name == "Identifier" )
|
|
aPropValue.Value >>= m_nID;
|
|
}
|
|
}
|
|
|
|
if ( !m_aCommandURL.isEmpty() )
|
|
m_aListenerMap.insert( URLToDispatchMap::value_type( m_aCommandURL, Reference< XDispatch >() ));
|
|
}
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::update()
|
|
throw ( RuntimeException )
|
|
{
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
if ( m_bDisposed )
|
|
throw DisposedException();
|
|
}
|
|
|
|
// Bind all registered listeners to their dispatch objects
|
|
bindListener();
|
|
}
|
|
|
|
// XComponent
|
|
void SAL_CALL StatusbarController::dispose()
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
if ( m_bDisposed )
|
|
throw DisposedException();
|
|
}
|
|
|
|
com::sun::star::lang::EventObject aEvent( xThis );
|
|
m_aListenerContainer.disposeAndClear( aEvent );
|
|
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
|
|
Reference< XURLTransformer > xURLTransformer = getURLTransformer();
|
|
URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
|
|
com::sun::star::util::URL aTargetURL;
|
|
while ( pIter != m_aListenerMap.end() )
|
|
{
|
|
try
|
|
{
|
|
Reference< XDispatch > xDispatch( pIter->second );
|
|
aTargetURL.Complete = pIter->first;
|
|
xURLTransformer->parseStrict( aTargetURL );
|
|
|
|
if ( xDispatch.is() && xStatusListener.is() )
|
|
xDispatch->removeStatusListener( xStatusListener, aTargetURL );
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
|
|
++pIter;
|
|
}
|
|
|
|
// clear hash map
|
|
m_aListenerMap.clear();
|
|
|
|
// release references
|
|
m_xURLTransformer.clear();
|
|
m_xServiceManager.clear();
|
|
m_xFrame.clear();
|
|
m_xParentWindow.clear();
|
|
|
|
m_bDisposed = sal_True;
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::addEventListener( const Reference< XEventListener >& xListener )
|
|
throw ( RuntimeException )
|
|
{
|
|
m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::removeEventListener( const Reference< XEventListener >& aListener )
|
|
throw ( RuntimeException )
|
|
{
|
|
m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), aListener );
|
|
}
|
|
|
|
// XEventListener
|
|
void SAL_CALL StatusbarController::disposing( const EventObject& Source )
|
|
throw ( RuntimeException )
|
|
{
|
|
Reference< XInterface > xSource( Source.Source );
|
|
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
return;
|
|
|
|
URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
|
|
while ( pIter != m_aListenerMap.end() )
|
|
{
|
|
// Compare references and release dispatch references if they are equal.
|
|
Reference< XInterface > xIfac( pIter->second, UNO_QUERY );
|
|
if ( xSource == xIfac )
|
|
pIter->second.clear();
|
|
++pIter;
|
|
}
|
|
|
|
Reference< XInterface > xIfac( m_xFrame, UNO_QUERY );
|
|
if ( xIfac == xSource )
|
|
m_xFrame.clear();
|
|
}
|
|
|
|
// XStatusListener
|
|
void SAL_CALL StatusbarController::statusChanged( const FeatureStateEvent& Event )
|
|
throw ( RuntimeException )
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
return;
|
|
|
|
Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow );
|
|
if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR && m_nID != 0 )
|
|
{
|
|
rtl::OUString aStrValue;
|
|
StatusBar* pStatusBar = (StatusBar *)pWindow;
|
|
|
|
if ( Event.State >>= aStrValue )
|
|
pStatusBar->SetItemText( m_nID, aStrValue );
|
|
else if ( !Event.State.hasValue() )
|
|
pStatusBar->SetItemText( m_nID, String() );
|
|
}
|
|
}
|
|
|
|
// XStatusbarController
|
|
::sal_Bool SAL_CALL StatusbarController::mouseButtonDown(
|
|
const ::com::sun::star::awt::MouseEvent& )
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return sal_False;
|
|
}
|
|
|
|
::sal_Bool SAL_CALL StatusbarController::mouseMove(
|
|
const ::com::sun::star::awt::MouseEvent& )
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return sal_False;
|
|
}
|
|
|
|
::sal_Bool SAL_CALL StatusbarController::mouseButtonUp(
|
|
const ::com::sun::star::awt::MouseEvent& )
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return sal_False;
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::command(
|
|
const ::com::sun::star::awt::Point&,
|
|
::sal_Int32,
|
|
::sal_Bool,
|
|
const ::com::sun::star::uno::Any& )
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::paint(
|
|
const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >&,
|
|
const ::com::sun::star::awt::Rectangle&,
|
|
::sal_Int32,
|
|
::sal_Int32 )
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::click()
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
}
|
|
|
|
void SAL_CALL StatusbarController::doubleClick() throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
return;
|
|
|
|
Sequence< PropertyValue > aArgs;
|
|
execute( aArgs );
|
|
}
|
|
|
|
void StatusbarController::addStatusListener( const rtl::OUString& aCommandURL )
|
|
{
|
|
Reference< XDispatch > xDispatch;
|
|
Reference< XStatusListener > xStatusListener;
|
|
com::sun::star::util::URL aTargetURL;
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
URLToDispatchMap::iterator pIter = m_aListenerMap.find( aCommandURL );
|
|
|
|
// Already in the list of status listener. Do nothing.
|
|
if ( pIter != m_aListenerMap.end() )
|
|
return;
|
|
|
|
// Check if we are already initialized. Implementation starts adding itself as status listener when
|
|
// intialize is called.
|
|
if ( !m_bInitialized )
|
|
{
|
|
// Put into the boost::unordered_map of status listener. Will be activated when initialized is called
|
|
m_aListenerMap.insert( URLToDispatchMap::value_type( aCommandURL, Reference< XDispatch >() ));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Add status listener directly as intialize has already been called.
|
|
Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
|
|
if ( m_xServiceManager.is() && xDispatchProvider.is() )
|
|
{
|
|
Reference< XURLTransformer > xURLTransformer = getURLTransformer();
|
|
aTargetURL.Complete = aCommandURL;
|
|
xURLTransformer->parseStrict( aTargetURL );
|
|
xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
|
|
|
|
xStatusListener = Reference< XStatusListener >( static_cast< OWeakObject* >( this ), UNO_QUERY );
|
|
URLToDispatchMap::iterator aIter = m_aListenerMap.find( aCommandURL );
|
|
if ( aIter != m_aListenerMap.end() )
|
|
{
|
|
Reference< XDispatch > xOldDispatch( aIter->second );
|
|
aIter->second = xDispatch;
|
|
|
|
try
|
|
{
|
|
if ( xOldDispatch.is() )
|
|
xOldDispatch->removeStatusListener( xStatusListener, aTargetURL );
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
}
|
|
else
|
|
m_aListenerMap.insert( URLToDispatchMap::value_type( aCommandURL, xDispatch ));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Call without locked mutex as we are called back from dispatch implementation
|
|
try
|
|
{
|
|
if ( xDispatch.is() )
|
|
xDispatch->addStatusListener( xStatusListener, aTargetURL );
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
void StatusbarController::bindListener()
|
|
{
|
|
std::vector< Listener > aDispatchVector;
|
|
Reference< XStatusListener > xStatusListener;
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( !m_bInitialized )
|
|
return;
|
|
|
|
// Collect all registered command URL's and store them temporary
|
|
Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
|
|
if ( m_xServiceManager.is() && xDispatchProvider.is() )
|
|
{
|
|
xStatusListener = Reference< XStatusListener >( static_cast< OWeakObject* >( this ), UNO_QUERY );
|
|
URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
|
|
while ( pIter != m_aListenerMap.end() )
|
|
{
|
|
Reference< XURLTransformer > xURLTransformer = getURLTransformer();
|
|
com::sun::star::util::URL aTargetURL;
|
|
aTargetURL.Complete = pIter->first;
|
|
xURLTransformer->parseStrict( aTargetURL );
|
|
|
|
Reference< XDispatch > xDispatch( pIter->second );
|
|
if ( xDispatch.is() )
|
|
{
|
|
// We already have a dispatch object => we have to requery.
|
|
// Release old dispatch object and remove it as listener
|
|
try
|
|
{
|
|
xDispatch->removeStatusListener( xStatusListener, aTargetURL );
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
pIter->second.clear();
|
|
xDispatch.clear();
|
|
|
|
// Query for dispatch object. Old dispatch will be released with this, too.
|
|
try
|
|
{
|
|
xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
pIter->second = xDispatch;
|
|
|
|
Listener aListener( aTargetURL, xDispatch );
|
|
aDispatchVector.push_back( aListener );
|
|
++pIter;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Call without locked mutex as we are called back from dispatch implementation
|
|
if ( xStatusListener.is() )
|
|
{
|
|
try
|
|
{
|
|
for ( sal_uInt32 i = 0; i < aDispatchVector.size(); i++ )
|
|
{
|
|
Listener& rListener = aDispatchVector[i];
|
|
if ( rListener.xDispatch.is() )
|
|
rListener.xDispatch->addStatusListener( xStatusListener, rListener.aURL );
|
|
else if ( rListener.aURL.Complete == m_aCommandURL )
|
|
{
|
|
try
|
|
{
|
|
// Send status changed for the main URL, if we cannot get a valid dispatch object.
|
|
// UI disables the button. Catch exception as we release our mutex, it is possible
|
|
// that someone else already disposed this instance!
|
|
FeatureStateEvent aFeatureStateEvent;
|
|
aFeatureStateEvent.IsEnabled = sal_False;
|
|
aFeatureStateEvent.FeatureURL = rListener.aURL;
|
|
aFeatureStateEvent.State = Any();
|
|
xStatusListener->statusChanged( aFeatureStateEvent );
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
::Rectangle StatusbarController::getControlRect() const
|
|
{
|
|
::Rectangle aRect;
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
throw DisposedException();
|
|
|
|
if ( m_xParentWindow.is() )
|
|
{
|
|
StatusBar* pStatusBar = dynamic_cast< StatusBar* >( VCLUnoHelper::GetWindow( m_xParentWindow ));
|
|
if ( pStatusBar && pStatusBar->GetType() == WINDOW_STATUSBAR )
|
|
aRect = pStatusBar->GetItemRect( m_nID );
|
|
}
|
|
}
|
|
|
|
return aRect;
|
|
}
|
|
|
|
void StatusbarController::execute( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
|
|
{
|
|
Reference< XDispatch > xDispatch;
|
|
Reference< XURLTransformer > xURLTransformer;
|
|
rtl::OUString aCommandURL;
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
throw DisposedException();
|
|
|
|
if ( m_bInitialized &&
|
|
m_xFrame.is() &&
|
|
m_xServiceManager.is() &&
|
|
!m_aCommandURL.isEmpty() )
|
|
{
|
|
xURLTransformer = getURLTransformer();
|
|
aCommandURL = m_aCommandURL;
|
|
URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
|
|
if ( pIter != m_aListenerMap.end() )
|
|
xDispatch = pIter->second;
|
|
}
|
|
}
|
|
|
|
if ( xDispatch.is() && xURLTransformer.is() )
|
|
{
|
|
try
|
|
{
|
|
com::sun::star::util::URL aTargetURL;
|
|
|
|
aTargetURL.Complete = aCommandURL;
|
|
xURLTransformer->parseStrict( aTargetURL );
|
|
xDispatch->dispatch( aTargetURL, aArgs );
|
|
}
|
|
catch ( DisposedException& )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
void StatusbarController::execute(
|
|
const rtl::OUString& aCommandURL,
|
|
const Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
|
|
{
|
|
Reference< XDispatch > xDispatch;
|
|
com::sun::star::util::URL aTargetURL;
|
|
|
|
{
|
|
SolarMutexGuard aSolarMutexGuard;
|
|
|
|
if ( m_bDisposed )
|
|
throw DisposedException();
|
|
|
|
if ( m_bInitialized &&
|
|
m_xFrame.is() &&
|
|
m_xServiceManager.is() &&
|
|
!m_aCommandURL.isEmpty() )
|
|
{
|
|
Reference< XURLTransformer > xURLTransformer( getURLTransformer() );
|
|
aTargetURL.Complete = aCommandURL;
|
|
xURLTransformer->parseStrict( aTargetURL );
|
|
|
|
URLToDispatchMap::iterator pIter = m_aListenerMap.find( aCommandURL );
|
|
if ( pIter != m_aListenerMap.end() )
|
|
xDispatch = pIter->second;
|
|
else
|
|
{
|
|
Reference< ::com::sun::star::frame::XDispatchProvider > xDispatchProvider(
|
|
m_xFrame->getController(), UNO_QUERY );
|
|
if ( xDispatchProvider.is() )
|
|
xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( xDispatch.is() )
|
|
{
|
|
try
|
|
{
|
|
xDispatch->dispatch( aTargetURL, aArgs );
|
|
}
|
|
catch ( DisposedException& )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
} // svt
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|