summaryrefslogtreecommitdiffstats
path: root/reportdesign/source/ui/report/ReportControllerObserver.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'reportdesign/source/ui/report/ReportControllerObserver.cxx')
-rw-r--r--reportdesign/source/ui/report/ReportControllerObserver.cxx342
1 files changed, 342 insertions, 0 deletions
diff --git a/reportdesign/source/ui/report/ReportControllerObserver.cxx b/reportdesign/source/ui/report/ReportControllerObserver.cxx
new file mode 100644
index 000000000..514624388
--- /dev/null
+++ b/reportdesign/source/ui/report/ReportControllerObserver.cxx
@@ -0,0 +1,342 @@
+/* -*- 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 <sal/config.h>
+
+#include <map>
+
+#include <ReportControllerObserver.hxx>
+#include <ReportController.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <FormattedFieldBeautifier.hxx>
+
+// DBG_UNHANDLED_EXCEPTION
+#include <tools/diagnose_ex.h>
+
+namespace rptui
+{
+
+ using namespace ::com::sun::star;
+
+typedef std::map<OUString, bool> AllProperties;
+typedef std::map<uno::Reference< beans::XPropertySet >, AllProperties> PropertySetInfoCache;
+
+class OXReportControllerObserverImpl
+{
+public:
+ ::std::vector< uno::Reference< container::XChild> > m_aSections;
+ ::osl::Mutex m_aMutex;
+ oslInterlockedCount m_nLocks;
+
+ explicit OXReportControllerObserverImpl();
+ OXReportControllerObserverImpl(const OXReportControllerObserverImpl&) = delete;
+ OXReportControllerObserverImpl& operator=(const OXReportControllerObserverImpl&) = delete;
+};
+
+
+ OXReportControllerObserverImpl::OXReportControllerObserverImpl()
+ :m_nLocks(0)
+ {
+ }
+
+
+ OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController)
+ :m_pImpl(new OXReportControllerObserverImpl )
+ ,m_aFormattedFieldBeautifier(_rController)
+ ,m_aFixedTextColor(_rController)
+ {
+
+ Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
+ }
+
+ OXReportControllerObserver::~OXReportControllerObserver()
+ {
+ Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
+ }
+
+
+ IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclSimpleEvent&, _rEvt, void)
+ {
+ VclEventId nEvent = _rEvt.GetId();
+
+ if (nEvent != VclEventId::ApplicationDataChanged )
+ return;
+
+ DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(_rEvt).GetData());
+ if ( !(pData && ((( pData->GetType() == DataChangedEventType::SETTINGS ) ||
+ ( pData->GetType() == DataChangedEventType::DISPLAY )) &&
+ ( pData->GetFlags() & AllSettingsFlags::STYLE ))))
+ return;
+
+ OEnvLock aLock(*this);
+
+ // send all Section Objects a 'tingle'
+ // maybe they need a change in format, color, etc
+ for (const uno::Reference<container::XChild>& xChild : m_pImpl->m_aSections)
+ {
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // XEventListener
+ void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e)
+ {
+ // check if it's an object we have cached information 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);
+ m_pImpl->m_aSections.clear();
+ }
+
+ // XPropertyChangeListener
+ void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent)
+ {
+ osl::MutexGuard aGuard( m_pImpl->m_aMutex );
+
+ if ( m_pImpl->m_nLocks != 0 )
+ return;
+
+ m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent);
+ m_aFixedTextColor.notifyPropertyChange(_rEvent);
+ }
+
+
+void OXReportControllerObserver::Lock()
+{
+ OSL_ENSURE(m_refCount,"Illegal call to dead object!");
+ osl_atomic_increment( &m_pImpl->m_nLocks );
+}
+
+void OXReportControllerObserver::UnLock()
+{
+ OSL_ENSURE(m_refCount,"Illegal call to dead object!");
+
+ osl_atomic_decrement( &m_pImpl->m_nLocks );
+}
+
+void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection)
+{
+ OEnvLock aLock(*this);
+ try
+ {
+ uno::Reference<container::XChild> xChild = _xSection;
+ m_pImpl->m_aSections.push_back(xChild);
+ uno::Reference< uno::XInterface > xInt(_xSection);
+ AddElement(xInt);
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+}
+
+
+void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection)
+{
+ OEnvLock aLock(*this);
+ try
+ {
+ uno::Reference<container::XChild> xChild(_xSection);
+ 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("reportdesign");
+ }
+}
+
+
+void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening )
+{
+ 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 );
+ if ( xSimpleContainer.is() )
+ {
+ if ( _bStartListening )
+ xSimpleContainer->addContainerListener( this );
+ else
+ xSimpleContainer->removeContainerListener( this );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+}
+
+
+void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening )
+{
+ OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
+
+ try
+ {
+ uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY );
+ if ( xProps.is() )
+ {
+ if ( _bStartListening )
+ xProps->addPropertyChangeListener( OUString(), this );
+ else
+ xProps->removePropertyChangeListener( 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("reportdesign");
+ }
+}
+
+
+void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ )
+{
+}
+
+
+void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement )
+{
+ 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 );
+}
+
+
+// XContainerListener
+
+void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
+
+ // new listener object
+ uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
+ if ( xIface.is() )
+ {
+ AddElement(xIface);
+ }
+}
+
+
+void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt)
+{
+ SolarMutexGuard aSolarGuard;
+ ::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)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
+
+ uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
+ if ( xIface.is() )
+ {
+ RemoveElement(xIface);
+ }
+}
+
+
+} // namespace rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */