bump product version to 5.0.4.1
[LibreOffice.git] / reportdesign / source / ui / report / ReportControllerObserver.cxx
blob3dd5b0091c3f4973e158bde2cefb0b705f4786a0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <map>
24 #include <ReportControllerObserver.hxx>
25 #include <ReportController.hxx>
26 #include <boost/noncopyable.hpp>
27 #include <svl/smplhint.hxx>
28 #include <osl/mutex.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/settings.hxx>
32 #include <com/sun/star/report/XFormattedField.hpp>
33 #include <com/sun/star/awt/FontSlant.hpp>
34 #include <FormattedFieldBeautifier.hxx>
36 #include <svx/unopage.hxx>
38 // DBG_*
39 #include <tools/debug.hxx>
40 // DBG_UNHANDLED_EXCEPTION
41 #include <tools/diagnose_ex.h>
43 namespace rptui
46 using namespace ::com::sun::star;
48 typedef std::map<OUString, bool> AllProperties;
49 typedef std::map<uno::Reference< beans::XPropertySet >, AllProperties> PropertySetInfoCache;
51 class OXReportControllerObserverImpl: private boost::noncopyable
53 public:
54 const OReportController& m_rReportController;
55 ::std::vector< uno::Reference< container::XChild> > m_aSections;
56 ::osl::Mutex m_aMutex;
57 oslInterlockedCount m_nLocks;
58 bool m_bReadOnly;
60 OXReportControllerObserverImpl(const OReportController& _rController);
61 ~OXReportControllerObserverImpl();
66 OXReportControllerObserverImpl::OXReportControllerObserverImpl(const OReportController& _rController)
67 :m_rReportController(_rController)
68 ,m_nLocks(0)
69 ,m_bReadOnly(false)
73 OXReportControllerObserverImpl::~OXReportControllerObserverImpl()
82 OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController)
83 :m_pImpl(new OXReportControllerObserverImpl(_rController) )
84 ,m_aFormattedFieldBeautifier(_rController)
85 ,m_aFixedTextColor(_rController)
88 Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
91 OXReportControllerObserver::~OXReportControllerObserver()
93 Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
97 IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclWindowEvent*, _pEvt)
99 if ( _pEvt )
101 sal_Int32 nEvent = _pEvt->GetId();
103 if (nEvent == VCLEVENT_APPLICATION_DATACHANGED )
105 DataChangedEvent* pData = static_cast<DataChangedEvent*>(_pEvt->GetData());
106 if ( pData && ((( pData->GetType() == DataChangedEventType::SETTINGS ) ||
107 ( pData->GetType() == DataChangedEventType::DISPLAY )) &&
108 ( pData->GetFlags() & AllSettingsFlags::STYLE )))
110 OEnvLock aLock(*this);
112 // send all Section Objects a 'tingle'
113 // maybe they need a change in format, color, etc
114 ::std::vector< uno::Reference< container::XChild > >::const_iterator aIter = m_pImpl->m_aSections.begin();
115 ::std::vector< uno::Reference< container::XChild > >::const_iterator aEnd = m_pImpl->m_aSections.end();
116 for (;aIter != aEnd; ++aIter)
118 const uno::Reference<container::XChild> xChild (*aIter);
119 if (xChild.is())
121 uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY);
122 if (xSection.is())
124 const sal_Int32 nCount = xSection->getCount();
125 for (sal_Int32 i = 0; i < nCount; ++i)
127 const uno::Any aObj = xSection->getByIndex(i);
128 uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY);
129 if (xReportComponent.is())
131 m_aFormattedFieldBeautifier.handle(xReportComponent);
132 m_aFixedTextColor.handle(xReportComponent);
142 return 0L;
145 // XEventListener
146 void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e) throw( uno::RuntimeException, std::exception )
148 (void) e;
149 // check if it's an object we have cached information about
150 uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY);
151 if ( xSourceSet.is() )
153 uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
154 if ( xSection.is() )
155 RemoveSection(xSection);
156 else
157 RemoveElement(xSourceSet);
161 void OXReportControllerObserver::Clear()
163 OEnvLock aLock(*this);
164 m_pImpl->m_aSections.clear();
167 // XPropertyChangeListener
168 void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent) throw(uno::RuntimeException, std::exception)
170 (void) _rEvent;
171 ::osl::ClearableMutexGuard aGuard( m_pImpl->m_aMutex );
173 if ( IsLocked() )
174 return;
176 m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent);
177 m_aFixedTextColor.notifyPropertyChange(_rEvent);
181 void OXReportControllerObserver::Lock()
183 OSL_ENSURE(m_refCount,"Illegal call to dead object!");
184 osl_atomic_increment( &m_pImpl->m_nLocks );
187 void OXReportControllerObserver::UnLock()
189 OSL_ENSURE(m_refCount,"Illegal call to dead object!");
191 osl_atomic_decrement( &m_pImpl->m_nLocks );
194 bool OXReportControllerObserver::IsLocked() const
196 return m_pImpl->m_nLocks != 0;
200 void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection)
202 OEnvLock aLock(*this);
205 uno::Reference<container::XChild> xChild = _xSection.get();
206 m_pImpl->m_aSections.push_back(xChild);
207 uno::Reference< uno::XInterface > xInt(_xSection);
208 AddElement(xInt);
210 catch(const uno::Exception&)
212 DBG_UNHANDLED_EXCEPTION();
217 void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection)
219 OEnvLock aLock(*this);
222 uno::Reference<container::XChild> xChild(_xSection.get());
223 m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),
224 xChild), m_pImpl->m_aSections.end());
225 uno::Reference< uno::XInterface > xInt(_xSection);
226 RemoveElement(xInt);
228 catch(uno::Exception&)
230 DBG_UNHANDLED_EXCEPTION();
235 void OXReportControllerObserver::TogglePropertyListening(const uno::Reference< uno::XInterface > & Element)
237 // listen at Container
238 uno::Reference< container::XIndexAccess > xContainer(Element, uno::UNO_QUERY);
239 if (xContainer.is())
241 uno::Reference< uno::XInterface > xInterface;
242 sal_Int32 nCount = xContainer->getCount();
243 for(sal_Int32 i = 0;i != nCount;++i)
245 xInterface.set(xContainer->getByIndex( i ),uno::UNO_QUERY);
246 TogglePropertyListening(xInterface);
250 uno::Reference< beans::XPropertySet > xSet(Element, uno::UNO_QUERY);
251 if (xSet.is())
253 if (!m_pImpl->m_bReadOnly)
254 xSet->addPropertyChangeListener( OUString(), this );
255 else
256 xSet->removePropertyChangeListener( OUString(), this );
262 void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening )
264 OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" );
265 if ( !_rxContainer.is() )
266 return;
270 // also handle all children of this element
271 uno::Reference< uno::XInterface > xInterface;
272 sal_Int32 nCount = _rxContainer->getCount();
273 for(sal_Int32 i = 0;i != nCount;++i)
275 xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
276 if ( _bStartListening )
277 AddElement( xInterface );
278 else
279 RemoveElement( xInterface );
282 // be notified of any changes in the container elements
283 uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY );
284 if ( xSimpleContainer.is() )
286 if ( _bStartListening )
287 xSimpleContainer->addContainerListener( this );
288 else
289 xSimpleContainer->removeContainerListener( this );
292 catch( const uno::Exception& )
294 DBG_UNHANDLED_EXCEPTION();
299 void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening )
301 OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
305 if ( !m_pImpl->m_bReadOnly )
307 uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY );
308 if ( xProps.is() )
310 if ( _bStartListening )
311 xProps->addPropertyChangeListener( OUString(), this );
312 else
313 xProps->removePropertyChangeListener( OUString(), this );
317 uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY );
318 if ( xBroadcaster.is() )
320 if ( _bStartListening )
321 xBroadcaster->addModifyListener( this );
322 else
323 xBroadcaster->removeModifyListener( this );
326 catch( const uno::Exception& )
328 DBG_UNHANDLED_EXCEPTION();
333 void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ ) throw (uno::RuntimeException, std::exception)
338 void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement )
340 m_aFormattedFieldBeautifier.notifyElementInserted(_rxElement);
341 m_aFixedTextColor.notifyElementInserted(_rxElement);
343 // if it's a container, start listening at all elements
344 uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
345 if ( xContainer.is() )
346 switchListening( xContainer, true );
348 switchListening( _rxElement, true );
352 void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement)
354 switchListening( _rxElement, false );
356 uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
357 if ( xContainer.is() )
358 switchListening( xContainer, false );
362 ::std::vector< uno::Reference< container::XChild> >::const_iterator OXReportControllerObserver::getSection(const uno::Reference<container::XChild>& _xContainer) const
364 ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = m_pImpl->m_aSections.end();
365 if ( _xContainer.is() )
367 aFind = ::std::find(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),_xContainer);
369 if ( aFind == m_pImpl->m_aSections.end() )
371 uno::Reference<container::XChild> xParent(_xContainer->getParent(),uno::UNO_QUERY);
372 aFind = getSection(xParent);
375 return aFind;
377 // XContainerListener
379 void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt) throw(uno::RuntimeException, std::exception)
381 SolarMutexGuard aSolarGuard;
382 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
384 // neues Object zum lauschen
385 uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
386 if ( xIface.is() )
388 AddElement(xIface);
393 void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt) throw(uno::RuntimeException, std::exception)
395 SolarMutexGuard aSolarGuard;
396 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
398 uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY);
399 OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
400 RemoveElement(xIface);
402 xIface.set(evt.Element,uno::UNO_QUERY);
403 AddElement(xIface);
407 void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt) throw(uno::RuntimeException, std::exception)
409 SolarMutexGuard aSolarGuard;
410 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
412 uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
413 if ( xIface.is() )
415 RemoveElement(xIface);
420 } // namespace rptui
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */