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