diff options
Diffstat (limited to '')
-rw-r--r-- | extensions/source/propctrlr/formgeometryhandler.cxx | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/extensions/source/propctrlr/formgeometryhandler.cxx b/extensions/source/propctrlr/formgeometryhandler.cxx new file mode 100644 index 000000000..99ff37e2e --- /dev/null +++ b/extensions/source/propctrlr/formgeometryhandler.cxx @@ -0,0 +1,824 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include "pcrservices.hxx" +#include "propertyhandler.hxx" +#include "formmetadata.hxx" +#include "formstrings.hxx" +#include "handlerhelper.hxx" +#include "cellbindinghelper.hxx" + +#include <com/sun/star/inspection/XObjectInspectorUI.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/container/XMap.hpp> +#include <com/sun/star/inspection/XNumericControl.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/table/XColumnRowRange.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/form/XGridColumnFactory.hpp> + +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <comphelper/componentbase.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> + +namespace pcr +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::beans::Property; + using ::com::sun::star::awt::XControlModel; + using ::com::sun::star::drawing::XControlShape; + using ::com::sun::star::container::XMap; + using ::com::sun::star::inspection::LineDescriptor; + using ::com::sun::star::inspection::XPropertyControlFactory; + using ::com::sun::star::lang::NullPointerException; + using ::com::sun::star::beans::Optional; + using ::com::sun::star::inspection::XNumericControl; + using ::com::sun::star::drawing::XShape; + using ::com::sun::star::beans::PropertyChangeEvent; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::XPropertyChangeListener; + using ::com::sun::star::text::TextContentAnchorType; + using ::com::sun::star::text::TextContentAnchorType_AT_PARAGRAPH; + using ::com::sun::star::text::TextContentAnchorType_AS_CHARACTER; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::inspection::XObjectInspectorUI; + using ::com::sun::star::lang::XServiceInfo; + using ::com::sun::star::sheet::XSpreadsheet; + using ::com::sun::star::table::XColumnRowRange; + using ::com::sun::star::table::XTableColumns; + using ::com::sun::star::table::XTableRows; + using ::com::sun::star::container::XIndexAccess; + using ::com::sun::star::container::XChild; + using ::com::sun::star::form::XGridColumnFactory; + + namespace MeasureUnit = css::util::MeasureUnit; + + #define ANCHOR_TO_SHEET 0 + #define ANCHOR_TO_CELL 1 + + + //= BroadcastHelperBase + + namespace { + + class BroadcastHelperBase + { + protected: + explicit BroadcastHelperBase( ::osl::Mutex& _rMutex ) + :maBHelper( _rMutex ) + { + } + + protected: + ::cppu::OBroadcastHelper& getBroadcastHelper() { return maBHelper; } + + private: + ::cppu::OBroadcastHelper maBHelper; + }; + + } + + //= ShapeGeometryChangeNotifier - declaration + + /** helper class to work around the ...unfortunate implementation of property change broadcasts + in the XShape implementation, which broadcasts way too generous and unspecified + */ + typedef ::comphelper::ComponentBase ShapeGeometryChangeNotifier_CBase; + typedef ::cppu::WeakImplHelper < css::beans::XPropertyChangeListener + > ShapeGeometryChangeNotifier_IBase; + + namespace { + + class ShapeGeometryChangeNotifier :public BroadcastHelperBase + ,public ShapeGeometryChangeNotifier_CBase + ,public ShapeGeometryChangeNotifier_IBase + { + public: + ShapeGeometryChangeNotifier( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rParentMutex, const Reference< XShape >& _shape ) + :BroadcastHelperBase( _rParentMutex ) + ,ShapeGeometryChangeNotifier_CBase( BroadcastHelperBase::getBroadcastHelper(), ::comphelper::ComponentBase::NoInitializationNeeded() ) + ,ShapeGeometryChangeNotifier_IBase() + ,m_rParent( _rParent ) + ,m_aPropertyChangeListeners( _rParentMutex ) + ,m_xShape( _shape ) + { + ENSURE_OR_THROW( m_xShape.is(), "illegal shape!" ); + impl_init_nothrow(); + } + + // property change broadcasting + void addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) + { + m_aPropertyChangeListeners.addInterface( _listener ); + } + void removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) + { + m_aPropertyChangeListeners.removeInterface( _listener ); + } + + // XComponent equivalent + void dispose() + { + ::osl::MutexGuard aGuard( getMutex() ); + impl_dispose_nothrow(); + } + + // XInterface + virtual void SAL_CALL acquire( ) throw () override + { + m_rParent.acquire(); + } + + virtual void SAL_CALL release( ) throw () override + { + m_rParent.release(); + } + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const PropertyChangeEvent& _event ) override; + + // XEventListener + virtual void SAL_CALL disposing( const EventObject& _event ) override; + + protected: + virtual ~ShapeGeometryChangeNotifier() override + { + if ( !getBroadcastHelper().bDisposed ) + { + acquire(); + dispose(); + } + } + + protected: + ::cppu::OBroadcastHelper& getBroadcastHelper() { return BroadcastHelperBase::getBroadcastHelper(); } + + private: + void impl_init_nothrow(); + void impl_dispose_nothrow(); + + private: + ::cppu::OWeakObject& m_rParent; + ::comphelper::OInterfaceContainerHelper2 m_aPropertyChangeListeners; + Reference< XShape > m_xShape; + }; + + } + + //= FormGeometryHandler - declaration + + namespace { + + class FormGeometryHandler; + + } + + typedef HandlerComponentBase< FormGeometryHandler > FormGeometryHandler_Base; + /** a property handler for any virtual string properties + */ + + namespace { + + class FormGeometryHandler : public FormGeometryHandler_Base + { + public: + explicit FormGeometryHandler( + const Reference< XComponentContext >& _rxContext + ); + + /// @throws RuntimeException + static OUString getImplementationName_static( ); + /// @throws RuntimeException + static Sequence< OUString > getSupportedServiceNames_static( ); + + protected: + virtual ~FormGeometryHandler() override; + + protected: + // XPropertyHandler overriables + virtual Any SAL_CALL getPropertyValue( const OUString& _rPropertyName ) override; + virtual void SAL_CALL setPropertyValue( const OUString& _rPropertyName, const Any& _rValue ) override; + virtual LineDescriptor SAL_CALL describePropertyLine( const OUString& _rPropertyName, const css::uno::Reference< css::inspection::XPropertyControlFactory >& _rxControlFactory ) override; + virtual void SAL_CALL addPropertyChangeListener( const css::uno::Reference< css::beans::XPropertyChangeListener >& _rxListener ) override; + virtual void SAL_CALL removePropertyChangeListener( const css::uno::Reference< css::beans::XPropertyChangeListener >& _rxListener ) override; + virtual Sequence< OUString > SAL_CALL getActuatingProperties( ) override; + virtual void SAL_CALL actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) override; + + // OComponentHandler overridables + virtual void SAL_CALL disposing() override; + + // PropertyHandler overridables + virtual Sequence< Property > doDescribeSupportedProperties() const override; + + protected: + virtual void onNewComponent() override; + + private: + bool impl_haveTextAnchorType_nothrow() const; + bool impl_haveSheetAnchorType_nothrow() const; + void impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const; + + private: + Reference< XControlShape > m_xAssociatedShape; + Reference< XPropertySet > m_xShapeProperties; + ::rtl::Reference< ShapeGeometryChangeNotifier > m_xChangeNotifier; + }; + + } + + //= FormGeometryHandler - implementation + + + FormGeometryHandler::FormGeometryHandler( const Reference< XComponentContext >& _rxContext ) + :FormGeometryHandler_Base( _rxContext ) + { + } + + + FormGeometryHandler::~FormGeometryHandler( ) + { + if ( !rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + } + + + void FormGeometryHandler::onNewComponent() + { + if ( m_xChangeNotifier.is() ) + { + m_xChangeNotifier->dispose(); + m_xChangeNotifier.clear(); + } + m_xAssociatedShape.clear(); + m_xShapeProperties.clear(); + + FormGeometryHandler_Base::onNewComponent(); + + try + { + Reference< XControlModel > xControlModel( m_xComponent, UNO_QUERY ); + if ( xControlModel.is() ) + { + // do not ask the map for shapes for grid control columns... + Reference< XChild > xCompChild( m_xComponent, UNO_QUERY_THROW ); + Reference< XGridColumnFactory > xCheckGrid( xCompChild->getParent(), UNO_QUERY ); + if ( !xCheckGrid.is() ) + { + Reference< XMap > xControlMap; + Any any = m_xContext->getValueByName( "ControlShapeAccess" ); + any >>= xControlMap; + m_xAssociatedShape.set( xControlMap->get( makeAny( xControlModel ) ), UNO_QUERY_THROW ); + m_xShapeProperties.set( m_xAssociatedShape, UNO_QUERY_THROW ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + + if ( m_xAssociatedShape.is() ) + m_xChangeNotifier = new ShapeGeometryChangeNotifier( *this, m_aMutex, m_xAssociatedShape.get() ); + } + + + OUString FormGeometryHandler::getImplementationName_static( ) + { + return "com.sun.star.comp.extensions.FormGeometryHandler"; + } + + + Sequence< OUString > FormGeometryHandler::getSupportedServiceNames_static( ) + { + Sequence<OUString> aSupported { "com.sun.star.form.inspection.FormGeometryHandler" }; + return aSupported; + } + + + Any SAL_CALL FormGeometryHandler::getPropertyValue( const OUString& _rPropertyName ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) ); + + ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this ); + ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: no shape properties!", *this ); + + Any aReturn; + try + { + switch ( nPropId ) + { + case PROPERTY_ID_POSITIONX: + aReturn <<= m_xAssociatedShape->getPosition().X; + break; + case PROPERTY_ID_POSITIONY: + aReturn <<= m_xAssociatedShape->getPosition().Y; + break; + case PROPERTY_ID_WIDTH: + aReturn <<= m_xAssociatedShape->getSize().Width; + break; + case PROPERTY_ID_HEIGHT: + aReturn <<= m_xAssociatedShape->getSize().Height; + break; + case PROPERTY_ID_TEXT_ANCHOR_TYPE: + aReturn = m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR_TYPE ); + OSL_ENSURE( aReturn.hasValue(), "FormGeometryHandler::getPropertyValue: illegal anchor type!" ); + break; + case PROPERTY_ID_SHEET_ANCHOR_TYPE: + { + Reference< XSpreadsheet > xAnchorSheet( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ), UNO_QUERY ); + aReturn <<= sal_Int32( xAnchorSheet.is() ? ANCHOR_TO_SHEET : ANCHOR_TO_CELL ); + } + break; + + default: + OSL_FAIL( "FormGeometryHandler::getPropertyValue: huh?" ); + break; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + return aReturn; + } + + + void SAL_CALL FormGeometryHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) ); + + ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this ); + ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: properties, but no shape!", *this ); + + try + { + switch ( nPropId ) + { + case PROPERTY_ID_POSITIONX: + case PROPERTY_ID_POSITIONY: + { + sal_Int32 nPosition(0); + OSL_VERIFY( _rValue >>= nPosition ); + + css::awt::Point aPos( m_xAssociatedShape->getPosition() ); + if ( nPropId == PROPERTY_ID_POSITIONX ) + aPos.X = nPosition; + else + aPos.Y = nPosition; + m_xAssociatedShape->setPosition( aPos ); + } + break; + + case PROPERTY_ID_WIDTH: + case PROPERTY_ID_HEIGHT: + { + sal_Int32 nSize(0); + OSL_VERIFY( _rValue >>= nSize ); + + css::awt::Size aSize( m_xAssociatedShape->getSize() ); + if ( nPropId == PROPERTY_ID_WIDTH ) + aSize.Width = nSize; + else + aSize.Height = nSize; + m_xAssociatedShape->setSize( aSize ); + } + break; + + case PROPERTY_ID_TEXT_ANCHOR_TYPE: + m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR_TYPE, _rValue ); + break; + + case PROPERTY_ID_SHEET_ANCHOR_TYPE: + { + sal_Int32 nSheetAnchorType = 0; + OSL_VERIFY( _rValue >>= nSheetAnchorType ); + impl_setSheetAnchorType_nothrow( nSheetAnchorType ); + } + break; + + default: + OSL_FAIL( "FormGeometryHandler::getPropertyValue: huh?" ); + break; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + } + + + LineDescriptor SAL_CALL FormGeometryHandler::describePropertyLine( const OUString& _rPropertyName, + const Reference< XPropertyControlFactory >& _rxControlFactory ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) ); + + LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) ); + try + { + bool bIsSize = false; + switch ( nPropId ) + { + case PROPERTY_ID_WIDTH: + case PROPERTY_ID_HEIGHT: + bIsSize = true; + [[fallthrough]]; + case PROPERTY_ID_POSITIONX: + case PROPERTY_ID_POSITIONY: + { + Optional< double > aZero( true, 0 ); + Optional< double > aValueNotPresent( false, 0 ); + aLineDesc.Control = PropertyHandlerHelper::createNumericControl( + _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent ); + + Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW ); + xNumericControl->setValueUnit( MeasureUnit::MM_100TH ); + xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() ); + } + break; + + case PROPERTY_ID_TEXT_ANCHOR_TYPE: + case PROPERTY_ID_SHEET_ANCHOR_TYPE: + // default handling from PropertyHandler is sufficient + break; + + default: + OSL_FAIL( "FormGeometryHandler::describePropertyLine: huh?" ); + break; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + return aLineDesc; + } + + + void SAL_CALL FormGeometryHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" ); + if ( m_xChangeNotifier.is() ) + m_xChangeNotifier->addPropertyChangeListener( _listener ); + } + + + void SAL_CALL FormGeometryHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" ); + if ( m_xChangeNotifier.is() ) + m_xChangeNotifier->removePropertyChangeListener( _listener ); + } + + + Sequence< OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( ) + { + Sequence< OUString > aInterestedIn { PROPERTY_TEXT_ANCHOR_TYPE }; + return aInterestedIn; + } + + + void SAL_CALL FormGeometryHandler::actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool /*_bFirstTimeInit*/ ) + { + if ( !_rxInspectorUI.is() ) + throw NullPointerException(); + + ::osl::MutexGuard aGuard( m_aMutex ); + PropertyId nActuatingPropId( impl_getPropertyId_nothrow( _rActuatingPropertyName ) ); + + switch ( nActuatingPropId ) + { + case PROPERTY_ID_TEXT_ANCHOR_TYPE: + { + TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH ); + OSL_VERIFY( _rNewValue >>= eAnchorType ); + _rxInspectorUI->enablePropertyUI( PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER ); + } + break; + case -1: + throw RuntimeException(); + break; + default: + OSL_FAIL( "FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" ); + break; + } + } + + + Sequence< Property > FormGeometryHandler::doDescribeSupportedProperties() const + { + if ( !m_xAssociatedShape.is() ) + return Sequence< Property >(); + + std::vector< Property > aProperties; + + addInt32PropertyDescription( aProperties, PROPERTY_POSITIONX ); + addInt32PropertyDescription( aProperties, PROPERTY_POSITIONY ); + addInt32PropertyDescription( aProperties, PROPERTY_WIDTH ); + addInt32PropertyDescription( aProperties, PROPERTY_HEIGHT ); + + if ( impl_haveTextAnchorType_nothrow() ) + implAddPropertyDescription( aProperties, PROPERTY_TEXT_ANCHOR_TYPE, ::cppu::UnoType< TextContentAnchorType >::get() ); + + if ( impl_haveSheetAnchorType_nothrow() ) + addInt32PropertyDescription( aProperties, PROPERTY_SHEET_ANCHOR_TYPE ); + + return comphelper::containerToSequence(aProperties); + } + + + void SAL_CALL FormGeometryHandler::disposing() + { + FormGeometryHandler_Base::disposing(); + + if ( m_xChangeNotifier.is() ) + { + m_xChangeNotifier->dispose(); + m_xChangeNotifier.clear(); + } + } + + + bool FormGeometryHandler::impl_haveTextAnchorType_nothrow() const + { + ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" ); + try + { + Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW ); + if ( xPSI->hasPropertyByName( PROPERTY_ANCHOR_TYPE ) ) + return true; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + return false; + } + + + bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow() const + { + ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" ); + try + { + Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW ); + if ( !xPSI->hasPropertyByName( PROPERTY_ANCHOR ) ) + return false; + Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW ); + if ( xSI->supportsService("com.sun.star.sheet.Shape") ) + return true; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + return false; + } + + + namespace + { + sal_Int32 lcl_getLowerBoundRowOrColumn( const Reference< XIndexAccess >& _rxRowsOrColumns, const bool _bRows, + const css::awt::Point& _rRelativePosition ) + { + sal_Int32 nAccumulated = 0; + + const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X; + + sal_Int32 nElements = _rxRowsOrColumns->getCount(); + sal_Int32 currentPos = 0; + for ( currentPos=0; currentPos<nElements; ++currentPos ) + { + Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW ); + + bool bIsVisible = true; + OSL_VERIFY( xRowOrColumn->getPropertyValue( PROPERTY_IS_VISIBLE ) >>= bIsVisible ); + if ( !bIsVisible ) + continue; + + sal_Int32 nHeightOrWidth( 0 ); + OSL_VERIFY( xRowOrColumn->getPropertyValue( _bRows ? OUString(PROPERTY_HEIGHT) : OUString(PROPERTY_WIDTH) ) >>= nHeightOrWidth ); + + if ( nAccumulated + nHeightOrWidth > rRelativePos ) + break; + + nAccumulated += nHeightOrWidth; + } + + return currentPos; + } + } + + + void FormGeometryHandler::impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const + { + ENSURE_OR_THROW( m_xShapeProperties.is(), "illegal to be called without shape properties." ); + try + { + CellBindingHelper aHelper( m_xComponent, impl_getContextDocument_nothrow() ); + // find the sheet which the control belongs to + Reference< XSpreadsheet > xSheet; + aHelper.getControlSheetIndex( xSheet ); + + switch ( _nAnchorType ) + { + case ANCHOR_TO_SHEET: + OSL_ENSURE( xSheet.is(), + "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" ); + if ( xSheet.is() ) + { + css::awt::Point aPreservePosition( m_xAssociatedShape->getPosition() ); + m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, makeAny( xSheet ) ); + m_xAssociatedShape->setPosition( aPreservePosition ); + } + break; + + case ANCHOR_TO_CELL: + { + Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW ); + + // get the current anchor + Reference< XSpreadsheet > xCurrentAnchor; + OSL_VERIFY( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ) >>= xCurrentAnchor ); + OSL_ENSURE( xCurrentAnchor.is(), "FormGeometryHandler::impl_setSheetAnchorType_nothrow: only to be called when currently anchored to a sheet!" ); + + // get the current position + css::awt::Point aRelativePosition( m_xAssociatedShape->getPosition() ); + + Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW ); + sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols.get(), false, aRelativePosition ); + + Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW ); + sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows.get(), true, aRelativePosition ); + + Any aNewAnchorCell( xSheet->getCellByPosition( nNewAnchorCol, nNewAnchorRow ) ); + m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, aNewAnchorCell ); + } + break; + + default: + OSL_FAIL( "FormGeometryHandler::impl_setSheetAnchorType_nothrow: illegal anchor type!" ); + break; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + } + + + //= ShapeGeometryChangeNotifier - implementation + + namespace + { + struct EventTranslation + { + OUString sPropertyName; + Any aNewPropertyValue; + + EventTranslation( const OUString& _propertyName, const Any& _newPropertyValue ) + :sPropertyName( _propertyName ) + ,aNewPropertyValue( _newPropertyValue ) + { + } + }; + } + + + void SAL_CALL ShapeGeometryChangeNotifier::propertyChange( const PropertyChangeEvent& _event ) + { + ::comphelper::ComponentMethodGuard aGuard( *this ); + + std::vector< EventTranslation > aEventTranslations; + aEventTranslations.reserve(2); + + if ( _event.PropertyName == "Position" ) + { + css::awt::Point aPos = m_xShape->getPosition(); + aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONX, makeAny( aPos.X ) ) ); + aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONY, makeAny( aPos.Y ) ) ); + } + else if ( _event.PropertyName == "Size" ) + { + css::awt::Size aSize = m_xShape->getSize(); + aEventTranslations.push_back( EventTranslation( PROPERTY_WIDTH, makeAny( aSize.Width ) ) ); + aEventTranslations.push_back( EventTranslation( PROPERTY_HEIGHT, makeAny( aSize.Height ) ) ); + } + else if ( _event.PropertyName == PROPERTY_ANCHOR_TYPE ) + { + aEventTranslations.push_back( EventTranslation( PROPERTY_TEXT_ANCHOR_TYPE, _event.NewValue ) ); + } + else if ( _event.PropertyName == PROPERTY_ANCHOR ) + { + aEventTranslations.push_back( EventTranslation( PROPERTY_SHEET_ANCHOR_TYPE, _event.NewValue ) ); + } + + PropertyChangeEvent aTranslatedEvent( _event ); + aTranslatedEvent.Source = m_rParent; + + aGuard.clear(); + for (auto const& eventTranslation : aEventTranslations) + { + aTranslatedEvent.PropertyName = eventTranslation.sPropertyName; + aTranslatedEvent.NewValue = eventTranslation.aNewPropertyValue; + m_aPropertyChangeListeners.notifyEach( &XPropertyChangeListener::propertyChange, aTranslatedEvent ); + } + } + + + void SAL_CALL ShapeGeometryChangeNotifier::disposing( const EventObject& /*_event*/ ) + { + ::comphelper::ComponentMethodGuard aGuard( *this ); + impl_dispose_nothrow(); + } + + + void ShapeGeometryChangeNotifier::impl_init_nothrow() + { + osl_atomic_increment( &m_refCount ); + try + { + Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW ); + xShapeProperties->addPropertyChangeListener( OUString(), this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + osl_atomic_decrement( &m_refCount ); + } + + + void ShapeGeometryChangeNotifier::impl_dispose_nothrow() + { + try + { + Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW ); + xShapeProperties->removePropertyChangeListener( OUString(), this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); + } + + getBroadcastHelper().bDisposed = true; + } + + +} // namespace pcr + + +extern "C" void createRegistryInfo_FormGeometryHandler() +{ + ::pcr::FormGeometryHandler::registerImplementation(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |