Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
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>
29 :
30 : #include <svx/unopage.hxx>
31 :
32 : // DBG_*
33 : #include <tools/debug.hxx>
34 : // DBG_UNHANDLED_EXCEPTION
35 : #include <tools/diagnose_ex.h>
36 :
37 : namespace rptui
38 : {
39 :
40 : using namespace ::com::sun::star;
41 :
42 : DECLARE_STL_USTRINGACCESS_MAP(bool, AllProperties);
43 : DECLARE_STL_STDKEY_MAP(uno::Reference< beans::XPropertySet >, AllProperties, PropertySetInfoCache);
44 :
45 : class OXReportControllerObserverImpl
46 : {
47 : OXReportControllerObserverImpl(OXReportControllerObserverImpl&);
48 : void operator =(OXReportControllerObserverImpl&);
49 : public:
50 : const OReportController& m_rReportController;
51 : ::std::vector< uno::Reference< container::XChild> > m_aSections;
52 : ::osl::Mutex m_aMutex;
53 : oslInterlockedCount m_nLocks;
54 : sal_Bool m_bReadOnly;
55 :
56 : OXReportControllerObserverImpl(const OReportController& _rController);
57 : ~OXReportControllerObserverImpl();
58 : };
59 :
60 : // -----------------------------------------------------------------------------
61 :
62 0 : OXReportControllerObserverImpl::OXReportControllerObserverImpl(const OReportController& _rController)
63 : :m_rReportController(_rController)
64 : ,m_nLocks(0)
65 0 : ,m_bReadOnly(sal_False)
66 : {
67 0 : }
68 :
69 0 : OXReportControllerObserverImpl::~OXReportControllerObserverImpl()
70 : {
71 0 : }
72 :
73 : // -----------------------------------------------------------------------------
74 : // -----------------------------------------------------------------------------
75 : // -----------------------------------------------------------------------------
76 :
77 : DBG_NAME(rpt_OXReportControllerObserver)
78 :
79 0 : OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController)
80 0 : :m_pImpl(new OXReportControllerObserverImpl(_rController) )
81 : ,m_aFormattedFieldBeautifier(_rController)
82 0 : ,m_aFixedTextColor(_rController)
83 : {
84 : DBG_CTOR( rpt_OXReportControllerObserver,NULL);
85 :
86 0 : Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
87 0 : }
88 :
89 0 : OXReportControllerObserver::~OXReportControllerObserver()
90 : {
91 : DBG_CTOR( rpt_OXReportControllerObserver,NULL);
92 0 : Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
93 0 : }
94 :
95 : // -----------------------------------------------------------------------------
96 0 : IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclWindowEvent*, _pEvt)
97 : {
98 0 : if ( _pEvt )
99 : {
100 0 : sal_Int32 nEvent = _pEvt->GetId();
101 :
102 0 : if (nEvent == VCLEVENT_APPLICATION_DATACHANGED )
103 : {
104 0 : DataChangedEvent* pData = reinterpret_cast<DataChangedEvent*>(_pEvt->GetData());
105 0 : if ( pData && ((( pData->GetType() == DATACHANGED_SETTINGS ) ||
106 0 : ( pData->GetType() == DATACHANGED_DISPLAY )) &&
107 0 : ( pData->GetFlags() & SETTINGS_STYLE )))
108 : {
109 0 : OEnvLock aLock(*this);
110 :
111 : // send all Section Objects a 'tingle'
112 : // maybe they need a change in format, color, etc
113 0 : ::std::vector< uno::Reference< container::XChild > >::const_iterator aIter = m_pImpl->m_aSections.begin();
114 0 : ::std::vector< uno::Reference< container::XChild > >::const_iterator aEnd = m_pImpl->m_aSections.end();
115 0 : for (;aIter != aEnd; ++aIter)
116 : {
117 0 : const uno::Reference<container::XChild> xChild (*aIter);
118 0 : if (xChild.is())
119 : {
120 0 : uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY);
121 0 : if (xSection.is())
122 : {
123 0 : const sal_Int32 nCount = xSection->getCount();
124 0 : for (sal_Int32 i = 0; i < nCount; ++i)
125 : {
126 0 : const uno::Any aObj = xSection->getByIndex(i);
127 0 : uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY);
128 0 : if (xReportComponent.is())
129 : {
130 0 : m_aFormattedFieldBeautifier.handle(xReportComponent);
131 0 : m_aFixedTextColor.handle(xReportComponent);
132 : }
133 0 : }
134 0 : }
135 : }
136 0 : }
137 : }
138 : }
139 : }
140 :
141 0 : return 0L;
142 : }
143 :
144 : // XEventListener
145 0 : void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e) throw( uno::RuntimeException )
146 : {
147 : (void) e;
148 : // check if it's an object we have cached informations about
149 0 : uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY);
150 0 : if ( xSourceSet.is() )
151 : {
152 0 : uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
153 0 : if ( xSection.is() )
154 0 : RemoveSection(xSection);
155 : else
156 0 : RemoveElement(xSourceSet);
157 0 : }
158 0 : }
159 :
160 0 : void OXReportControllerObserver::Clear()
161 : {
162 0 : OEnvLock aLock(*this);
163 0 : m_pImpl->m_aSections.clear();
164 0 : }
165 :
166 : // XPropertyChangeListener
167 0 : void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent) throw(uno::RuntimeException)
168 : {
169 : (void) _rEvent;
170 0 : ::osl::ClearableMutexGuard aGuard( m_pImpl->m_aMutex );
171 :
172 0 : if ( IsLocked() )
173 0 : return;
174 :
175 0 : m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent);
176 0 : m_aFixedTextColor.notifyPropertyChange(_rEvent);
177 : }
178 :
179 : // -----------------------------------------------------------------------------
180 0 : void OXReportControllerObserver::Lock()
181 : {
182 : OSL_ENSURE(m_refCount,"Illegal call to dead object!");
183 0 : osl_atomic_increment( &m_pImpl->m_nLocks );
184 0 : }
185 0 : void OXReportControllerObserver::UnLock()
186 : {
187 : OSL_ENSURE(m_refCount,"Illegal call to dead object!");
188 :
189 0 : osl_atomic_decrement( &m_pImpl->m_nLocks );
190 0 : }
191 0 : sal_Bool OXReportControllerObserver::IsLocked() const { return m_pImpl->m_nLocks != 0; }
192 :
193 : //------------------------------------------------------------------------------
194 0 : void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection)
195 : {
196 0 : OEnvLock aLock(*this);
197 : try
198 : {
199 0 : uno::Reference<container::XChild> xChild = _xSection.get();
200 0 : m_pImpl->m_aSections.push_back(xChild);
201 0 : uno::Reference< uno::XInterface > xInt(_xSection);
202 0 : AddElement(xInt);
203 : }
204 0 : catch(const uno::Exception&)
205 : {
206 : DBG_UNHANDLED_EXCEPTION();
207 0 : }
208 0 : }
209 :
210 : //------------------------------------------------------------------------------
211 0 : void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection)
212 : {
213 0 : OEnvLock aLock(*this);
214 : try
215 : {
216 0 : uno::Reference<container::XChild> xChild(_xSection.get());
217 0 : m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),
218 0 : xChild), m_pImpl->m_aSections.end());
219 0 : uno::Reference< uno::XInterface > xInt(_xSection);
220 0 : RemoveElement(xInt);
221 : }
222 0 : catch(uno::Exception&)
223 : {
224 : DBG_UNHANDLED_EXCEPTION();
225 0 : }
226 0 : }
227 :
228 : //------------------------------------------------------------------------------
229 0 : void OXReportControllerObserver::TogglePropertyListening(const uno::Reference< uno::XInterface > & Element)
230 : {
231 : // listen at Container
232 0 : uno::Reference< container::XIndexAccess > xContainer(Element, uno::UNO_QUERY);
233 0 : if (xContainer.is())
234 : {
235 0 : uno::Reference< uno::XInterface > xInterface;
236 0 : sal_Int32 nCount = xContainer->getCount();
237 0 : for(sal_Int32 i = 0;i != nCount;++i)
238 : {
239 0 : xInterface.set(xContainer->getByIndex( i ),uno::UNO_QUERY);
240 0 : TogglePropertyListening(xInterface);
241 0 : }
242 : }
243 :
244 0 : uno::Reference< beans::XPropertySet > xSet(Element, uno::UNO_QUERY);
245 0 : if (xSet.is())
246 : {
247 0 : if (!m_pImpl->m_bReadOnly)
248 0 : xSet->addPropertyChangeListener( ::rtl::OUString(), this );
249 : else
250 0 : xSet->removePropertyChangeListener( ::rtl::OUString(), this );
251 0 : }
252 0 : }
253 :
254 :
255 : //------------------------------------------------------------------------------
256 0 : void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening ) SAL_THROW(())
257 : {
258 : OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" );
259 0 : if ( !_rxContainer.is() )
260 0 : return;
261 :
262 : try
263 : {
264 : // also handle all children of this element
265 0 : uno::Reference< uno::XInterface > xInterface;
266 0 : sal_Int32 nCount = _rxContainer->getCount();
267 0 : for(sal_Int32 i = 0;i != nCount;++i)
268 : {
269 0 : xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
270 0 : if ( _bStartListening )
271 0 : AddElement( xInterface );
272 : else
273 0 : RemoveElement( xInterface );
274 : }
275 :
276 : // be notified of any changes in the container elements
277 0 : uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY );
278 0 : if ( xSimpleContainer.is() )
279 : {
280 0 : if ( _bStartListening )
281 0 : xSimpleContainer->addContainerListener( this );
282 : else
283 0 : xSimpleContainer->removeContainerListener( this );
284 0 : }
285 : }
286 0 : catch( const uno::Exception& )
287 : {
288 : DBG_UNHANDLED_EXCEPTION();
289 : }
290 : }
291 :
292 : //------------------------------------------------------------------------------
293 0 : void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(())
294 : {
295 : OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
296 :
297 : try
298 : {
299 0 : if ( !m_pImpl->m_bReadOnly )
300 : {
301 0 : uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY );
302 0 : if ( xProps.is() )
303 : {
304 0 : if ( _bStartListening )
305 0 : xProps->addPropertyChangeListener( ::rtl::OUString(), this );
306 : else
307 0 : xProps->removePropertyChangeListener( ::rtl::OUString(), this );
308 0 : }
309 : }
310 :
311 0 : uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY );
312 0 : if ( xBroadcaster.is() )
313 : {
314 0 : if ( _bStartListening )
315 0 : xBroadcaster->addModifyListener( this );
316 : else
317 0 : xBroadcaster->removeModifyListener( this );
318 0 : }
319 : }
320 0 : catch( const uno::Exception& )
321 : {
322 : DBG_UNHANDLED_EXCEPTION();
323 : }
324 0 : }
325 :
326 : //------------------------------------------------------------------------------
327 0 : void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ ) throw (uno::RuntimeException)
328 : {
329 0 : }
330 :
331 : //------------------------------------------------------------------------------
332 0 : void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement )
333 : {
334 0 : m_aFormattedFieldBeautifier.notifyElementInserted(_rxElement);
335 0 : m_aFixedTextColor.notifyElementInserted(_rxElement);
336 :
337 : // if it's a container, start listening at all elements
338 0 : uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
339 0 : if ( xContainer.is() )
340 0 : switchListening( xContainer, true );
341 :
342 0 : switchListening( _rxElement, true );
343 0 : }
344 :
345 : //------------------------------------------------------------------------------
346 0 : void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement)
347 : {
348 0 : switchListening( _rxElement, false );
349 :
350 0 : uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
351 0 : if ( xContainer.is() )
352 0 : switchListening( xContainer, false );
353 0 : }
354 :
355 : // -----------------------------------------------------------------------------
356 0 : ::std::vector< uno::Reference< container::XChild> >::const_iterator OXReportControllerObserver::getSection(const uno::Reference<container::XChild>& _xContainer) const
357 : {
358 0 : ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = m_pImpl->m_aSections.end();
359 0 : if ( _xContainer.is() )
360 : {
361 0 : aFind = ::std::find(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),_xContainer);
362 :
363 0 : if ( aFind == m_pImpl->m_aSections.end() )
364 : {
365 0 : uno::Reference<container::XChild> xParent(_xContainer->getParent(),uno::UNO_QUERY);
366 0 : aFind = getSection(xParent);
367 : }
368 : }
369 0 : return aFind;
370 : }
371 : // XContainerListener
372 : //------------------------------------------------------------------------------
373 0 : void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt) throw(uno::RuntimeException)
374 : {
375 0 : SolarMutexGuard aSolarGuard;
376 0 : ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
377 :
378 : // neues Object zum lauschen
379 0 : uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
380 0 : if ( xIface.is() )
381 : {
382 0 : AddElement(xIface);
383 0 : }
384 0 : }
385 :
386 : //------------------------------------------------------------------------------
387 0 : void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt) throw(uno::RuntimeException)
388 : {
389 0 : SolarMutexGuard aSolarGuard;
390 0 : ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
391 :
392 0 : uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY);
393 : OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
394 0 : RemoveElement(xIface);
395 :
396 0 : xIface.set(evt.Element,uno::UNO_QUERY);
397 0 : AddElement(xIface);
398 0 : }
399 :
400 : //------------------------------------------------------------------------------
401 0 : void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt) throw(uno::RuntimeException)
402 : {
403 0 : SolarMutexGuard aSolarGuard;
404 0 : ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
405 :
406 0 : uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
407 0 : if ( xIface.is() )
408 : {
409 0 : RemoveElement(xIface);
410 0 : }
411 0 : }
412 :
413 :
414 : } // namespace rptui
415 :
416 :
417 :
418 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|