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 70 OXReportControllerObserverImpl::OXReportControllerObserverImpl(const OReportController& _rController) 71 :m_rReportController(_rController) 72 ,m_nLocks(0) 73 ,m_bReadOnly(sal_False) 74 { 75 } 76 77 OXReportControllerObserverImpl::~OXReportControllerObserverImpl() 78 { 79 } 80 81 // ----------------------------------------------------------------------------- 82 // ----------------------------------------------------------------------------- 83 // ----------------------------------------------------------------------------- 84 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 97 OXReportControllerObserver::~OXReportControllerObserver() 98 { 99 DBG_CTOR( rpt_OXReportControllerObserver,NULL); 100 Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) ); 101 } 102 103 // ----------------------------------------------------------------------------- 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 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 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 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 // ----------------------------------------------------------------------------- 216 void OXReportControllerObserver::Lock() 217 { 218 OSL_ENSURE(m_refCount,"Illegal call to dead object!"); 219 osl_incrementInterlockedCount( &m_pImpl->m_nLocks ); 220 } 221 void OXReportControllerObserver::UnLock() 222 { 223 OSL_ENSURE(m_refCount,"Illegal call to dead object!"); 224 225 osl_decrementInterlockedCount( &m_pImpl->m_nLocks ); 226 } 227 sal_Bool OXReportControllerObserver::IsLocked() const { return m_pImpl->m_nLocks != 0; } 228 229 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 364 void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ ) throw (uno::RuntimeException) 365 { 366 // implSetModified(); 367 } 368 369 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 // ----------------------------------------------------------------------------- 397 ::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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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