lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / reportdesign / source / ui / report / ReportControllerObserver.cxx
blobd56d55b0a427ded0b4822571c927073da3ed7acd
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 <osl/mutex.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
30 #include <com/sun/star/awt/FontSlant.hpp>
31 #include <FormattedFieldBeautifier.hxx>
33 #include <svx/unopage.hxx>
35 // DBG_*
36 #include <tools/debug.hxx>
37 // DBG_UNHANDLED_EXCEPTION
38 #include <tools/diagnose_ex.h>
40 namespace rptui
43 using namespace ::com::sun::star;
45 typedef std::map<OUString, bool> AllProperties;
46 typedef std::map<uno::Reference< beans::XPropertySet >, AllProperties> PropertySetInfoCache;
48 class OXReportControllerObserverImpl
50 public:
51 ::std::vector< uno::Reference< container::XChild> > m_aSections;
52 ::osl::Mutex m_aMutex;
53 oslInterlockedCount m_nLocks;
55 explicit OXReportControllerObserverImpl();
56 OXReportControllerObserverImpl(const OXReportControllerObserverImpl&) = delete;
57 OXReportControllerObserverImpl& operator=(const OXReportControllerObserverImpl&) = delete;
61 OXReportControllerObserverImpl::OXReportControllerObserverImpl()
62 :m_nLocks(0)
67 OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController)
68 :m_pImpl(new OXReportControllerObserverImpl )
69 ,m_aFormattedFieldBeautifier(_rController)
70 ,m_aFixedTextColor(_rController)
73 Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
76 OXReportControllerObserver::~OXReportControllerObserver()
78 Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
82 IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclSimpleEvent&, _rEvt, void)
84 VclEventId nEvent = _rEvt.GetId();
86 if (nEvent == VclEventId::ApplicationDataChanged )
88 DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(_rEvt).GetData());
89 if ( pData && ((( pData->GetType() == DataChangedEventType::SETTINGS ) ||
90 ( pData->GetType() == DataChangedEventType::DISPLAY )) &&
91 ( pData->GetFlags() & AllSettingsFlags::STYLE )))
93 OEnvLock aLock(*this);
95 // send all Section Objects a 'tingle'
96 // maybe they need a change in format, color, etc
97 ::std::vector< uno::Reference< container::XChild > >::const_iterator aIter = m_pImpl->m_aSections.begin();
98 ::std::vector< uno::Reference< container::XChild > >::const_iterator aEnd = m_pImpl->m_aSections.end();
99 for (;aIter != aEnd; ++aIter)
101 const uno::Reference<container::XChild> xChild (*aIter);
102 if (xChild.is())
104 uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY);
105 if (xSection.is())
107 const sal_Int32 nCount = xSection->getCount();
108 for (sal_Int32 i = 0; i < nCount; ++i)
110 const uno::Any aObj = xSection->getByIndex(i);
111 uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY);
112 if (xReportComponent.is())
114 m_aFormattedFieldBeautifier.handle(xReportComponent);
115 m_aFixedTextColor.handle(xReportComponent);
125 // XEventListener
126 void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e)
128 // check if it's an object we have cached information about
129 uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY);
130 if ( xSourceSet.is() )
132 uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
133 if ( xSection.is() )
134 RemoveSection(xSection);
135 else
136 RemoveElement(xSourceSet);
140 void OXReportControllerObserver::Clear()
142 OEnvLock aLock(*this);
143 m_pImpl->m_aSections.clear();
146 // XPropertyChangeListener
147 void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent)
149 ::osl::ClearableMutexGuard aGuard( m_pImpl->m_aMutex );
151 if ( m_pImpl->m_nLocks != 0 )
152 return;
154 m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent);
155 m_aFixedTextColor.notifyPropertyChange(_rEvent);
159 void OXReportControllerObserver::Lock()
161 OSL_ENSURE(m_refCount,"Illegal call to dead object!");
162 osl_atomic_increment( &m_pImpl->m_nLocks );
165 void OXReportControllerObserver::UnLock()
167 OSL_ENSURE(m_refCount,"Illegal call to dead object!");
169 osl_atomic_decrement( &m_pImpl->m_nLocks );
172 void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection)
174 OEnvLock aLock(*this);
177 uno::Reference<container::XChild> xChild = _xSection.get();
178 m_pImpl->m_aSections.push_back(xChild);
179 uno::Reference< uno::XInterface > xInt(_xSection);
180 AddElement(xInt);
182 catch(const uno::Exception&)
184 DBG_UNHANDLED_EXCEPTION("reportdesign");
189 void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection)
191 OEnvLock aLock(*this);
194 uno::Reference<container::XChild> xChild(_xSection.get());
195 m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),
196 xChild), m_pImpl->m_aSections.end());
197 uno::Reference< uno::XInterface > xInt(_xSection);
198 RemoveElement(xInt);
200 catch(uno::Exception&)
202 DBG_UNHANDLED_EXCEPTION("reportdesign");
207 void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening )
209 OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" );
210 if ( !_rxContainer.is() )
211 return;
215 // also handle all children of this element
216 uno::Reference< uno::XInterface > xInterface;
217 sal_Int32 nCount = _rxContainer->getCount();
218 for(sal_Int32 i = 0;i != nCount;++i)
220 xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
221 if ( _bStartListening )
222 AddElement( xInterface );
223 else
224 RemoveElement( xInterface );
227 // be notified of any changes in the container elements
228 uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY );
229 if ( xSimpleContainer.is() )
231 if ( _bStartListening )
232 xSimpleContainer->addContainerListener( this );
233 else
234 xSimpleContainer->removeContainerListener( this );
237 catch( const uno::Exception& )
239 DBG_UNHANDLED_EXCEPTION("reportdesign");
244 void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening )
246 OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
250 uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY );
251 if ( xProps.is() )
253 if ( _bStartListening )
254 xProps->addPropertyChangeListener( OUString(), this );
255 else
256 xProps->removePropertyChangeListener( OUString(), this );
259 uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY );
260 if ( xBroadcaster.is() )
262 if ( _bStartListening )
263 xBroadcaster->addModifyListener( this );
264 else
265 xBroadcaster->removeModifyListener( this );
268 catch( const uno::Exception& )
270 DBG_UNHANDLED_EXCEPTION("reportdesign");
275 void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ )
280 void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement )
282 m_aFormattedFieldBeautifier.notifyElementInserted(_rxElement);
283 m_aFixedTextColor.notifyElementInserted(_rxElement);
285 // if it's a container, start listening at all elements
286 uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
287 if ( xContainer.is() )
288 switchListening( xContainer, true );
290 switchListening( _rxElement, true );
294 void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement)
296 switchListening( _rxElement, false );
298 uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
299 if ( xContainer.is() )
300 switchListening( xContainer, false );
304 // XContainerListener
306 void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt)
308 SolarMutexGuard aSolarGuard;
309 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
311 // new listener object
312 uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
313 if ( xIface.is() )
315 AddElement(xIface);
320 void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt)
322 SolarMutexGuard aSolarGuard;
323 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
325 uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY);
326 OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
327 RemoveElement(xIface);
329 xIface.set(evt.Element,uno::UNO_QUERY);
330 AddElement(xIface);
334 void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt)
336 SolarMutexGuard aSolarGuard;
337 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
339 uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
340 if ( xIface.is() )
342 RemoveElement(xIface);
347 } // namespace rptui
350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */