diff options
Diffstat (limited to 'reportdesign/source/ui/report/ReportControllerObserver.cxx')
-rw-r--r-- | reportdesign/source/ui/report/ReportControllerObserver.cxx | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/reportdesign/source/ui/report/ReportControllerObserver.cxx b/reportdesign/source/ui/report/ReportControllerObserver.cxx new file mode 100644 index 000000000000..7c0f3a572be8 --- /dev/null +++ b/reportdesign/source/ui/report/ReportControllerObserver.cxx @@ -0,0 +1,462 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_reportdesign.hxx" + +#include <ReportControllerObserver.hxx> +#include <ReportController.hxx> +#include <svl/smplhint.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/report/XFormattedField.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <FormattedFieldBeautifier.hxx> + +#include <svx/unopage.hxx> + +// DBG_* +#include <tools/debug.hxx> +// DBG_UNHANDLED_EXCEPTION +#include <tools/diagnose_ex.h> + +namespace rptui +{ + + using namespace ::com::sun::star; + + // const OReportController *& m_pReportController; + +DECLARE_STL_USTRINGACCESS_MAP(bool, AllProperties); +DECLARE_STL_STDKEY_MAP(uno::Reference< beans::XPropertySet >, AllProperties, PropertySetInfoCache); + +class OXReportControllerObserverImpl +{ + OXReportControllerObserverImpl(OXReportControllerObserverImpl&); + void operator =(OXReportControllerObserverImpl&); +public: + const OReportController& m_rReportController; + ::std::vector< uno::Reference< container::XChild> > m_aSections; + ::osl::Mutex m_aMutex; + oslInterlockedCount m_nLocks; + sal_Bool m_bReadOnly; + + OXReportControllerObserverImpl(const OReportController& _rController); + ~OXReportControllerObserverImpl(); +}; + +// ----------------------------------------------------------------------------- + + OXReportControllerObserverImpl::OXReportControllerObserverImpl(const OReportController& _rController) + :m_rReportController(_rController) + ,m_nLocks(0) + ,m_bReadOnly(sal_False) + { + } + + OXReportControllerObserverImpl::~OXReportControllerObserverImpl() + { + } + + // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------------------- + + DBG_NAME(rpt_OXReportControllerObserver) + + OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController) + :m_pImpl(new OXReportControllerObserverImpl(_rController) ) + ,m_aFormattedFieldBeautifier(_rController) + ,m_aFixedTextColor(_rController) + { + DBG_CTOR( rpt_OXReportControllerObserver,NULL); + + Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) ); + } + + OXReportControllerObserver::~OXReportControllerObserver() + { + DBG_CTOR( rpt_OXReportControllerObserver,NULL); + Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) ); + } + + // ----------------------------------------------------------------------------- + IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclWindowEvent*, _pEvt) + { + if ( _pEvt ) + { + sal_Int32 nEvent = _pEvt->GetId(); + /* + // just for debug + if (nEvent == VCLEVENT_WINDOW_CHILDCREATED || + nEvent == VCLEVENT_WINDOW_PAINT || + nEvent == VCLEVENT_WINDOW_MOVE || + nEvent == VCLEVENT_WINDOW_RESIZE || + nEvent == VCLEVENT_WINDOW_SHOW || + nEvent == VCLEVENT_WINDOW_MOUSEMOVE || + nEvent == VCLEVENT_WINDOW_FRAMETITLECHANGED || + nEvent == VCLEVENT_WINDOW_HIDE || + nEvent == VCLEVENT_EDIT_MODIFY || + nEvent == VCLEVENT_SCROLLBAR_ENDSCROLL || + nEvent == VCLEVENT_EDIT_SELECTIONCHANGED || + nEvent == VCLEVENT_TABPAGE_INSERTED || + nEvent == VCLEVENT_TABPAGE_REMOVED || + nEvent == VCLEVENT_TOOLBOX_FORMATCHANGED || + nEvent == VCLEVENT_TOOLBOX_ITEMADDED || + nEvent == VCLEVENT_TOOLBOX_ALLITEMCHANGED || + nEvent == VCLEVENT_MENUBARADDED || + nEvent == 1 + ) + { + return 0L; + } + */ + + if (nEvent == VCLEVENT_APPLICATION_DATACHANGED ) + { + DataChangedEvent* pData = reinterpret_cast<DataChangedEvent*>(_pEvt->GetData()); + if ( pData && ((( pData->GetType() == DATACHANGED_SETTINGS ) || + ( pData->GetType() == DATACHANGED_DISPLAY )) && + ( pData->GetFlags() & SETTINGS_STYLE ))) + { + OEnvLock aLock(*this); + + // sal_uInt32 nCount = m_pImpl->m_aSections.size(); + + // send all Section Objects a 'tingle' + // maybe they need a change in format, color, etc + ::std::vector< uno::Reference< container::XChild > >::const_iterator aIter = m_pImpl->m_aSections.begin(); + ::std::vector< uno::Reference< container::XChild > >::const_iterator aEnd = m_pImpl->m_aSections.end(); + for (;aIter != aEnd; aIter++) + { + const uno::Reference<container::XChild> xChild (*aIter); + if (xChild.is()) + { + uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY); + if (xSection.is()) + { + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + const uno::Any aObj = xSection->getByIndex(i); + uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY); + if (xReportComponent.is()) + { + m_aFormattedFieldBeautifier.handle(xReportComponent); + m_aFixedTextColor.handle(xReportComponent); + } + } + } + } + } + } + } + } + + return 0L; + } + + // XEventListener + void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e) throw( uno::RuntimeException ) + { + (void) e; + // check if it's an object we have cached informations about + uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY); + if ( xSourceSet.is() ) + { + uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY); + if ( xSection.is() ) + RemoveSection(xSection); + else + RemoveElement(xSourceSet); + } + } + + void OXReportControllerObserver::Clear() + { + OEnvLock aLock(*this); + // sal_uInt32 nDebugValue = m_pImpl->m_aSections.size(); + m_pImpl->m_aSections.clear(); + } + + // XPropertyChangeListener + void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent) throw(uno::RuntimeException) + { + (void) _rEvent; + ::osl::ClearableMutexGuard aGuard( m_pImpl->m_aMutex ); + + if ( IsLocked() ) + return; + + m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent); + m_aFixedTextColor.notifyPropertyChange(_rEvent); + } + +// ----------------------------------------------------------------------------- +void OXReportControllerObserver::Lock() +{ + OSL_ENSURE(m_refCount,"Illegal call to dead object!"); + osl_incrementInterlockedCount( &m_pImpl->m_nLocks ); +} +void OXReportControllerObserver::UnLock() +{ + OSL_ENSURE(m_refCount,"Illegal call to dead object!"); + + osl_decrementInterlockedCount( &m_pImpl->m_nLocks ); +} +sal_Bool OXReportControllerObserver::IsLocked() const { return m_pImpl->m_nLocks != 0; } + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection) +{ + OEnvLock aLock(*this); + try + { + uno::Reference<container::XChild> xChild = _xSection.get(); + m_pImpl->m_aSections.push_back(xChild); + uno::Reference< uno::XInterface > xInt(_xSection); + AddElement(xInt); + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection) +{ + OEnvLock aLock(*this); + try + { + uno::Reference<container::XChild> xChild(_xSection.get()); + m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(), + xChild), m_pImpl->m_aSections.end()); + uno::Reference< uno::XInterface > xInt(_xSection); + RemoveElement(xInt); + } + catch(uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::TogglePropertyListening(const uno::Reference< uno::XInterface > & Element) +{ + // listen at Container + uno::Reference< container::XIndexAccess > xContainer(Element, uno::UNO_QUERY); + if (xContainer.is()) + { + uno::Reference< uno::XInterface > xInterface; + sal_Int32 nCount = xContainer->getCount(); + for(sal_Int32 i = 0;i != nCount;++i) + { + xInterface.set(xContainer->getByIndex( i ),uno::UNO_QUERY); + TogglePropertyListening(xInterface); + } + } + + uno::Reference< beans::XPropertySet > xSet(Element, uno::UNO_QUERY); + if (xSet.is()) + { + if (!m_pImpl->m_bReadOnly) + xSet->addPropertyChangeListener( ::rtl::OUString(), this ); + else + xSet->removePropertyChangeListener( ::rtl::OUString(), this ); + } +} + + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening ) SAL_THROW(()) +{ + OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" ); + if ( !_rxContainer.is() ) + return; + + try + { + // also handle all children of this element + uno::Reference< uno::XInterface > xInterface; + sal_Int32 nCount = _rxContainer->getCount(); + for(sal_Int32 i = 0;i != nCount;++i) + { + xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY); + if ( _bStartListening ) + AddElement( xInterface ); + else + RemoveElement( xInterface ); + } + + // be notified of any changes in the container elements + uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY ); + // OSL_ENSURE( xSimpleContainer.is(), "OXReportControllerObserver::switchListening: how are we expected to be notified of changes in the container?" ); + if ( xSimpleContainer.is() ) + { + if ( _bStartListening ) + xSimpleContainer->addContainerListener( this ); + else + xSimpleContainer->removeContainerListener( this ); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(()) +{ + OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" ); + + try + { + if ( !m_pImpl->m_bReadOnly ) + { + uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY ); + if ( xProps.is() ) + { + if ( _bStartListening ) + xProps->addPropertyChangeListener( ::rtl::OUString(), this ); + else + xProps->removePropertyChangeListener( ::rtl::OUString(), this ); + } + } + + uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY ); + if ( xBroadcaster.is() ) + { + if ( _bStartListening ) + xBroadcaster->addModifyListener( this ); + else + xBroadcaster->removeModifyListener( this ); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ ) throw (uno::RuntimeException) +{ + // implSetModified(); +} + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement ) +{ + // if ( !IsLocked() ) + // { + m_aFormattedFieldBeautifier.notifyElementInserted(_rxElement); + m_aFixedTextColor.notifyElementInserted(_rxElement); + // } + + // if it's a container, start listening at all elements + uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY ); + if ( xContainer.is() ) + switchListening( xContainer, true ); + + switchListening( _rxElement, true ); +} + +//------------------------------------------------------------------------------ +void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement) +{ + switchListening( _rxElement, false ); + + uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY ); + if ( xContainer.is() ) + switchListening( xContainer, false ); +} + +// ----------------------------------------------------------------------------- +::std::vector< uno::Reference< container::XChild> >::const_iterator OXReportControllerObserver::getSection(const uno::Reference<container::XChild>& _xContainer) const +{ + ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = m_pImpl->m_aSections.end(); + if ( _xContainer.is() ) + { + aFind = ::std::find(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),_xContainer); + + if ( aFind == m_pImpl->m_aSections.end() ) + { + uno::Reference<container::XChild> xParent(_xContainer->getParent(),uno::UNO_QUERY); + aFind = getSection(xParent); + } + } + return aFind; +} +// XContainerListener +//------------------------------------------------------------------------------ +void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt) throw(uno::RuntimeException) +{ + ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + // neues Object zum lauschen + uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY ); + if ( xIface.is() ) + { + AddElement(xIface); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt) throw(uno::RuntimeException) +{ + ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY); + OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!"); + RemoveElement(xIface); + + xIface.set(evt.Element,uno::UNO_QUERY); + AddElement(xIface); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt) throw(uno::RuntimeException) +{ + ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY ); + if ( xIface.is() ) + { + RemoveElement(xIface); + } +} + + +} // namespace rptui + + + |