1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_reportdesign.hxx"
26
27 #include <ReportControllerObserver.hxx>
28 #include <ReportController.hxx>
29 #include <svl/smplhint.hxx>
30 #include <vos/mutex.hxx>
31 #include <vcl/svapp.hxx>
32 #include <com/sun/star/report/XFormattedField.hpp>
33 #include <com/sun/star/awt/FontSlant.hpp>
34 #include <FormattedFieldBeautifier.hxx>
35
36 #include <svx/unopage.hxx>
37
38 // DBG_*
39 #include <tools/debug.hxx>
40 // DBG_UNHANDLED_EXCEPTION
41 #include <tools/diagnose_ex.h>
42
43 namespace rptui
44 {
45
46 using namespace ::com::sun::star;
47
48 // const OReportController *& m_pReportController;
49
50 DECLARE_STL_USTRINGACCESS_MAP(bool, AllProperties);
51 DECLARE_STL_STDKEY_MAP(uno::Reference< beans::XPropertySet >, AllProperties, PropertySetInfoCache);
52
53 class OXReportControllerObserverImpl
54 {
55 OXReportControllerObserverImpl(OXReportControllerObserverImpl&);
56 void operator =(OXReportControllerObserverImpl&);
57 public:
58 const OReportController& m_rReportController;
59 ::std::vector< uno::Reference< container::XChild> > m_aSections;
60 ::osl::Mutex m_aMutex;
61 oslInterlockedCount m_nLocks;
62 sal_Bool m_bReadOnly;
63
64 OXReportControllerObserverImpl(const OReportController& _rController);
65 ~OXReportControllerObserverImpl();
66 };
67
68 // -----------------------------------------------------------------------------
69
OXReportControllerObserverImpl(const OReportController & _rController)70 OXReportControllerObserverImpl::OXReportControllerObserverImpl(const OReportController& _rController)
71 :m_rReportController(_rController)
72 ,m_nLocks(0)
73 ,m_bReadOnly(sal_False)
74 {
75 }
76
~OXReportControllerObserverImpl()77 OXReportControllerObserverImpl::~OXReportControllerObserverImpl()
78 {
79 }
80
81 // -----------------------------------------------------------------------------
82 // -----------------------------------------------------------------------------
83 // -----------------------------------------------------------------------------
84
DBG_NAME(rpt_OXReportControllerObserver)85 DBG_NAME(rpt_OXReportControllerObserver)
86
87 OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController)
88 :m_pImpl(new OXReportControllerObserverImpl(_rController) )
89 ,m_aFormattedFieldBeautifier(_rController)
90 ,m_aFixedTextColor(_rController)
91 {
92 DBG_CTOR( rpt_OXReportControllerObserver,NULL);
93
94 Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
95 }
96
~OXReportControllerObserver()97 OXReportControllerObserver::~OXReportControllerObserver()
98 {
99 DBG_CTOR( rpt_OXReportControllerObserver,NULL);
100 Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) );
101 }
102
103 // -----------------------------------------------------------------------------
IMPL_LINK(OXReportControllerObserver,SettingsChanged,VclWindowEvent *,_pEvt)104 IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclWindowEvent*, _pEvt)
105 {
106 if ( _pEvt )
107 {
108 sal_Int32 nEvent = _pEvt->GetId();
109 /*
110 // just for debug
111 if (nEvent == VCLEVENT_WINDOW_CHILDCREATED ||
112 nEvent == VCLEVENT_WINDOW_PAINT ||
113 nEvent == VCLEVENT_WINDOW_MOVE ||
114 nEvent == VCLEVENT_WINDOW_RESIZE ||
115 nEvent == VCLEVENT_WINDOW_SHOW ||
116 nEvent == VCLEVENT_WINDOW_MOUSEMOVE ||
117 nEvent == VCLEVENT_WINDOW_FRAMETITLECHANGED ||
118 nEvent == VCLEVENT_WINDOW_HIDE ||
119 nEvent == VCLEVENT_EDIT_MODIFY ||
120 nEvent == VCLEVENT_SCROLLBAR_ENDSCROLL ||
121 nEvent == VCLEVENT_EDIT_SELECTIONCHANGED ||
122 nEvent == VCLEVENT_TABPAGE_INSERTED ||
123 nEvent == VCLEVENT_TABPAGE_REMOVED ||
124 nEvent == VCLEVENT_TOOLBOX_FORMATCHANGED ||
125 nEvent == VCLEVENT_TOOLBOX_ITEMADDED ||
126 nEvent == VCLEVENT_TOOLBOX_ALLITEMCHANGED ||
127 nEvent == VCLEVENT_MENUBARADDED ||
128 nEvent == 1
129 )
130 {
131 return 0L;
132 }
133 */
134
135 if (nEvent == VCLEVENT_APPLICATION_DATACHANGED )
136 {
137 DataChangedEvent* pData = reinterpret_cast<DataChangedEvent*>(_pEvt->GetData());
138 if ( pData && ((( pData->GetType() == DATACHANGED_SETTINGS ) ||
139 ( pData->GetType() == DATACHANGED_DISPLAY )) &&
140 ( pData->GetFlags() & SETTINGS_STYLE )))
141 {
142 OEnvLock aLock(*this);
143
144 // sal_uInt32 nCount = m_pImpl->m_aSections.size();
145
146 // send all Section Objects a 'tingle'
147 // maybe they need a change in format, color, etc
148 ::std::vector< uno::Reference< container::XChild > >::const_iterator aIter = m_pImpl->m_aSections.begin();
149 ::std::vector< uno::Reference< container::XChild > >::const_iterator aEnd = m_pImpl->m_aSections.end();
150 for (;aIter != aEnd; aIter++)
151 {
152 const uno::Reference<container::XChild> xChild (*aIter);
153 if (xChild.is())
154 {
155 uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY);
156 if (xSection.is())
157 {
158 const sal_Int32 nCount = xSection->getCount();
159 for (sal_Int32 i = 0; i < nCount; ++i)
160 {
161 const uno::Any aObj = xSection->getByIndex(i);
162 uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY);
163 if (xReportComponent.is())
164 {
165 m_aFormattedFieldBeautifier.handle(xReportComponent);
166 m_aFixedTextColor.handle(xReportComponent);
167 }
168 }
169 }
170 }
171 }
172 }
173 }
174 }
175
176 return 0L;
177 }
178
179 // XEventListener
disposing(const lang::EventObject & e)180 void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e) throw( uno::RuntimeException )
181 {
182 (void) e;
183 // check if it's an object we have cached informations about
184 uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY);
185 if ( xSourceSet.is() )
186 {
187 uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
188 if ( xSection.is() )
189 RemoveSection(xSection);
190 else
191 RemoveElement(xSourceSet);
192 }
193 }
194
Clear()195 void OXReportControllerObserver::Clear()
196 {
197 OEnvLock aLock(*this);
198 // sal_uInt32 nDebugValue = m_pImpl->m_aSections.size();
199 m_pImpl->m_aSections.clear();
200 }
201
202 // XPropertyChangeListener
propertyChange(const beans::PropertyChangeEvent & _rEvent)203 void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent) throw(uno::RuntimeException)
204 {
205 (void) _rEvent;
206 ::osl::ClearableMutexGuard aGuard( m_pImpl->m_aMutex );
207
208 if ( IsLocked() )
209 return;
210
211 m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent);
212 m_aFixedTextColor.notifyPropertyChange(_rEvent);
213 }
214
215 // -----------------------------------------------------------------------------
Lock()216 void OXReportControllerObserver::Lock()
217 {
218 OSL_ENSURE(m_refCount,"Illegal call to dead object!");
219 osl_incrementInterlockedCount( &m_pImpl->m_nLocks );
220 }
UnLock()221 void OXReportControllerObserver::UnLock()
222 {
223 OSL_ENSURE(m_refCount,"Illegal call to dead object!");
224
225 osl_decrementInterlockedCount( &m_pImpl->m_nLocks );
226 }
IsLocked() const227 sal_Bool OXReportControllerObserver::IsLocked() const { return m_pImpl->m_nLocks != 0; }
228
229 //------------------------------------------------------------------------------
AddSection(const uno::Reference<report::XSection> & _xSection)230 void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection)
231 {
232 OEnvLock aLock(*this);
233 try
234 {
235 uno::Reference<container::XChild> xChild = _xSection.get();
236 m_pImpl->m_aSections.push_back(xChild);
237 uno::Reference< uno::XInterface > xInt(_xSection);
238 AddElement(xInt);
239 }
240 catch(const uno::Exception&)
241 {
242 DBG_UNHANDLED_EXCEPTION();
243 }
244 }
245
246 //------------------------------------------------------------------------------
RemoveSection(const uno::Reference<report::XSection> & _xSection)247 void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection)
248 {
249 OEnvLock aLock(*this);
250 try
251 {
252 uno::Reference<container::XChild> xChild(_xSection.get());
253 m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),
254 xChild), m_pImpl->m_aSections.end());
255 uno::Reference< uno::XInterface > xInt(_xSection);
256 RemoveElement(xInt);
257 }
258 catch(uno::Exception&)
259 {
260 DBG_UNHANDLED_EXCEPTION();
261 }
262 }
263
264 //------------------------------------------------------------------------------
TogglePropertyListening(const uno::Reference<uno::XInterface> & Element)265 void OXReportControllerObserver::TogglePropertyListening(const uno::Reference< uno::XInterface > & Element)
266 {
267 // listen at Container
268 uno::Reference< container::XIndexAccess > xContainer(Element, uno::UNO_QUERY);
269 if (xContainer.is())
270 {
271 uno::Reference< uno::XInterface > xInterface;
272 sal_Int32 nCount = xContainer->getCount();
273 for(sal_Int32 i = 0;i != nCount;++i)
274 {
275 xInterface.set(xContainer->getByIndex( i ),uno::UNO_QUERY);
276 TogglePropertyListening(xInterface);
277 }
278 }
279
280 uno::Reference< beans::XPropertySet > xSet(Element, uno::UNO_QUERY);
281 if (xSet.is())
282 {
283 if (!m_pImpl->m_bReadOnly)
284 xSet->addPropertyChangeListener( ::rtl::OUString(), this );
285 else
286 xSet->removePropertyChangeListener( ::rtl::OUString(), this );
287 }
288 }
289
290
291 //------------------------------------------------------------------------------
switchListening(const uno::Reference<container::XIndexAccess> & _rxContainer,bool _bStartListening)292 void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening ) SAL_THROW(())
293 {
294 OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" );
295 if ( !_rxContainer.is() )
296 return;
297
298 try
299 {
300 // also handle all children of this element
301 uno::Reference< uno::XInterface > xInterface;
302 sal_Int32 nCount = _rxContainer->getCount();
303 for(sal_Int32 i = 0;i != nCount;++i)
304 {
305 xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
306 if ( _bStartListening )
307 AddElement( xInterface );
308 else
309 RemoveElement( xInterface );
310 }
311
312 // be notified of any changes in the container elements
313 uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY );
314 // OSL_ENSURE( xSimpleContainer.is(), "OXReportControllerObserver::switchListening: how are we expected to be notified of changes in the container?" );
315 if ( xSimpleContainer.is() )
316 {
317 if ( _bStartListening )
318 xSimpleContainer->addContainerListener( this );
319 else
320 xSimpleContainer->removeContainerListener( this );
321 }
322 }
323 catch( const uno::Exception& )
324 {
325 DBG_UNHANDLED_EXCEPTION();
326 }
327 }
328
329 //------------------------------------------------------------------------------
switchListening(const uno::Reference<uno::XInterface> & _rxObject,bool _bStartListening)330 void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(())
331 {
332 OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
333
334 try
335 {
336 if ( !m_pImpl->m_bReadOnly )
337 {
338 uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY );
339 if ( xProps.is() )
340 {
341 if ( _bStartListening )
342 xProps->addPropertyChangeListener( ::rtl::OUString(), this );
343 else
344 xProps->removePropertyChangeListener( ::rtl::OUString(), this );
345 }
346 }
347
348 uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY );
349 if ( xBroadcaster.is() )
350 {
351 if ( _bStartListening )
352 xBroadcaster->addModifyListener( this );
353 else
354 xBroadcaster->removeModifyListener( this );
355 }
356 }
357 catch( const uno::Exception& )
358 {
359 DBG_UNHANDLED_EXCEPTION();
360 }
361 }
362
363 //------------------------------------------------------------------------------
modified(const lang::EventObject &)364 void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ ) throw (uno::RuntimeException)
365 {
366 // implSetModified();
367 }
368
369 //------------------------------------------------------------------------------
AddElement(const uno::Reference<uno::XInterface> & _rxElement)370 void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement )
371 {
372 // if ( !IsLocked() )
373 // {
374 m_aFormattedFieldBeautifier.notifyElementInserted(_rxElement);
375 m_aFixedTextColor.notifyElementInserted(_rxElement);
376 // }
377
378 // if it's a container, start listening at all elements
379 uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
380 if ( xContainer.is() )
381 switchListening( xContainer, true );
382
383 switchListening( _rxElement, true );
384 }
385
386 //------------------------------------------------------------------------------
RemoveElement(const uno::Reference<uno::XInterface> & _rxElement)387 void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement)
388 {
389 switchListening( _rxElement, false );
390
391 uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
392 if ( xContainer.is() )
393 switchListening( xContainer, false );
394 }
395
396 // -----------------------------------------------------------------------------
getSection(const uno::Reference<container::XChild> & _xContainer) const397 ::std::vector< uno::Reference< container::XChild> >::const_iterator OXReportControllerObserver::getSection(const uno::Reference<container::XChild>& _xContainer) const
398 {
399 ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = m_pImpl->m_aSections.end();
400 if ( _xContainer.is() )
401 {
402 aFind = ::std::find(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),_xContainer);
403
404 if ( aFind == m_pImpl->m_aSections.end() )
405 {
406 uno::Reference<container::XChild> xParent(_xContainer->getParent(),uno::UNO_QUERY);
407 aFind = getSection(xParent);
408 }
409 }
410 return aFind;
411 }
412 // XContainerListener
413 //------------------------------------------------------------------------------
elementInserted(const container::ContainerEvent & evt)414 void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt) throw(uno::RuntimeException)
415 {
416 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
417 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
418
419 // neues Object zum lauschen
420 uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
421 if ( xIface.is() )
422 {
423 AddElement(xIface);
424 }
425 }
426
427 //------------------------------------------------------------------------------
elementReplaced(const container::ContainerEvent & evt)428 void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt) throw(uno::RuntimeException)
429 {
430 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
431 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
432
433 uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY);
434 OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
435 RemoveElement(xIface);
436
437 xIface.set(evt.Element,uno::UNO_QUERY);
438 AddElement(xIface);
439 }
440
441 //------------------------------------------------------------------------------
elementRemoved(const container::ContainerEvent & evt)442 void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt) throw(uno::RuntimeException)
443 {
444 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
445 ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
446
447 uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
448 if ( xIface.is() )
449 {
450 RemoveElement(xIface);
451 }
452 }
453
454
455 } // namespace rptui
456
457
458
459