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