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 .
21 #include <ReportControllerObserver.hxx>
22 #include <ReportController.hxx>
23 #include <svl/smplhint.hxx>
24 #include <osl/mutex.hxx>
25 #include <vcl/svapp.hxx>
26 #include <com/sun/star/report/XFormattedField.hpp>
27 #include <com/sun/star/awt/FontSlant.hpp>
28 #include <FormattedFieldBeautifier.hxx>
30 #include <svx/unopage.hxx>
33 #include <tools/debug.hxx>
34 // DBG_UNHANDLED_EXCEPTION
35 #include <tools/diagnose_ex.h>
40 using namespace ::com::sun::star
;
42 DECLARE_STL_USTRINGACCESS_MAP(bool, AllProperties
);
43 DECLARE_STL_STDKEY_MAP(uno::Reference
< beans::XPropertySet
>, AllProperties
, PropertySetInfoCache
);
45 class OXReportControllerObserverImpl
47 OXReportControllerObserverImpl(OXReportControllerObserverImpl
&);
48 void operator =(OXReportControllerObserverImpl
&);
50 const OReportController
& m_rReportController
;
51 ::std::vector
< uno::Reference
< container::XChild
> > m_aSections
;
52 ::osl::Mutex m_aMutex
;
53 oslInterlockedCount m_nLocks
;
56 OXReportControllerObserverImpl(const OReportController
& _rController
);
57 ~OXReportControllerObserverImpl();
60 // -----------------------------------------------------------------------------
62 OXReportControllerObserverImpl::OXReportControllerObserverImpl(const OReportController
& _rController
)
63 :m_rReportController(_rController
)
65 ,m_bReadOnly(sal_False
)
69 OXReportControllerObserverImpl::~OXReportControllerObserverImpl()
73 // -----------------------------------------------------------------------------
74 // -----------------------------------------------------------------------------
75 // -----------------------------------------------------------------------------
77 DBG_NAME(rpt_OXReportControllerObserver
)
79 OXReportControllerObserver::OXReportControllerObserver(const OReportController
& _rController
)
80 :m_pImpl(new OXReportControllerObserverImpl(_rController
) )
81 ,m_aFormattedFieldBeautifier(_rController
)
82 ,m_aFixedTextColor(_rController
)
84 DBG_CTOR( rpt_OXReportControllerObserver
,NULL
);
86 Application::AddEventListener(LINK( this, OXReportControllerObserver
, SettingsChanged
) );
89 OXReportControllerObserver::~OXReportControllerObserver()
91 DBG_CTOR( rpt_OXReportControllerObserver
,NULL
);
92 Application::RemoveEventListener(LINK( this, OXReportControllerObserver
, SettingsChanged
) );
95 // -----------------------------------------------------------------------------
96 IMPL_LINK(OXReportControllerObserver
, SettingsChanged
, VclWindowEvent
*, _pEvt
)
100 sal_Int32 nEvent
= _pEvt
->GetId();
102 if (nEvent
== VCLEVENT_APPLICATION_DATACHANGED
)
104 DataChangedEvent
* pData
= reinterpret_cast<DataChangedEvent
*>(_pEvt
->GetData());
105 if ( pData
&& ((( pData
->GetType() == DATACHANGED_SETTINGS
) ||
106 ( pData
->GetType() == DATACHANGED_DISPLAY
)) &&
107 ( pData
->GetFlags() & SETTINGS_STYLE
)))
109 OEnvLock
aLock(*this);
111 // send all Section Objects a 'tingle'
112 // maybe they need a change in format, color, etc
113 ::std::vector
< uno::Reference
< container::XChild
> >::const_iterator aIter
= m_pImpl
->m_aSections
.begin();
114 ::std::vector
< uno::Reference
< container::XChild
> >::const_iterator aEnd
= m_pImpl
->m_aSections
.end();
115 for (;aIter
!= aEnd
; ++aIter
)
117 const uno::Reference
<container::XChild
> xChild (*aIter
);
120 uno::Reference
<report::XSection
> xSection(xChild
, uno::UNO_QUERY
);
123 const sal_Int32 nCount
= xSection
->getCount();
124 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
126 const uno::Any aObj
= xSection
->getByIndex(i
);
127 uno::Reference
< report::XReportComponent
> xReportComponent(aObj
, uno::UNO_QUERY
);
128 if (xReportComponent
.is())
130 m_aFormattedFieldBeautifier
.handle(xReportComponent
);
131 m_aFixedTextColor
.handle(xReportComponent
);
145 void SAL_CALL
OXReportControllerObserver::disposing(const lang::EventObject
& e
) throw( uno::RuntimeException
)
148 // check if it's an object we have cached information about
149 uno::Reference
< beans::XPropertySet
> xSourceSet(e
.Source
, uno::UNO_QUERY
);
150 if ( xSourceSet
.is() )
152 uno::Reference
< report::XSection
> xSection(xSourceSet
,uno::UNO_QUERY
);
154 RemoveSection(xSection
);
156 RemoveElement(xSourceSet
);
160 void OXReportControllerObserver::Clear()
162 OEnvLock
aLock(*this);
163 m_pImpl
->m_aSections
.clear();
166 // XPropertyChangeListener
167 void SAL_CALL
OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent
& _rEvent
) throw(uno::RuntimeException
)
170 ::osl::ClearableMutexGuard
aGuard( m_pImpl
->m_aMutex
);
175 m_aFormattedFieldBeautifier
.notifyPropertyChange(_rEvent
);
176 m_aFixedTextColor
.notifyPropertyChange(_rEvent
);
179 // -----------------------------------------------------------------------------
180 void OXReportControllerObserver::Lock()
182 OSL_ENSURE(m_refCount
,"Illegal call to dead object!");
183 osl_atomic_increment( &m_pImpl
->m_nLocks
);
185 void OXReportControllerObserver::UnLock()
187 OSL_ENSURE(m_refCount
,"Illegal call to dead object!");
189 osl_atomic_decrement( &m_pImpl
->m_nLocks
);
191 sal_Bool
OXReportControllerObserver::IsLocked() const { return m_pImpl
->m_nLocks
!= 0; }
193 //------------------------------------------------------------------------------
194 void OXReportControllerObserver::AddSection(const uno::Reference
< report::XSection
> & _xSection
)
196 OEnvLock
aLock(*this);
199 uno::Reference
<container::XChild
> xChild
= _xSection
.get();
200 m_pImpl
->m_aSections
.push_back(xChild
);
201 uno::Reference
< uno::XInterface
> xInt(_xSection
);
204 catch(const uno::Exception
&)
206 DBG_UNHANDLED_EXCEPTION();
210 //------------------------------------------------------------------------------
211 void OXReportControllerObserver::RemoveSection(const uno::Reference
< report::XSection
> & _xSection
)
213 OEnvLock
aLock(*this);
216 uno::Reference
<container::XChild
> xChild(_xSection
.get());
217 m_pImpl
->m_aSections
.erase(::std::remove(m_pImpl
->m_aSections
.begin(),m_pImpl
->m_aSections
.end(),
218 xChild
), m_pImpl
->m_aSections
.end());
219 uno::Reference
< uno::XInterface
> xInt(_xSection
);
222 catch(uno::Exception
&)
224 DBG_UNHANDLED_EXCEPTION();
228 //------------------------------------------------------------------------------
229 void OXReportControllerObserver::TogglePropertyListening(const uno::Reference
< uno::XInterface
> & Element
)
231 // listen at Container
232 uno::Reference
< container::XIndexAccess
> xContainer(Element
, uno::UNO_QUERY
);
235 uno::Reference
< uno::XInterface
> xInterface
;
236 sal_Int32 nCount
= xContainer
->getCount();
237 for(sal_Int32 i
= 0;i
!= nCount
;++i
)
239 xInterface
.set(xContainer
->getByIndex( i
),uno::UNO_QUERY
);
240 TogglePropertyListening(xInterface
);
244 uno::Reference
< beans::XPropertySet
> xSet(Element
, uno::UNO_QUERY
);
247 if (!m_pImpl
->m_bReadOnly
)
248 xSet
->addPropertyChangeListener( OUString(), this );
250 xSet
->removePropertyChangeListener( OUString(), this );
255 //------------------------------------------------------------------------------
256 void OXReportControllerObserver::switchListening( const uno::Reference
< container::XIndexAccess
>& _rxContainer
, bool _bStartListening
) SAL_THROW(())
258 OSL_PRECOND( _rxContainer
.is(), "OXReportControllerObserver::switchListening: invalid container!" );
259 if ( !_rxContainer
.is() )
264 // also handle all children of this element
265 uno::Reference
< uno::XInterface
> xInterface
;
266 sal_Int32 nCount
= _rxContainer
->getCount();
267 for(sal_Int32 i
= 0;i
!= nCount
;++i
)
269 xInterface
.set(_rxContainer
->getByIndex( i
),uno::UNO_QUERY
);
270 if ( _bStartListening
)
271 AddElement( xInterface
);
273 RemoveElement( xInterface
);
276 // be notified of any changes in the container elements
277 uno::Reference
< container::XContainer
> xSimpleContainer( _rxContainer
, uno::UNO_QUERY
);
278 if ( xSimpleContainer
.is() )
280 if ( _bStartListening
)
281 xSimpleContainer
->addContainerListener( this );
283 xSimpleContainer
->removeContainerListener( this );
286 catch( const uno::Exception
& )
288 DBG_UNHANDLED_EXCEPTION();
292 //------------------------------------------------------------------------------
293 void OXReportControllerObserver::switchListening( const uno::Reference
< uno::XInterface
>& _rxObject
, bool _bStartListening
) SAL_THROW(())
295 OSL_PRECOND( _rxObject
.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
299 if ( !m_pImpl
->m_bReadOnly
)
301 uno::Reference
< beans::XPropertySet
> xProps( _rxObject
, uno::UNO_QUERY
);
304 if ( _bStartListening
)
305 xProps
->addPropertyChangeListener( OUString(), this );
307 xProps
->removePropertyChangeListener( OUString(), this );
311 uno::Reference
< util::XModifyBroadcaster
> xBroadcaster( _rxObject
, uno::UNO_QUERY
);
312 if ( xBroadcaster
.is() )
314 if ( _bStartListening
)
315 xBroadcaster
->addModifyListener( this );
317 xBroadcaster
->removeModifyListener( this );
320 catch( const uno::Exception
& )
322 DBG_UNHANDLED_EXCEPTION();
326 //------------------------------------------------------------------------------
327 void SAL_CALL
OXReportControllerObserver::modified( const lang::EventObject
& /*aEvent*/ ) throw (uno::RuntimeException
)
331 //------------------------------------------------------------------------------
332 void OXReportControllerObserver::AddElement(const uno::Reference
< uno::XInterface
>& _rxElement
)
334 m_aFormattedFieldBeautifier
.notifyElementInserted(_rxElement
);
335 m_aFixedTextColor
.notifyElementInserted(_rxElement
);
337 // if it's a container, start listening at all elements
338 uno::Reference
< container::XIndexAccess
> xContainer( _rxElement
, uno::UNO_QUERY
);
339 if ( xContainer
.is() )
340 switchListening( xContainer
, true );
342 switchListening( _rxElement
, true );
345 //------------------------------------------------------------------------------
346 void OXReportControllerObserver::RemoveElement(const uno::Reference
< uno::XInterface
>& _rxElement
)
348 switchListening( _rxElement
, false );
350 uno::Reference
< container::XIndexAccess
> xContainer( _rxElement
, uno::UNO_QUERY
);
351 if ( xContainer
.is() )
352 switchListening( xContainer
, false );
355 // -----------------------------------------------------------------------------
356 ::std::vector
< uno::Reference
< container::XChild
> >::const_iterator
OXReportControllerObserver::getSection(const uno::Reference
<container::XChild
>& _xContainer
) const
358 ::std::vector
< uno::Reference
< container::XChild
> >::const_iterator aFind
= m_pImpl
->m_aSections
.end();
359 if ( _xContainer
.is() )
361 aFind
= ::std::find(m_pImpl
->m_aSections
.begin(),m_pImpl
->m_aSections
.end(),_xContainer
);
363 if ( aFind
== m_pImpl
->m_aSections
.end() )
365 uno::Reference
<container::XChild
> xParent(_xContainer
->getParent(),uno::UNO_QUERY
);
366 aFind
= getSection(xParent
);
371 // XContainerListener
372 //------------------------------------------------------------------------------
373 void SAL_CALL
OXReportControllerObserver::elementInserted(const container::ContainerEvent
& evt
) throw(uno::RuntimeException
)
375 SolarMutexGuard aSolarGuard
;
376 ::osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
378 // neues Object zum lauschen
379 uno::Reference
< uno::XInterface
> xIface( evt
.Element
, uno::UNO_QUERY
);
386 //------------------------------------------------------------------------------
387 void SAL_CALL
OXReportControllerObserver::elementReplaced(const container::ContainerEvent
& evt
) throw(uno::RuntimeException
)
389 SolarMutexGuard aSolarGuard
;
390 ::osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
392 uno::Reference
< uno::XInterface
> xIface(evt
.ReplacedElement
,uno::UNO_QUERY
);
393 OSL_ENSURE(xIface
.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
394 RemoveElement(xIface
);
396 xIface
.set(evt
.Element
,uno::UNO_QUERY
);
400 //------------------------------------------------------------------------------
401 void SAL_CALL
OXReportControllerObserver::elementRemoved(const container::ContainerEvent
& evt
) throw(uno::RuntimeException
)
403 SolarMutexGuard aSolarGuard
;
404 ::osl::MutexGuard
aGuard( m_pImpl
->m_aMutex
);
406 uno::Reference
< uno::XInterface
> xIface( evt
.Element
, uno::UNO_QUERY
);
409 RemoveElement(xIface
);
418 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */