f49d8ce461
Change-Id: I32f74fe67e8eb0b6b12ee60405c3d99932b75182 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167284 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
821 lines
29 KiB
C++
821 lines
29 KiB
C++
/* -*- 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 "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/interfacecontainer2.hxx>
|
|
#include <comphelper/componentbase.hxx>
|
|
#include <rtl/ref.hxx>
|
|
#include <utility>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
|
|
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::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() )
|
|
,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( ) noexcept override
|
|
{
|
|
m_rParent.acquire();
|
|
}
|
|
|
|
virtual void SAL_CALL release( ) noexcept 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;
|
|
|
|
}
|
|
|
|
/** a property handler for any virtual string properties
|
|
*/
|
|
|
|
namespace {
|
|
|
|
class FormGeometryHandler : public PropertyHandlerComponent
|
|
{
|
|
public:
|
|
explicit FormGeometryHandler(
|
|
const Reference< XComponentContext >& _rxContext
|
|
);
|
|
|
|
protected:
|
|
virtual ~FormGeometryHandler() override;
|
|
|
|
protected:
|
|
// XServiceInfo
|
|
virtual OUString SAL_CALL getImplementationName() override;
|
|
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames () override;
|
|
|
|
// 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 )
|
|
:PropertyHandlerComponent( _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();
|
|
|
|
PropertyHandlerComponent::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( u"ControlShapeAccess"_ustr );
|
|
any >>= xControlMap;
|
|
m_xAssociatedShape.set( xControlMap->get( Any( 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 );
|
|
}
|
|
|
|
|
|
OUString FormGeometryHandler::getImplementationName( )
|
|
{
|
|
return u"com.sun.star.comp.extensions.FormGeometryHandler"_ustr;
|
|
}
|
|
|
|
|
|
Sequence< OUString > FormGeometryHandler::getSupportedServiceNames( )
|
|
{
|
|
return { u"com.sun.star.form.inspection.FormGeometryHandler"_ustr };
|
|
}
|
|
|
|
|
|
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()
|
|
{
|
|
PropertyHandlerComponent::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(u"com.sun.star.sheet.Shape"_ustr) )
|
|
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 ? PROPERTY_HEIGHT : 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, Any( 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, false, aRelativePosition );
|
|
|
|
Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW );
|
|
sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows, 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( OUString _propertyName, Any _newPropertyValue )
|
|
:sPropertyName(std::move( _propertyName ))
|
|
,aNewPropertyValue(std::move( _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.emplace_back(PROPERTY_POSITIONX, Any( aPos.X ));
|
|
aEventTranslations.emplace_back(PROPERTY_POSITIONY, Any( aPos.Y ));
|
|
}
|
|
else if ( _event.PropertyName == "Size" )
|
|
{
|
|
css::awt::Size aSize = m_xShape->getSize();
|
|
aEventTranslations.emplace_back(PROPERTY_WIDTH, Any( aSize.Width ));
|
|
aEventTranslations.emplace_back(PROPERTY_HEIGHT, Any( aSize.Height ));
|
|
}
|
|
else if ( _event.PropertyName == PROPERTY_ANCHOR_TYPE )
|
|
{
|
|
aEventTranslations.emplace_back(PROPERTY_TEXT_ANCHOR_TYPE, _event.NewValue);
|
|
}
|
|
else if ( _event.PropertyName == PROPERTY_ANCHOR )
|
|
{
|
|
aEventTranslations.emplace_back(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" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
|
|
extensions_propctrlr_FormGeometryHandler_get_implementation(
|
|
css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
|
|
{
|
|
return cppu::acquire(new pcr::FormGeometryHandler(context));
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|