1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 // MARKER(update_precomp.py): autogen include statement, do not remove 28 #include "precompiled_extensions.hxx" 29 30 #include "propertyhandler.hxx" 31 #include "formmetadata.hxx" 32 #include "formstrings.hxx" 33 #include "handlerhelper.hxx" 34 #include "cellbindinghelper.hxx" 35 36 /** === begin UNO includes === **/ 37 #include <com/sun/star/inspection/XObjectInspectorUI.hpp> 38 #include <com/sun/star/awt/XControlModel.hpp> 39 #include <com/sun/star/drawing/XControlShape.hpp> 40 #include <com/sun/star/container/XMap.hpp> 41 #include <com/sun/star/inspection/XNumericControl.hpp> 42 #include <com/sun/star/util/MeasureUnit.hpp> 43 #include <com/sun/star/text/TextContentAnchorType.hpp> 44 #include <com/sun/star/lang/XServiceInfo.hpp> 45 #include <com/sun/star/sheet/XSpreadsheet.hpp> 46 #include <com/sun/star/table/XColumnRowRange.hpp> 47 #include <com/sun/star/table/XCellRange.hpp> 48 #include <com/sun/star/container/XChild.hpp> 49 #include <com/sun/star/form/XGridColumnFactory.hpp> 50 /** === end UNO includes === **/ 51 52 #include <cppuhelper/interfacecontainer.hxx> 53 #include <comphelper/componentbase.hxx> 54 #include <tools/debug.hxx> 55 #include <tools/diagnose_ex.h> 56 57 //........................................................................ 58 namespace pcr 59 { 60 //........................................................................ 61 62 /** === begin UNO using === **/ 63 using ::com::sun::star::uno::Reference; 64 using ::com::sun::star::uno::XInterface; 65 using ::com::sun::star::uno::UNO_QUERY; 66 using ::com::sun::star::uno::UNO_QUERY_THROW; 67 using ::com::sun::star::uno::UNO_SET_THROW; 68 using ::com::sun::star::uno::Exception; 69 using ::com::sun::star::uno::RuntimeException; 70 using ::com::sun::star::uno::Any; 71 using ::com::sun::star::uno::makeAny; 72 using ::com::sun::star::uno::Sequence; 73 using ::com::sun::star::uno::Type; 74 using ::com::sun::star::uno::XComponentContext; 75 using ::com::sun::star::beans::UnknownPropertyException; 76 using ::com::sun::star::beans::Property; 77 using ::com::sun::star::awt::XControlModel; 78 using ::com::sun::star::drawing::XControlShape; 79 using ::com::sun::star::container::XMap; 80 using ::com::sun::star::inspection::LineDescriptor; 81 using ::com::sun::star::inspection::XPropertyControlFactory; 82 using ::com::sun::star::lang::NullPointerException; 83 using ::com::sun::star::beans::Optional; 84 using ::com::sun::star::inspection::XNumericControl; 85 using ::com::sun::star::drawing::XShape; 86 using ::com::sun::star::beans::PropertyChangeEvent; 87 using ::com::sun::star::lang::EventObject; 88 using ::com::sun::star::beans::XPropertySet; 89 using ::com::sun::star::beans::XPropertyChangeListener; 90 using ::com::sun::star::text::TextContentAnchorType; 91 using ::com::sun::star::text::TextContentAnchorType_AT_PARAGRAPH; 92 using ::com::sun::star::text::TextContentAnchorType_AS_CHARACTER; 93 using ::com::sun::star::beans::XPropertySetInfo; 94 using ::com::sun::star::inspection::XObjectInspectorUI; 95 using ::com::sun::star::lang::XServiceInfo; 96 using ::com::sun::star::sheet::XSpreadsheet; 97 using ::com::sun::star::table::XColumnRowRange; 98 using ::com::sun::star::table::XTableColumns; 99 using ::com::sun::star::table::XTableRows; 100 using ::com::sun::star::table::XCellRange; 101 using ::com::sun::star::container::XIndexAccess; 102 using ::com::sun::star::container::XChild; 103 using ::com::sun::star::form::XGridColumnFactory; 104 /** === end UNO using === **/ 105 namespace MeasureUnit = ::com::sun::star::util::MeasureUnit; 106 107 typedef ::com::sun::star::awt::Point AwtPoint; 108 typedef ::com::sun::star::awt::Size AwtSize; 109 110 #define ANCHOR_TO_SHEET 0 111 #define ANCHOR_TO_CELL 1 112 113 //==================================================================== 114 //= BroadcastHelperBase 115 //==================================================================== 116 class BroadcastHelperBase 117 { 118 protected: 119 BroadcastHelperBase( ::osl::Mutex& _rMutex ) 120 :maBHelper( _rMutex ) 121 { 122 } 123 124 protected: 125 ::cppu::OBroadcastHelper& getBroadcastHelper() { return maBHelper; } 126 127 private: 128 ::cppu::OBroadcastHelper maBHelper; 129 }; 130 131 //==================================================================== 132 //= ShapeGeometryChangeNotifier - declaration 133 //==================================================================== 134 /** helper class to work around the ...unfortunate implementation of property change broadcasts 135 in the XShape implementation, which broadcasts way too generous and unspecified 136 */ 137 typedef ::comphelper::ComponentBase ShapeGeometryChangeNotifier_CBase; 138 typedef ::cppu::WeakImplHelper1 < ::com::sun::star::beans::XPropertyChangeListener 139 > ShapeGeometryChangeNotifier_IBase; 140 141 class ShapeGeometryChangeNotifier :public BroadcastHelperBase 142 ,public ShapeGeometryChangeNotifier_CBase 143 ,public ShapeGeometryChangeNotifier_IBase 144 { 145 public: 146 ShapeGeometryChangeNotifier( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rParentMutex, const Reference< XShape >& _shape ) 147 :BroadcastHelperBase( _rParentMutex ) 148 ,ShapeGeometryChangeNotifier_CBase( BroadcastHelperBase::getBroadcastHelper(), ::comphelper::ComponentBase::NoInitializationNeeded() ) 149 ,ShapeGeometryChangeNotifier_IBase() 150 ,m_rParent( _rParent ) 151 ,m_aPropertyChangeListeners( _rParentMutex ) 152 ,m_xShape( _shape ) 153 { 154 ENSURE_OR_THROW( m_xShape.is(), "illegal shape!" ); 155 impl_init_nothrow(); 156 } 157 158 // property change broadcasting 159 void addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) 160 { 161 m_aPropertyChangeListeners.addInterface( _listener ); 162 } 163 void removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) 164 { 165 m_aPropertyChangeListeners.removeInterface( _listener ); 166 } 167 168 // XComponent equivalent 169 void dispose() 170 { 171 ::osl::MutexGuard aGuard( getMutex() ); 172 impl_dispose_nothrow(); 173 } 174 175 // XInterface 176 virtual void SAL_CALL acquire( ) throw () 177 { 178 m_rParent.acquire(); 179 } 180 181 virtual void SAL_CALL release( ) throw () 182 { 183 m_rParent.release(); 184 } 185 186 // XPropertyChangeListener 187 virtual void SAL_CALL propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException); 188 189 // XEventListener 190 virtual void SAL_CALL disposing( const EventObject& _event ) throw (RuntimeException); 191 192 protected: 193 virtual ~ShapeGeometryChangeNotifier() 194 { 195 if ( !getBroadcastHelper().bDisposed ) 196 { 197 acquire(); 198 dispose(); 199 } 200 } 201 202 protected: 203 ::cppu::OBroadcastHelper& getBroadcastHelper() { return BroadcastHelperBase::getBroadcastHelper(); } 204 205 private: 206 void impl_init_nothrow(); 207 void impl_dispose_nothrow(); 208 209 private: 210 ::cppu::OWeakObject& m_rParent; 211 ::cppu::OInterfaceContainerHelper m_aPropertyChangeListeners; 212 Reference< XShape > m_xShape; 213 }; 214 215 //==================================================================== 216 //= FormGeometryHandler - declaration 217 //==================================================================== 218 class FormGeometryHandler; 219 typedef HandlerComponentBase< FormGeometryHandler > FormGeometryHandler_Base; 220 /** a property handler for any virtual string properties 221 */ 222 class FormGeometryHandler : public FormGeometryHandler_Base 223 { 224 public: 225 FormGeometryHandler( 226 const Reference< XComponentContext >& _rxContext 227 ); 228 229 static ::rtl::OUString SAL_CALL getImplementationName_static( ) throw (RuntimeException); 230 static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( ) throw (RuntimeException); 231 232 protected: 233 ~FormGeometryHandler(); 234 235 protected: 236 // XPropertyHandler overriables 237 virtual Any SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException); 238 virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException); 239 virtual LineDescriptor SAL_CALL describePropertyLine( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 240 virtual void SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException); 241 virtual void SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException); 242 virtual Sequence< ::rtl::OUString > SAL_CALL getActuatingProperties( ) throw (RuntimeException); 243 virtual void SAL_CALL actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (NullPointerException, RuntimeException); 244 245 // OComponentHandler overridables 246 virtual void SAL_CALL disposing(); 247 248 // PropertyHandler overridables 249 virtual Sequence< Property > SAL_CALL doDescribeSupportedProperties() const; 250 251 protected: 252 virtual void onNewComponent(); 253 254 private: 255 bool impl_haveTextAnchorType_nothrow() const; 256 bool impl_haveSheetAnchorType_nothrow() const; 257 void impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const; 258 259 private: 260 Reference< XControlShape > m_xAssociatedShape; 261 Reference< XPropertySet > m_xShapeProperties; 262 ::rtl::Reference< ShapeGeometryChangeNotifier > m_xChangeNotifier; 263 }; 264 265 //==================================================================== 266 //= FormGeometryHandler - implementation 267 //==================================================================== 268 DBG_NAME( FormGeometryHandler ) 269 //-------------------------------------------------------------------- 270 FormGeometryHandler::FormGeometryHandler( const Reference< XComponentContext >& _rxContext ) 271 :FormGeometryHandler_Base( _rxContext ) 272 { 273 DBG_CTOR( FormGeometryHandler, NULL ); 274 } 275 276 //-------------------------------------------------------------------- 277 FormGeometryHandler::~FormGeometryHandler( ) 278 { 279 if ( !rBHelper.bDisposed ) 280 { 281 acquire(); 282 dispose(); 283 } 284 285 DBG_DTOR( FormGeometryHandler, NULL ); 286 } 287 288 //-------------------------------------------------------------------- 289 void FormGeometryHandler::onNewComponent() 290 { 291 if ( m_xChangeNotifier.is() ) 292 { 293 m_xChangeNotifier->dispose(); 294 m_xChangeNotifier.clear(); 295 } 296 m_xAssociatedShape.clear(); 297 m_xShapeProperties.clear(); 298 299 FormGeometryHandler_Base::onNewComponent(); 300 301 try 302 { 303 Reference< XControlModel > xControlModel( m_xComponent, UNO_QUERY ); 304 if ( xControlModel.is() ) 305 { 306 // do not ask the map for shapes for grid control columns .... 307 Reference< XChild > xCompChild( m_xComponent, UNO_QUERY_THROW ); 308 Reference< XGridColumnFactory > xCheckGrid( xCompChild->getParent(), UNO_QUERY ); 309 if ( !xCheckGrid.is() ) 310 { 311 Reference< XMap > xControlMap( m_aContext.getContextValueByAsciiName( "ControlShapeAccess" ), UNO_QUERY_THROW ); 312 m_xAssociatedShape.set( xControlMap->get( makeAny( xControlModel ) ), UNO_QUERY_THROW ); 313 m_xShapeProperties.set( m_xAssociatedShape, UNO_QUERY_THROW ); 314 } 315 } 316 } 317 catch( const Exception& ) 318 { 319 DBG_UNHANDLED_EXCEPTION(); 320 } 321 322 if ( m_xAssociatedShape.is() ) 323 m_xChangeNotifier = new ShapeGeometryChangeNotifier( *this, m_aMutex, m_xAssociatedShape.get() ); 324 } 325 326 //-------------------------------------------------------------------- 327 ::rtl::OUString SAL_CALL FormGeometryHandler::getImplementationName_static( ) throw (RuntimeException) 328 { 329 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.FormGeometryHandler" ) ); 330 } 331 332 //-------------------------------------------------------------------- 333 Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getSupportedServiceNames_static( ) throw (RuntimeException) 334 { 335 Sequence< ::rtl::OUString > aSupported( 1 ); 336 aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.FormGeometryHandler" ) ); 337 return aSupported; 338 } 339 340 //-------------------------------------------------------------------- 341 Any SAL_CALL FormGeometryHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException) 342 { 343 ::osl::MutexGuard aGuard( m_aMutex ); 344 PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) ); 345 346 ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this ); 347 ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: no shape properties!", *this ); 348 349 Any aReturn; 350 try 351 { 352 switch ( nPropId ) 353 { 354 case PROPERTY_ID_POSITIONX: 355 aReturn <<= m_xAssociatedShape->getPosition().X; 356 break; 357 case PROPERTY_ID_POSITIONY: 358 aReturn <<= m_xAssociatedShape->getPosition().Y; 359 break; 360 case PROPERTY_ID_WIDTH: 361 aReturn <<= m_xAssociatedShape->getSize().Width; 362 break; 363 case PROPERTY_ID_HEIGHT: 364 aReturn <<= m_xAssociatedShape->getSize().Height; 365 break; 366 case PROPERTY_ID_TEXT_ANCHOR_TYPE: 367 aReturn = m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR_TYPE ); 368 OSL_ENSURE( aReturn.hasValue(), "FormGeometryHandler::getPropertyValue: illegal anchor type!" ); 369 break; 370 case PROPERTY_ID_SHEET_ANCHOR_TYPE: 371 { 372 Reference< XSpreadsheet > xAnchorSheet( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ), UNO_QUERY ); 373 aReturn <<= sal_Int32( xAnchorSheet.is() ? ANCHOR_TO_SHEET : ANCHOR_TO_CELL ); 374 } 375 break; 376 377 default: 378 OSL_ENSURE( false, "FormGeometryHandler::getPropertyValue: huh?" ); 379 break; 380 } 381 } 382 catch( const Exception& ) 383 { 384 DBG_UNHANDLED_EXCEPTION(); 385 } 386 return aReturn; 387 } 388 389 //-------------------------------------------------------------------- 390 void SAL_CALL FormGeometryHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException) 391 { 392 ::osl::MutexGuard aGuard( m_aMutex ); 393 PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) ); 394 395 ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this ); 396 ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: properties, but no shape!", *this ); 397 398 try 399 { 400 switch ( nPropId ) 401 { 402 case PROPERTY_ID_POSITIONX: 403 case PROPERTY_ID_POSITIONY: 404 { 405 sal_Int32 nPosition(0); 406 OSL_VERIFY( _rValue >>= nPosition ); 407 408 AwtPoint aPos( m_xAssociatedShape->getPosition() ); 409 if ( nPropId == PROPERTY_ID_POSITIONX ) 410 aPos.X = nPosition; 411 else 412 aPos.Y = nPosition; 413 m_xAssociatedShape->setPosition( aPos ); 414 } 415 break; 416 417 case PROPERTY_ID_WIDTH: 418 case PROPERTY_ID_HEIGHT: 419 { 420 sal_Int32 nSize(0); 421 OSL_VERIFY( _rValue >>= nSize ); 422 423 AwtSize aSize( m_xAssociatedShape->getSize() ); 424 if ( nPropId == PROPERTY_ID_WIDTH ) 425 aSize.Width = nSize; 426 else 427 aSize.Height = nSize; 428 m_xAssociatedShape->setSize( aSize ); 429 } 430 break; 431 432 case PROPERTY_ID_TEXT_ANCHOR_TYPE: 433 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR_TYPE, _rValue ); 434 break; 435 436 case PROPERTY_ID_SHEET_ANCHOR_TYPE: 437 { 438 sal_Int32 nSheetAnchorType = 0; 439 OSL_VERIFY( _rValue >>= nSheetAnchorType ); 440 impl_setSheetAnchorType_nothrow( nSheetAnchorType ); 441 } 442 break; 443 444 default: 445 OSL_ENSURE( false, "FormGeometryHandler::getPropertyValue: huh?" ); 446 break; 447 } 448 } 449 catch( const Exception& ) 450 { 451 DBG_UNHANDLED_EXCEPTION(); 452 } 453 } 454 455 //-------------------------------------------------------------------- 456 LineDescriptor SAL_CALL FormGeometryHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName, 457 const Reference< XPropertyControlFactory >& _rxControlFactory ) 458 throw (UnknownPropertyException, NullPointerException, RuntimeException) 459 { 460 ::osl::MutexGuard aGuard( m_aMutex ); 461 PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) ); 462 463 LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) ); 464 try 465 { 466 bool bIsSize = false; 467 switch ( nPropId ) 468 { 469 case PROPERTY_ID_WIDTH: 470 case PROPERTY_ID_HEIGHT: 471 bIsSize = true; 472 // NO break! 473 case PROPERTY_ID_POSITIONX: 474 case PROPERTY_ID_POSITIONY: 475 { 476 Optional< double > aZero( sal_True, 0 ); 477 Optional< double > aValueNotPresent( sal_False, 0 ); 478 aLineDesc.Control = PropertyHandlerHelper::createNumericControl( 479 _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent, sal_False ); 480 481 Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW ); 482 xNumericControl->setValueUnit( MeasureUnit::MM_100TH ); 483 xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() ); 484 } 485 break; 486 487 case PROPERTY_ID_TEXT_ANCHOR_TYPE: 488 case PROPERTY_ID_SHEET_ANCHOR_TYPE: 489 // default handling from PropertyHandler is sufficient 490 break; 491 492 default: 493 OSL_ENSURE( false, "FormGeometryHandler::describePropertyLine: huh?" ); 494 break; 495 } 496 } 497 catch( const Exception& ) 498 { 499 DBG_UNHANDLED_EXCEPTION(); 500 } 501 return aLineDesc; 502 } 503 504 //-------------------------------------------------------------------- 505 void SAL_CALL FormGeometryHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException) 506 { 507 ::osl::MutexGuard aGuard( m_aMutex ); 508 OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" ); 509 if ( m_xChangeNotifier.is() ) 510 m_xChangeNotifier->addPropertyChangeListener( _listener ); 511 } 512 513 //-------------------------------------------------------------------- 514 void SAL_CALL FormGeometryHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException) 515 { 516 ::osl::MutexGuard aGuard( m_aMutex ); 517 OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" ); 518 if ( m_xChangeNotifier.is() ) 519 m_xChangeNotifier->removePropertyChangeListener( _listener ); 520 } 521 522 //-------------------------------------------------------------------- 523 Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( ) throw (RuntimeException) 524 { 525 Sequence< ::rtl::OUString > aInterestedIn(1); 526 aInterestedIn[0] = PROPERTY_TEXT_ANCHOR_TYPE; 527 return aInterestedIn; 528 } 529 530 //-------------------------------------------------------------------- 531 void SAL_CALL FormGeometryHandler::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException) 532 { 533 if ( !_rxInspectorUI.is() ) 534 throw NullPointerException(); 535 536 ::osl::MutexGuard aGuard( m_aMutex ); 537 PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) ); 538 539 switch ( nActuatingPropId ) 540 { 541 case PROPERTY_ID_TEXT_ANCHOR_TYPE: 542 { 543 TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH ); 544 OSL_VERIFY( _rNewValue >>= eAnchorType ); 545 _rxInspectorUI->enablePropertyUI( PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER ); 546 } 547 break; 548 default: 549 OSL_ENSURE( false, "FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" ); 550 break; 551 } 552 } 553 554 //-------------------------------------------------------------------- 555 Sequence< Property > SAL_CALL FormGeometryHandler::doDescribeSupportedProperties() const 556 { 557 if ( !m_xAssociatedShape.is() ) 558 return Sequence< Property >(); 559 560 ::std::vector< Property > aProperties; 561 562 addInt32PropertyDescription( aProperties, PROPERTY_POSITIONX ); 563 addInt32PropertyDescription( aProperties, PROPERTY_POSITIONY ); 564 addInt32PropertyDescription( aProperties, PROPERTY_WIDTH ); 565 addInt32PropertyDescription( aProperties, PROPERTY_HEIGHT ); 566 567 if ( impl_haveTextAnchorType_nothrow() ) 568 implAddPropertyDescription( aProperties, PROPERTY_TEXT_ANCHOR_TYPE, ::cppu::UnoType< TextContentAnchorType >::get() ); 569 570 if ( impl_haveSheetAnchorType_nothrow() ) 571 addInt32PropertyDescription( aProperties, PROPERTY_SHEET_ANCHOR_TYPE ); 572 573 return Sequence< Property >( &(*aProperties.begin()), aProperties.size() ); 574 } 575 576 //-------------------------------------------------------------------- 577 void SAL_CALL FormGeometryHandler::disposing() 578 { 579 FormGeometryHandler_Base::disposing(); 580 581 if ( m_xChangeNotifier.is() ) 582 { 583 m_xChangeNotifier->dispose(); 584 m_xChangeNotifier.clear(); 585 } 586 } 587 588 //-------------------------------------------------------------------- 589 bool FormGeometryHandler::impl_haveTextAnchorType_nothrow() const 590 { 591 ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" ); 592 try 593 { 594 Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW ); 595 if ( xPSI->hasPropertyByName( PROPERTY_ANCHOR_TYPE ) ) 596 return true; 597 } 598 catch( const Exception& ) 599 { 600 DBG_UNHANDLED_EXCEPTION(); 601 } 602 return false; 603 } 604 605 //-------------------------------------------------------------------- 606 bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow() const 607 { 608 ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" ); 609 try 610 { 611 Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW ); 612 if ( !xPSI->hasPropertyByName( PROPERTY_ANCHOR ) ) 613 return false; 614 Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW ); 615 if ( xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) ) ) ) 616 return true; 617 } 618 catch( const Exception& ) 619 { 620 DBG_UNHANDLED_EXCEPTION(); 621 } 622 return false; 623 } 624 625 //-------------------------------------------------------------------- 626 namespace 627 { 628 static sal_Int32 lcl_getLowerBoundRowOrColumn( const Reference< XIndexAccess >& _rxRowsOrColumns, const bool _bRows, 629 const AwtPoint& _rRelativePosition ) 630 { 631 sal_Int32 nAccumulated = 0; 632 633 const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X; 634 635 sal_Int32 nElements = _rxRowsOrColumns->getCount(); 636 sal_Int32 currentPos = 0; 637 for ( currentPos=0; currentPos<nElements; ++currentPos ) 638 { 639 Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW ); 640 641 sal_Bool bIsVisible = sal_True; 642 OSL_VERIFY( xRowOrColumn->getPropertyValue( PROPERTY_IS_VISIBLE ) >>= bIsVisible ); 643 if ( !bIsVisible ) 644 continue; 645 646 sal_Int32 nHeightOrWidth( 0 ); 647 OSL_VERIFY( xRowOrColumn->getPropertyValue( _bRows ? PROPERTY_HEIGHT : PROPERTY_WIDTH ) >>= nHeightOrWidth ); 648 649 if ( nAccumulated + nHeightOrWidth > rRelativePos ) 650 break; 651 652 nAccumulated += nHeightOrWidth; 653 } 654 655 return currentPos; 656 } 657 } 658 659 //-------------------------------------------------------------------- 660 void FormGeometryHandler::impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const 661 { 662 ENSURE_OR_THROW( m_xShapeProperties.is(), "illegal to be called without shape properties." ); 663 try 664 { 665 CellBindingHelper aHelper( m_xComponent, impl_getContextDocument_nothrow() ); 666 // find the sheet which the control belongs to 667 Reference< XSpreadsheet > xSheet; 668 aHelper.getControlSheetIndex( xSheet ); 669 670 switch ( _nAnchorType ) 671 { 672 case ANCHOR_TO_SHEET: 673 OSL_ENSURE( xSheet.is(), 674 "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" ); 675 if ( xSheet.is() ) 676 { 677 AwtPoint aPreservePosition( m_xAssociatedShape->getPosition() ); 678 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, makeAny( xSheet ) ); 679 m_xAssociatedShape->setPosition( aPreservePosition ); 680 } 681 break; 682 683 case ANCHOR_TO_CELL: 684 { 685 Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW ); 686 687 // get the current anchor 688 Reference< XSpreadsheet > xCurrentAnchor; 689 OSL_VERIFY( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ) >>= xCurrentAnchor ); 690 OSL_ENSURE( xCurrentAnchor.is(), "FormGeometryHandler::impl_setSheetAnchorType_nothrow: only to be called when currently anchored to a sheet!" ); 691 692 // get the current position 693 AwtPoint aRelativePosition( m_xAssociatedShape->getPosition() ); 694 695 Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW ); 696 sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols.get(), false, aRelativePosition ); 697 698 Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW ); 699 sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows.get(), true, aRelativePosition ); 700 701 Reference< XCellRange > xSheetCellRange( xSheet, UNO_QUERY_THROW ); 702 Any aNewAnchorCell( xSheetCellRange->getCellByPosition( nNewAnchorCol, nNewAnchorRow ) ); 703 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, aNewAnchorCell ); 704 } 705 break; 706 707 default: 708 OSL_ENSURE( false, "FormGeometryHandler::impl_setSheetAnchorType_nothrow: illegal anchor type!" ); 709 break; 710 } 711 } 712 catch( const Exception& ) 713 { 714 DBG_UNHANDLED_EXCEPTION(); 715 } 716 } 717 718 //==================================================================== 719 //= ShapeGeometryChangeNotifier - implementation 720 //==================================================================== 721 namespace 722 { 723 struct EventTranslation 724 { 725 ::rtl::OUString sPropertyName; 726 Any aNewPropertyValue; 727 728 EventTranslation( const ::rtl::OUString& _propertyName, const Any& _newPropertyValue ) 729 :sPropertyName( _propertyName ) 730 ,aNewPropertyValue( _newPropertyValue ) 731 { 732 } 733 }; 734 } 735 736 //-------------------------------------------------------------------- 737 void SAL_CALL ShapeGeometryChangeNotifier::propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException) 738 { 739 ::comphelper::ComponentMethodGuard aGuard( *this ); 740 741 ::std::vector< EventTranslation > aEventTranslations; 742 aEventTranslations.reserve(2); 743 744 if ( _event.PropertyName.equalsAscii( "Position" ) ) 745 { 746 AwtPoint aPos = m_xShape->getPosition(); 747 aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONX, makeAny( aPos.X ) ) ); 748 aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONY, makeAny( aPos.Y ) ) ); 749 } 750 else if ( _event.PropertyName.equalsAscii( "Size" ) ) 751 { 752 AwtSize aSize = m_xShape->getSize(); 753 aEventTranslations.push_back( EventTranslation( PROPERTY_WIDTH, makeAny( aSize.Width ) ) ); 754 aEventTranslations.push_back( EventTranslation( PROPERTY_HEIGHT, makeAny( aSize.Height ) ) ); 755 } 756 else if ( _event.PropertyName == PROPERTY_ANCHOR_TYPE ) 757 { 758 aEventTranslations.push_back( EventTranslation( PROPERTY_TEXT_ANCHOR_TYPE, makeAny( _event.NewValue ) ) ); 759 } 760 else if ( _event.PropertyName == PROPERTY_ANCHOR ) 761 { 762 aEventTranslations.push_back( EventTranslation( PROPERTY_SHEET_ANCHOR_TYPE, makeAny( _event.NewValue ) ) ); 763 } 764 765 PropertyChangeEvent aTranslatedEvent( _event ); 766 aTranslatedEvent.Source = m_rParent; 767 768 aGuard.clear(); 769 for ( ::std::vector< EventTranslation >::const_iterator t = aEventTranslations.begin(); 770 t != aEventTranslations.end(); 771 ++t 772 ) 773 { 774 aTranslatedEvent.PropertyName = t->sPropertyName; 775 aTranslatedEvent.NewValue = t->aNewPropertyValue; 776 m_aPropertyChangeListeners.notifyEach( &XPropertyChangeListener::propertyChange, aTranslatedEvent ); 777 } 778 } 779 780 //-------------------------------------------------------------------- 781 void SAL_CALL ShapeGeometryChangeNotifier::disposing( const EventObject& /*_event*/ ) throw (RuntimeException) 782 { 783 ::comphelper::ComponentMethodGuard aGuard( *this ); 784 impl_dispose_nothrow(); 785 } 786 787 //-------------------------------------------------------------------- 788 void ShapeGeometryChangeNotifier::impl_init_nothrow() 789 { 790 osl_incrementInterlockedCount( &m_refCount ); 791 try 792 { 793 Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW ); 794 xShapeProperties->addPropertyChangeListener( ::rtl::OUString(), this ); 795 } 796 catch( const Exception& ) 797 { 798 DBG_UNHANDLED_EXCEPTION(); 799 } 800 osl_decrementInterlockedCount( &m_refCount ); 801 } 802 803 //-------------------------------------------------------------------- 804 void ShapeGeometryChangeNotifier::impl_dispose_nothrow() 805 { 806 try 807 { 808 Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW ); 809 xShapeProperties->removePropertyChangeListener( ::rtl::OUString(), this ); 810 } 811 catch( const Exception& ) 812 { 813 DBG_UNHANDLED_EXCEPTION(); 814 } 815 816 getBroadcastHelper().bDisposed = true; 817 } 818 819 //........................................................................ 820 } // namespace pcr 821 //........................................................................ 822 823 extern "C" void SAL_CALL createRegistryInfo_FormGeometryHandler() 824 { 825 ::pcr::FormGeometryHandler::registerImplementation(); 826 } 827