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 ); 185 186 // XEventListener 187 virtual void SAL_CALL disposing( const EventObject& _event ); 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( ); 227 static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( ); 228 229 protected: 230 ~FormGeometryHandler(); 231 232 protected: 233 // XPropertyHandler overriables 234 virtual Any SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ); 235 virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ); 236 virtual LineDescriptor SAL_CALL describePropertyLine( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory ); 237 virtual void SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ); 238 virtual void SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ); 239 virtual Sequence< ::rtl::OUString > SAL_CALL getActuatingProperties( ); 240 virtual void SAL_CALL actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ); 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( ) 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( ) 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 ) 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 ) 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 { 456 ::osl::MutexGuard aGuard( m_aMutex ); 457 PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) ); 458 459 LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) ); 460 try 461 { 462 bool bIsSize = false; 463 switch ( nPropId ) 464 { 465 case PROPERTY_ID_WIDTH: 466 case PROPERTY_ID_HEIGHT: 467 bIsSize = true; 468 // NO break! 469 case PROPERTY_ID_POSITIONX: 470 case PROPERTY_ID_POSITIONY: 471 { 472 Optional< double > aZero( sal_True, 0 ); 473 Optional< double > aValueNotPresent( sal_False, 0 ); 474 aLineDesc.Control = PropertyHandlerHelper::createNumericControl( 475 _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent, sal_False ); 476 477 Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW ); 478 xNumericControl->setValueUnit( MeasureUnit::MM_100TH ); 479 xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() ); 480 } 481 break; 482 483 case PROPERTY_ID_TEXT_ANCHOR_TYPE: 484 case PROPERTY_ID_SHEET_ANCHOR_TYPE: 485 // default handling from PropertyHandler is sufficient 486 break; 487 488 default: 489 OSL_ENSURE( false, "FormGeometryHandler::describePropertyLine: huh?" ); 490 break; 491 } 492 } 493 catch( const Exception& ) 494 { 495 DBG_UNHANDLED_EXCEPTION(); 496 } 497 return aLineDesc; 498 } 499 500 //-------------------------------------------------------------------- 501 void SAL_CALL FormGeometryHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) 502 { 503 ::osl::MutexGuard aGuard( m_aMutex ); 504 OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" ); 505 if ( m_xChangeNotifier.is() ) 506 m_xChangeNotifier->addPropertyChangeListener( _listener ); 507 } 508 509 //-------------------------------------------------------------------- 510 void SAL_CALL FormGeometryHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) 511 { 512 ::osl::MutexGuard aGuard( m_aMutex ); 513 OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" ); 514 if ( m_xChangeNotifier.is() ) 515 m_xChangeNotifier->removePropertyChangeListener( _listener ); 516 } 517 518 //-------------------------------------------------------------------- 519 Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( ) 520 { 521 Sequence< ::rtl::OUString > aInterestedIn(1); 522 aInterestedIn[0] = PROPERTY_TEXT_ANCHOR_TYPE; 523 return aInterestedIn; 524 } 525 526 //-------------------------------------------------------------------- 527 void SAL_CALL FormGeometryHandler::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool /*_bFirstTimeInit*/ ) 528 { 529 if ( !_rxInspectorUI.is() ) 530 throw NullPointerException(); 531 532 ::osl::MutexGuard aGuard( m_aMutex ); 533 PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) ); 534 535 switch ( nActuatingPropId ) 536 { 537 case PROPERTY_ID_TEXT_ANCHOR_TYPE: 538 { 539 TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH ); 540 OSL_VERIFY( _rNewValue >>= eAnchorType ); 541 _rxInspectorUI->enablePropertyUI( PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER ); 542 } 543 break; 544 default: 545 OSL_ENSURE( false, "FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" ); 546 break; 547 } 548 } 549 550 //-------------------------------------------------------------------- 551 Sequence< Property > SAL_CALL FormGeometryHandler::doDescribeSupportedProperties() const 552 { 553 if ( !m_xAssociatedShape.is() ) 554 return Sequence< Property >(); 555 556 ::std::vector< Property > aProperties; 557 558 addInt32PropertyDescription( aProperties, PROPERTY_POSITIONX ); 559 addInt32PropertyDescription( aProperties, PROPERTY_POSITIONY ); 560 addInt32PropertyDescription( aProperties, PROPERTY_WIDTH ); 561 addInt32PropertyDescription( aProperties, PROPERTY_HEIGHT ); 562 563 if ( impl_haveTextAnchorType_nothrow() ) 564 implAddPropertyDescription( aProperties, PROPERTY_TEXT_ANCHOR_TYPE, ::cppu::UnoType< TextContentAnchorType >::get() ); 565 566 if ( impl_haveSheetAnchorType_nothrow() ) 567 addInt32PropertyDescription( aProperties, PROPERTY_SHEET_ANCHOR_TYPE ); 568 569 return Sequence< Property >( &(*aProperties.begin()), aProperties.size() ); 570 } 571 572 //-------------------------------------------------------------------- 573 void SAL_CALL FormGeometryHandler::disposing() 574 { 575 FormGeometryHandler_Base::disposing(); 576 577 if ( m_xChangeNotifier.is() ) 578 { 579 m_xChangeNotifier->dispose(); 580 m_xChangeNotifier.clear(); 581 } 582 } 583 584 //-------------------------------------------------------------------- 585 bool FormGeometryHandler::impl_haveTextAnchorType_nothrow() const 586 { 587 ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" ); 588 try 589 { 590 Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW ); 591 if ( xPSI->hasPropertyByName( PROPERTY_ANCHOR_TYPE ) ) 592 return true; 593 } 594 catch( const Exception& ) 595 { 596 DBG_UNHANDLED_EXCEPTION(); 597 } 598 return false; 599 } 600 601 //-------------------------------------------------------------------- 602 bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow() const 603 { 604 ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" ); 605 try 606 { 607 Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW ); 608 if ( !xPSI->hasPropertyByName( PROPERTY_ANCHOR ) ) 609 return false; 610 Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW ); 611 if ( xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) ) ) ) 612 return true; 613 } 614 catch( const Exception& ) 615 { 616 DBG_UNHANDLED_EXCEPTION(); 617 } 618 return false; 619 } 620 621 //-------------------------------------------------------------------- 622 namespace 623 { 624 static sal_Int32 lcl_getLowerBoundRowOrColumn( const Reference< XIndexAccess >& _rxRowsOrColumns, const bool _bRows, 625 const AwtPoint& _rRelativePosition ) 626 { 627 sal_Int32 nAccumulated = 0; 628 629 const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X; 630 631 sal_Int32 nElements = _rxRowsOrColumns->getCount(); 632 sal_Int32 currentPos = 0; 633 for ( currentPos=0; currentPos<nElements; ++currentPos ) 634 { 635 Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW ); 636 637 sal_Bool bIsVisible = sal_True; 638 OSL_VERIFY( xRowOrColumn->getPropertyValue( PROPERTY_IS_VISIBLE ) >>= bIsVisible ); 639 if ( !bIsVisible ) 640 continue; 641 642 sal_Int32 nHeightOrWidth( 0 ); 643 OSL_VERIFY( xRowOrColumn->getPropertyValue( _bRows ? PROPERTY_HEIGHT : PROPERTY_WIDTH ) >>= nHeightOrWidth ); 644 645 if ( nAccumulated + nHeightOrWidth > rRelativePos ) 646 break; 647 648 nAccumulated += nHeightOrWidth; 649 } 650 651 return currentPos; 652 } 653 } 654 655 //-------------------------------------------------------------------- 656 void FormGeometryHandler::impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const 657 { 658 ENSURE_OR_THROW( m_xShapeProperties.is(), "illegal to be called without shape properties." ); 659 try 660 { 661 CellBindingHelper aHelper( m_xComponent, impl_getContextDocument_nothrow() ); 662 // find the sheet which the control belongs to 663 Reference< XSpreadsheet > xSheet; 664 aHelper.getControlSheetIndex( xSheet ); 665 666 switch ( _nAnchorType ) 667 { 668 case ANCHOR_TO_SHEET: 669 OSL_ENSURE( xSheet.is(), 670 "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" ); 671 if ( xSheet.is() ) 672 { 673 AwtPoint aPreservePosition( m_xAssociatedShape->getPosition() ); 674 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, makeAny( xSheet ) ); 675 m_xAssociatedShape->setPosition( aPreservePosition ); 676 } 677 break; 678 679 case ANCHOR_TO_CELL: 680 { 681 Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW ); 682 683 // get the current anchor 684 Reference< XSpreadsheet > xCurrentAnchor; 685 OSL_VERIFY( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ) >>= xCurrentAnchor ); 686 OSL_ENSURE( xCurrentAnchor.is(), "FormGeometryHandler::impl_setSheetAnchorType_nothrow: only to be called when currently anchored to a sheet!" ); 687 688 // get the current position 689 AwtPoint aRelativePosition( m_xAssociatedShape->getPosition() ); 690 691 Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW ); 692 sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols.get(), false, aRelativePosition ); 693 694 Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW ); 695 sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows.get(), true, aRelativePosition ); 696 697 Reference< XCellRange > xSheetCellRange( xSheet, UNO_QUERY_THROW ); 698 Any aNewAnchorCell( xSheetCellRange->getCellByPosition( nNewAnchorCol, nNewAnchorRow ) ); 699 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, aNewAnchorCell ); 700 } 701 break; 702 703 default: 704 OSL_ENSURE( false, "FormGeometryHandler::impl_setSheetAnchorType_nothrow: illegal anchor type!" ); 705 break; 706 } 707 } 708 catch( const Exception& ) 709 { 710 DBG_UNHANDLED_EXCEPTION(); 711 } 712 } 713 714 //==================================================================== 715 //= ShapeGeometryChangeNotifier - implementation 716 //==================================================================== 717 namespace 718 { 719 struct EventTranslation 720 { 721 ::rtl::OUString sPropertyName; 722 Any aNewPropertyValue; 723 724 EventTranslation( const ::rtl::OUString& _propertyName, const Any& _newPropertyValue ) 725 :sPropertyName( _propertyName ) 726 ,aNewPropertyValue( _newPropertyValue ) 727 { 728 } 729 }; 730 } 731 732 //-------------------------------------------------------------------- 733 void SAL_CALL ShapeGeometryChangeNotifier::propertyChange( const PropertyChangeEvent& _event ) 734 { 735 ::comphelper::ComponentMethodGuard aGuard( *this ); 736 737 ::std::vector< EventTranslation > aEventTranslations; 738 aEventTranslations.reserve(2); 739 740 if ( _event.PropertyName.equalsAscii( "Position" ) ) 741 { 742 AwtPoint aPos = m_xShape->getPosition(); 743 aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONX, makeAny( aPos.X ) ) ); 744 aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONY, makeAny( aPos.Y ) ) ); 745 } 746 else if ( _event.PropertyName.equalsAscii( "Size" ) ) 747 { 748 AwtSize aSize = m_xShape->getSize(); 749 aEventTranslations.push_back( EventTranslation( PROPERTY_WIDTH, makeAny( aSize.Width ) ) ); 750 aEventTranslations.push_back( EventTranslation( PROPERTY_HEIGHT, makeAny( aSize.Height ) ) ); 751 } 752 else if ( _event.PropertyName == PROPERTY_ANCHOR_TYPE ) 753 { 754 aEventTranslations.push_back( EventTranslation( PROPERTY_TEXT_ANCHOR_TYPE, makeAny( _event.NewValue ) ) ); 755 } 756 else if ( _event.PropertyName == PROPERTY_ANCHOR ) 757 { 758 aEventTranslations.push_back( EventTranslation( PROPERTY_SHEET_ANCHOR_TYPE, makeAny( _event.NewValue ) ) ); 759 } 760 761 PropertyChangeEvent aTranslatedEvent( _event ); 762 aTranslatedEvent.Source = m_rParent; 763 764 aGuard.clear(); 765 for ( ::std::vector< EventTranslation >::const_iterator t = aEventTranslations.begin(); 766 t != aEventTranslations.end(); 767 ++t 768 ) 769 { 770 aTranslatedEvent.PropertyName = t->sPropertyName; 771 aTranslatedEvent.NewValue = t->aNewPropertyValue; 772 m_aPropertyChangeListeners.notifyEach( &XPropertyChangeListener::propertyChange, aTranslatedEvent ); 773 } 774 } 775 776 //-------------------------------------------------------------------- 777 void SAL_CALL ShapeGeometryChangeNotifier::disposing( const EventObject& /*_event*/ ) 778 { 779 ::comphelper::ComponentMethodGuard aGuard( *this ); 780 impl_dispose_nothrow(); 781 } 782 783 //-------------------------------------------------------------------- 784 void ShapeGeometryChangeNotifier::impl_init_nothrow() 785 { 786 osl_incrementInterlockedCount( &m_refCount ); 787 try 788 { 789 Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW ); 790 xShapeProperties->addPropertyChangeListener( ::rtl::OUString(), this ); 791 } 792 catch( const Exception& ) 793 { 794 DBG_UNHANDLED_EXCEPTION(); 795 } 796 osl_decrementInterlockedCount( &m_refCount ); 797 } 798 799 //-------------------------------------------------------------------- 800 void ShapeGeometryChangeNotifier::impl_dispose_nothrow() 801 { 802 try 803 { 804 Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW ); 805 xShapeProperties->removePropertyChangeListener( ::rtl::OUString(), this ); 806 } 807 catch( const Exception& ) 808 { 809 DBG_UNHANDLED_EXCEPTION(); 810 } 811 812 getBroadcastHelper().bDisposed = true; 813 } 814 815 //........................................................................ 816 } // namespace pcr 817 //........................................................................ 818 819 extern "C" void SAL_CALL createRegistryInfo_FormGeometryHandler() 820 { 821 ::pcr::FormGeometryHandler::registerImplementation(); 822 } 823