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