1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
36 #include <tools/debug.hxx>
37 // DBG_UNHANDLED_EXCEPTION
38 #include <tools/diagnose_ex.h>
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
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()
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 for (const uno::Reference
<container::XChild
>& xChild
: m_pImpl
->m_aSections
)
101 uno::Reference
<report::XSection
> xSection(xChild
, uno::UNO_QUERY
);
104 const sal_Int32 nCount
= xSection
->getCount();
105 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
107 const uno::Any aObj
= xSection
->getByIndex(i
);
108 uno::Reference
< report::XReportComponent
> xReportComponent(aObj
, uno::UNO_QUERY
);
109 if (xReportComponent
.is())
111 m_aFormattedFieldBeautifier
.handle(xReportComponent
);
112 m_aFixedTextColor
.handle(xReportComponent
);
123 void SAL_CALL
OXReportControllerObserver::disposing(const lang::EventObject
& e
)
125 // check if it's an object we have cached information about
126 uno::Reference
< beans::XPropertySet
> xSourceSet(e
.Source
, uno::UNO_QUERY
);
127 if ( xSourceSet
.is() )
129 uno::Reference
< report::XSection
> xSection(xSourceSet
,uno::UNO_QUERY
);
131 RemoveSection(xSection
);
133 RemoveElement(xSourceSet
);
137 void OXReportControllerObserver::Clear()
139 OEnvLock
aLock(*this);
140 m_pImpl
->m_aSections
.clear();
143 // XPropertyChangeListener
144 void SAL_CALL
OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent
& _rEvent
)
146 osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
148 if ( m_pImpl
->m_nLocks
!= 0 )
151 m_aFormattedFieldBeautifier
.notifyPropertyChange(_rEvent
);
152 m_aFixedTextColor
.notifyPropertyChange(_rEvent
);
156 void OXReportControllerObserver::Lock()
158 OSL_ENSURE(m_refCount
,"Illegal call to dead object!");
159 osl_atomic_increment( &m_pImpl
->m_nLocks
);
162 void OXReportControllerObserver::UnLock()
164 OSL_ENSURE(m_refCount
,"Illegal call to dead object!");
166 osl_atomic_decrement( &m_pImpl
->m_nLocks
);
169 void OXReportControllerObserver::AddSection(const uno::Reference
< report::XSection
> & _xSection
)
171 OEnvLock
aLock(*this);
174 uno::Reference
<container::XChild
> xChild
= _xSection
.get();
175 m_pImpl
->m_aSections
.push_back(xChild
);
176 uno::Reference
< uno::XInterface
> xInt(_xSection
);
179 catch(const uno::Exception
&)
181 DBG_UNHANDLED_EXCEPTION("reportdesign");
186 void OXReportControllerObserver::RemoveSection(const uno::Reference
< report::XSection
> & _xSection
)
188 OEnvLock
aLock(*this);
191 uno::Reference
<container::XChild
> xChild(_xSection
.get());
192 m_pImpl
->m_aSections
.erase(::std::remove(m_pImpl
->m_aSections
.begin(),m_pImpl
->m_aSections
.end(),
193 xChild
), m_pImpl
->m_aSections
.end());
194 uno::Reference
< uno::XInterface
> xInt(_xSection
);
197 catch(uno::Exception
&)
199 DBG_UNHANDLED_EXCEPTION("reportdesign");
204 void OXReportControllerObserver::switchListening( const uno::Reference
< container::XIndexAccess
>& _rxContainer
, bool _bStartListening
)
206 OSL_PRECOND( _rxContainer
.is(), "OXReportControllerObserver::switchListening: invalid container!" );
207 if ( !_rxContainer
.is() )
212 // also handle all children of this element
213 uno::Reference
< uno::XInterface
> xInterface
;
214 sal_Int32 nCount
= _rxContainer
->getCount();
215 for(sal_Int32 i
= 0;i
!= nCount
;++i
)
217 xInterface
.set(_rxContainer
->getByIndex( i
),uno::UNO_QUERY
);
218 if ( _bStartListening
)
219 AddElement( xInterface
);
221 RemoveElement( xInterface
);
224 // be notified of any changes in the container elements
225 uno::Reference
< container::XContainer
> xSimpleContainer( _rxContainer
, uno::UNO_QUERY
);
226 if ( xSimpleContainer
.is() )
228 if ( _bStartListening
)
229 xSimpleContainer
->addContainerListener( this );
231 xSimpleContainer
->removeContainerListener( this );
234 catch( const uno::Exception
& )
236 DBG_UNHANDLED_EXCEPTION("reportdesign");
241 void OXReportControllerObserver::switchListening( const uno::Reference
< uno::XInterface
>& _rxObject
, bool _bStartListening
)
243 OSL_PRECOND( _rxObject
.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
247 uno::Reference
< beans::XPropertySet
> xProps( _rxObject
, uno::UNO_QUERY
);
250 if ( _bStartListening
)
251 xProps
->addPropertyChangeListener( OUString(), this );
253 xProps
->removePropertyChangeListener( OUString(), this );
256 uno::Reference
< util::XModifyBroadcaster
> xBroadcaster( _rxObject
, uno::UNO_QUERY
);
257 if ( xBroadcaster
.is() )
259 if ( _bStartListening
)
260 xBroadcaster
->addModifyListener( this );
262 xBroadcaster
->removeModifyListener( this );
265 catch( const uno::Exception
& )
267 DBG_UNHANDLED_EXCEPTION("reportdesign");
272 void SAL_CALL
OXReportControllerObserver::modified( const lang::EventObject
& /*aEvent*/ )
277 void OXReportControllerObserver::AddElement(const uno::Reference
< uno::XInterface
>& _rxElement
)
279 m_aFormattedFieldBeautifier
.notifyElementInserted(_rxElement
);
280 m_aFixedTextColor
.notifyElementInserted(_rxElement
);
282 // if it's a container, start listening at all elements
283 uno::Reference
< container::XIndexAccess
> xContainer( _rxElement
, uno::UNO_QUERY
);
284 if ( xContainer
.is() )
285 switchListening( xContainer
, true );
287 switchListening( _rxElement
, true );
291 void OXReportControllerObserver::RemoveElement(const uno::Reference
< uno::XInterface
>& _rxElement
)
293 switchListening( _rxElement
, false );
295 uno::Reference
< container::XIndexAccess
> xContainer( _rxElement
, uno::UNO_QUERY
);
296 if ( xContainer
.is() )
297 switchListening( xContainer
, false );
301 // XContainerListener
303 void SAL_CALL
OXReportControllerObserver::elementInserted(const container::ContainerEvent
& evt
)
305 SolarMutexGuard aSolarGuard
;
306 ::osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
308 // new listener object
309 uno::Reference
< uno::XInterface
> xIface( evt
.Element
, uno::UNO_QUERY
);
317 void SAL_CALL
OXReportControllerObserver::elementReplaced(const container::ContainerEvent
& evt
)
319 SolarMutexGuard aSolarGuard
;
320 ::osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
322 uno::Reference
< uno::XInterface
> xIface(evt
.ReplacedElement
,uno::UNO_QUERY
);
323 OSL_ENSURE(xIface
.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
324 RemoveElement(xIface
);
326 xIface
.set(evt
.Element
,uno::UNO_QUERY
);
331 void SAL_CALL
OXReportControllerObserver::elementRemoved(const container::ContainerEvent
& evt
)
333 SolarMutexGuard aSolarGuard
;
334 ::osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
336 uno::Reference
< uno::XInterface
> xIface( evt
.Element
, uno::UNO_QUERY
);
339 RemoveElement(xIface
);
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */