LibreOffice Module reportdesign (master)  1
ReportControllerObserver.cxx
Go to the documentation of this file.
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 #include <sal/config.h>
21 
22 #include <map>
23 
25 #include <ReportController.hxx>
26 #include <osl/mutex.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
29 
31 
32 // DBG_UNHANDLED_EXCEPTION
33 #include <tools/diagnose_ex.h>
34 
35 namespace rptui
36 {
37 
38  using namespace ::com::sun::star;
39 
40 typedef std::map<OUString, bool> AllProperties;
41 typedef std::map<uno::Reference< beans::XPropertySet >, AllProperties> PropertySetInfoCache;
42 
44 {
45 public:
46  ::std::vector< uno::Reference< container::XChild> > m_aSections;
47  ::osl::Mutex m_aMutex;
48  oslInterlockedCount m_nLocks;
49 
53 };
54 
55 
57  :m_nLocks(0)
58  {
59  }
60 
61 
64  ,m_aFormattedFieldBeautifier(_rController)
65  ,m_aFixedTextColor(_rController)
66  {
67 
69  }
70 
72  {
74  }
75 
76 
77  IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclSimpleEvent&, _rEvt, void)
78  {
79  VclEventId nEvent = _rEvt.GetId();
80 
81  if (nEvent != VclEventId::ApplicationDataChanged )
82  return;
83 
84  DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(_rEvt).GetData());
85  if ( !(pData && ((( pData->GetType() == DataChangedEventType::SETTINGS ) ||
86  ( pData->GetType() == DataChangedEventType::DISPLAY )) &&
87  ( pData->GetFlags() & AllSettingsFlags::STYLE ))))
88  return;
89 
90  OEnvLock aLock(*this);
91 
92  // send all Section Objects a 'tingle'
93  // maybe they need a change in format, color, etc
94  for (const uno::Reference<container::XChild>& xChild : m_pImpl->m_aSections)
95  {
96  if (xChild.is())
97  {
98  uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY);
99  if (xSection.is())
100  {
101  const sal_Int32 nCount = xSection->getCount();
102  for (sal_Int32 i = 0; i < nCount; ++i)
103  {
104  const uno::Any aObj = xSection->getByIndex(i);
105  uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY);
106  if (xReportComponent.is())
107  {
108  m_aFormattedFieldBeautifier.handle(xReportComponent);
109  m_aFixedTextColor.handle(xReportComponent);
110  }
111  }
112  }
113  }
114  }
115  }
116 
117  // XEventListener
118  void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e)
119  {
120  // check if it's an object we have cached information about
121  uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY);
122  if ( xSourceSet.is() )
123  {
124  uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
125  if ( xSection.is() )
126  RemoveSection(xSection);
127  else
128  RemoveElement(xSourceSet);
129  }
130  }
131 
133  {
134  OEnvLock aLock(*this);
135  m_pImpl->m_aSections.clear();
136  }
137 
138  // XPropertyChangeListener
139  void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent)
140  {
141  osl::MutexGuard aGuard( m_pImpl->m_aMutex );
142 
143  if ( m_pImpl->m_nLocks != 0 )
144  return;
145 
148  }
149 
150 
152 {
153  OSL_ENSURE(m_refCount,"Illegal call to dead object!");
154  osl_atomic_increment( &m_pImpl->m_nLocks );
155 }
156 
158 {
159  OSL_ENSURE(m_refCount,"Illegal call to dead object!");
160 
161  osl_atomic_decrement( &m_pImpl->m_nLocks );
162 }
163 
164 void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection)
165 {
166  OEnvLock aLock(*this);
167  try
168  {
169  uno::Reference<container::XChild> xChild = _xSection;
170  m_pImpl->m_aSections.push_back(xChild);
171  uno::Reference< uno::XInterface > xInt(_xSection);
172  AddElement(xInt);
173  }
174  catch(const uno::Exception&)
175  {
176  DBG_UNHANDLED_EXCEPTION("reportdesign");
177  }
178 }
179 
180 
181 void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection)
182 {
183  OEnvLock aLock(*this);
184  try
185  {
186  uno::Reference<container::XChild> xChild(_xSection);
187  m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),
188  xChild), m_pImpl->m_aSections.end());
189  uno::Reference< uno::XInterface > xInt(_xSection);
190  RemoveElement(xInt);
191  }
192  catch(uno::Exception&)
193  {
194  DBG_UNHANDLED_EXCEPTION("reportdesign");
195  }
196 }
197 
198 
199 void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening )
200 {
201  OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" );
202  if ( !_rxContainer.is() )
203  return;
204 
205  try
206  {
207  // also handle all children of this element
208  uno::Reference< uno::XInterface > xInterface;
209  sal_Int32 nCount = _rxContainer->getCount();
210  for(sal_Int32 i = 0;i != nCount;++i)
211  {
212  xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
213  if ( _bStartListening )
214  AddElement( xInterface );
215  else
216  RemoveElement( xInterface );
217  }
218 
219  // be notified of any changes in the container elements
220  uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY );
221  if ( xSimpleContainer.is() )
222  {
223  if ( _bStartListening )
224  xSimpleContainer->addContainerListener( this );
225  else
226  xSimpleContainer->removeContainerListener( this );
227  }
228  }
229  catch( const uno::Exception& )
230  {
231  DBG_UNHANDLED_EXCEPTION("reportdesign");
232  }
233 }
234 
235 
236 void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening )
237 {
238  OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" );
239 
240  try
241  {
242  uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY );
243  if ( xProps.is() )
244  {
245  if ( _bStartListening )
246  xProps->addPropertyChangeListener( OUString(), this );
247  else
248  xProps->removePropertyChangeListener( OUString(), this );
249  }
250 
251  uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY );
252  if ( xBroadcaster.is() )
253  {
254  if ( _bStartListening )
255  xBroadcaster->addModifyListener( this );
256  else
257  xBroadcaster->removeModifyListener( this );
258  }
259  }
260  catch( const uno::Exception& )
261  {
262  DBG_UNHANDLED_EXCEPTION("reportdesign");
263  }
264 }
265 
266 
267 void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ )
268 {
269 }
270 
271 
272 void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement )
273 {
276 
277  // if it's a container, start listening at all elements
278  uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
279  if ( xContainer.is() )
280  switchListening( xContainer, true );
281 
282  switchListening( _rxElement, true );
283 }
284 
285 
286 void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement)
287 {
288  switchListening( _rxElement, false );
289 
290  uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY );
291  if ( xContainer.is() )
292  switchListening( xContainer, false );
293 }
294 
295 
296 // XContainerListener
297 
298 void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt)
299 {
300  SolarMutexGuard aSolarGuard;
301  ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
302 
303  // new listener object
304  uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
305  if ( xIface.is() )
306  {
307  AddElement(xIface);
308  }
309 }
310 
311 
312 void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt)
313 {
314  SolarMutexGuard aSolarGuard;
315  ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
316 
317  uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY);
318  OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!");
319  RemoveElement(xIface);
320 
321  xIface.set(evt.Element,uno::UNO_QUERY);
322  AddElement(xIface);
323 }
324 
325 
326 void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt)
327 {
328  SolarMutexGuard aSolarGuard;
329  ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
330 
331  uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY );
332  if ( xIface.is() )
333  {
334  RemoveElement(xIface);
335  }
336 }
337 
338 
339 } // namespace rptui
340 
341 
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::map< Reference< XPropertySet >, ObjectInfo > PropertySetInfoCache
Definition: UndoEnv.cxx:87
std::unique_ptr< ContentProperties > pData
std::map< OUString, bool > AllProperties
virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent &rEvent) override
ULONG m_refCount
static void RemoveEventListener(const Link< VclSimpleEvent &, void > &rEventListener)
OXReportControllerObserver(const OXReportControllerObserver &)=delete
void RemoveSection(const css::uno::Reference< css::report::XSection > &_xSection)
void notifyElementInserted(const css::uno::Reference< css::uno::XInterface > &_rxElement) override
DataChangedEventType GetType() const
void notifyPropertyChange(const css::beans::PropertyChangeEvent &_rEvent) override
static void AddEventListener(const Link< VclSimpleEvent &, void > &rEventListener)
void AddSection(const css::uno::Reference< css::report::XSection > &_xSection)
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
int nCount
AllSettingsFlags GetFlags() const
VclEventId
virtual void SAL_CALL elementInserted(const css::container::ContainerEvent &rEvent) override
void notifyElementInserted(const css::uno::Reference< css::uno::XInterface > &_rxElement) override
#define DBG_UNHANDLED_EXCEPTION(...)
const ::std::unique_ptr< OXReportControllerObserverImpl > m_pImpl
void AddElement(const css::uno::Reference< css::uno::XInterface > &Element)
int i
Mutex aLock
::std::vector< uno::Reference< container::XChild > > m_aSections
void notifyPropertyChange(const css::beans::PropertyChangeEvent &_rEvent) override
IMPL_LINK(OAddFieldWindow, DragBeginHdl, bool &, rUnsetDragIcon, bool)
Definition: AddField.cxx:49
void switchListening(const css::uno::Reference< css::container::XIndexAccess > &_rxContainer, bool _bStartListening)
FormattedFieldBeautifier m_aFormattedFieldBeautifier
virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent &rEvent) override
void RemoveElement(const css::uno::Reference< css::uno::XInterface > &Element)
OXReportControllerObserverImpl & operator=(const OXReportControllerObserverImpl &)=delete
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &evt) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Create an object ob OUndoEnvLock locks the undo possibility As long as in the OUndoEnvLock scope...
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl