28#include <com/sun/star/inspection/XObjectInspectorUI.hpp>
29#include <com/sun/star/awt/XControlModel.hpp>
30#include <com/sun/star/drawing/XControlShape.hpp>
31#include <com/sun/star/container/XMap.hpp>
32#include <com/sun/star/inspection/XNumericControl.hpp>
33#include <com/sun/star/util/MeasureUnit.hpp>
34#include <com/sun/star/text/TextContentAnchorType.hpp>
35#include <com/sun/star/lang/NullPointerException.hpp>
36#include <com/sun/star/lang/XServiceInfo.hpp>
37#include <com/sun/star/sheet/XSpreadsheet.hpp>
38#include <com/sun/star/table/XColumnRowRange.hpp>
39#include <com/sun/star/container/XChild.hpp>
40#include <com/sun/star/form/XGridColumnFactory.hpp>
54 using ::com::sun::star::uno::Reference;
55 using ::com::sun::star::uno::XInterface;
56 using ::com::sun::star::uno::UNO_QUERY;
57 using ::com::sun::star::uno::UNO_QUERY_THROW;
58 using ::com::sun::star::uno::UNO_SET_THROW;
59 using ::com::sun::star::uno::Exception;
60 using ::com::sun::star::uno::RuntimeException;
61 using ::com::sun::star::uno::Any;
62 using ::com::sun::star::uno::Sequence;
63 using ::com::sun::star::uno::XComponentContext;
64 using ::com::sun::star::beans::Property;
65 using ::com::sun::star::awt::XControlModel;
66 using ::com::sun::star::drawing::XControlShape;
67 using ::com::sun::star::container::XMap;
68 using ::com::sun::star::inspection::LineDescriptor;
69 using ::com::sun::star::inspection::XPropertyControlFactory;
70 using ::com::sun::star::lang::NullPointerException;
71 using ::com::sun::star::beans::Optional;
72 using ::com::sun::star::inspection::XNumericControl;
73 using ::com::sun::star::drawing::XShape;
74 using ::com::sun::star::beans::PropertyChangeEvent;
75 using ::com::sun::star::lang::EventObject;
76 using ::com::sun::star::beans::XPropertySet;
77 using ::com::sun::star::beans::XPropertyChangeListener;
78 using ::com::sun::star::text::TextContentAnchorType;
79 using ::com::sun::star::text::TextContentAnchorType_AT_PARAGRAPH;
80 using ::com::sun::star::text::TextContentAnchorType_AS_CHARACTER;
81 using ::com::sun::star::beans::XPropertySetInfo;
82 using ::com::sun::star::inspection::XObjectInspectorUI;
83 using ::com::sun::star::lang::XServiceInfo;
84 using ::com::sun::star::sheet::XSpreadsheet;
85 using ::com::sun::star::table::XColumnRowRange;
86 using ::com::sun::star::table::XTableColumns;
87 using ::com::sun::star::table::XTableRows;
88 using ::com::sun::star::container::XIndexAccess;
89 using ::com::sun::star::container::XChild;
90 using ::com::sun::star::form::XGridColumnFactory;
92 namespace MeasureUnit = css::util::MeasureUnit;
94 #define ANCHOR_TO_SHEET 0
95 #define ANCHOR_TO_CELL 1
102 class BroadcastHelperBase
105 explicit BroadcastHelperBase( ::osl::Mutex& _rMutex )
106 :maBHelper( _rMutex )
125 typedef ::cppu::WeakImplHelper < css::beans::XPropertyChangeListener
130 class ShapeGeometryChangeNotifier :
public BroadcastHelperBase
135 ShapeGeometryChangeNotifier(
::cppu::OWeakObject& _rParent, ::osl::Mutex& _rParentMutex,
const Reference< XShape >& _shape )
136 :BroadcastHelperBase( _rParentMutex )
139 ,m_aPropertyChangeListeners( _rParentMutex )
147 void addPropertyChangeListener(
const Reference< XPropertyChangeListener >& _listener )
149 m_aPropertyChangeListeners.addInterface( _listener );
151 void removePropertyChangeListener(
const Reference< XPropertyChangeListener >& _listener )
153 m_aPropertyChangeListeners.removeInterface( _listener );
159 ::osl::MutexGuard aGuard(
getMutex() );
160 impl_dispose_nothrow();
164 virtual void SAL_CALL acquire( )
noexcept override
169 virtual void SAL_CALL release( )
noexcept override
175 virtual void SAL_CALL propertyChange(
const PropertyChangeEvent& _event )
override;
178 virtual void SAL_CALL disposing(
const EventObject& _event )
override;
181 virtual ~ShapeGeometryChangeNotifier()
override
183 if ( !getBroadcastHelper().bDisposed )
194 void impl_init_nothrow();
195 void impl_dispose_nothrow();
200 Reference< XShape > m_xShape;
209 class FormGeometryHandler;
218 class FormGeometryHandler :
public PropertyHandlerComponent
221 explicit FormGeometryHandler(
222 const Reference< XComponentContext >& _rxContext
226 virtual ~FormGeometryHandler()
override;
235 virtual void SAL_CALL
setPropertyValue(
const OUString& _rPropertyName,
const Any& _rValue )
override;
236 virtual LineDescriptor SAL_CALL describePropertyLine(
const OUString& _rPropertyName,
const css::uno::Reference< css::inspection::XPropertyControlFactory >& _rxControlFactory )
override;
237 virtual void SAL_CALL addPropertyChangeListener(
const css::uno::Reference< css::beans::XPropertyChangeListener >& _rxListener )
override;
238 virtual void SAL_CALL removePropertyChangeListener(
const css::uno::Reference< css::beans::XPropertyChangeListener >& _rxListener )
override;
239 virtual Sequence< OUString > SAL_CALL getActuatingProperties( )
override;
240 virtual void SAL_CALL actuatingPropertyChanged(
const OUString& _rActuatingPropertyName,
const Any& _rNewValue,
const Any& _rOldValue,
const Reference< XObjectInspectorUI >& _rxInspectorUI,
sal_Bool _bFirstTimeInit )
override;
243 virtual void SAL_CALL disposing()
override;
246 virtual Sequence< Property > doDescribeSupportedProperties()
const override;
249 virtual void onNewComponent()
override;
252 bool impl_haveTextAnchorType_nothrow()
const;
253 bool impl_haveSheetAnchorType_nothrow()
const;
254 void impl_setSheetAnchorType_nothrow(
const sal_Int32 _nAnchorType )
const;
257 Reference< XControlShape > m_xAssociatedShape;
258 Reference< XPropertySet > m_xShapeProperties;
267 FormGeometryHandler::FormGeometryHandler(
const Reference< XComponentContext >& _rxContext )
268 :PropertyHandlerComponent( _rxContext )
273 FormGeometryHandler::~FormGeometryHandler( )
275 if ( !rBHelper.bDisposed )
284 void FormGeometryHandler::onNewComponent()
286 if ( m_xChangeNotifier.is() )
288 m_xChangeNotifier->dispose();
289 m_xChangeNotifier.clear();
291 m_xAssociatedShape.clear();
292 m_xShapeProperties.clear();
294 PropertyHandlerComponent::onNewComponent();
298 Reference< XControlModel > xControlModel( m_xComponent, UNO_QUERY );
299 if ( xControlModel.is() )
302 Reference< XChild > xCompChild( m_xComponent, UNO_QUERY_THROW );
303 Reference< XGridColumnFactory > xCheckGrid( xCompChild->getParent(), UNO_QUERY );
304 if ( !xCheckGrid.is() )
306 Reference< XMap > xControlMap;
309 m_xAssociatedShape.set( xControlMap->get(
Any( xControlModel ) ), UNO_QUERY_THROW );
310 m_xShapeProperties.set( m_xAssociatedShape, UNO_QUERY_THROW );
314 catch(
const Exception& )
319 if ( m_xAssociatedShape.is() )
320 m_xChangeNotifier =
new ShapeGeometryChangeNotifier( *
this,
m_aMutex, m_xAssociatedShape );
324 OUString FormGeometryHandler::getImplementationName( )
326 return "com.sun.star.comp.extensions.FormGeometryHandler";
330 Sequence< OUString > FormGeometryHandler::getSupportedServiceNames( )
332 return {
"com.sun.star.form.inspection.FormGeometryHandler" };
336 Any SAL_CALL FormGeometryHandler::getPropertyValue(
const OUString& _rPropertyName )
338 ::osl::MutexGuard aGuard(
m_aMutex );
339 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
341 ENSURE_OR_THROW2( m_xAssociatedShape.is(),
"internal error: properties, but no shape!", *
this );
342 ENSURE_OR_THROW2( m_xShapeProperties.is(),
"internal error: no shape properties!", *
this );
350 aReturn <<= m_xAssociatedShape->getPosition().X;
353 aReturn <<= m_xAssociatedShape->getPosition().Y;
356 aReturn <<= m_xAssociatedShape->getSize().Width;
359 aReturn <<= m_xAssociatedShape->getSize().Height;
363 OSL_ENSURE( aReturn.hasValue(),
"FormGeometryHandler::getPropertyValue: illegal anchor type!" );
367 Reference< XSpreadsheet > xAnchorSheet( m_xShapeProperties->getPropertyValue(
PROPERTY_ANCHOR ), UNO_QUERY );
373 OSL_FAIL(
"FormGeometryHandler::getPropertyValue: huh?" );
377 catch(
const Exception& )
385 void SAL_CALL FormGeometryHandler::setPropertyValue(
const OUString& _rPropertyName,
const Any& _rValue )
387 ::osl::MutexGuard aGuard(
m_aMutex );
388 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
390 ENSURE_OR_THROW2( m_xAssociatedShape.is(),
"internal error: properties, but no shape!", *
this );
391 ENSURE_OR_THROW2( m_xShapeProperties.is(),
"internal error: properties, but no shape!", *
this );
400 sal_Int32 nPosition(0);
401 OSL_VERIFY( _rValue >>= nPosition );
403 css::awt::Point aPos( m_xAssociatedShape->getPosition() );
408 m_xAssociatedShape->setPosition( aPos );
416 OSL_VERIFY( _rValue >>= nSize );
418 css::awt::Size aSize( m_xAssociatedShape->getSize() );
422 aSize.Height = nSize;
423 m_xAssociatedShape->setSize( aSize );
433 sal_Int32 nSheetAnchorType = 0;
434 OSL_VERIFY( _rValue >>= nSheetAnchorType );
435 impl_setSheetAnchorType_nothrow( nSheetAnchorType );
440 OSL_FAIL(
"FormGeometryHandler::getPropertyValue: huh?" );
444 catch(
const Exception& )
451 LineDescriptor SAL_CALL FormGeometryHandler::describePropertyLine(
const OUString& _rPropertyName,
452 const Reference< XPropertyControlFactory >& _rxControlFactory )
454 ::osl::MutexGuard aGuard(
m_aMutex );
455 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
457 LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) );
460 bool bIsSize =
false;
470 Optional< double > aZero(
true, 0 );
471 Optional< double > aValueNotPresent(
false, 0 );
472 aLineDesc.Control = PropertyHandlerHelper::createNumericControl(
473 _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent );
475 Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW );
476 xNumericControl->setValueUnit( MeasureUnit::MM_100TH );
477 xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() );
487 OSL_FAIL(
"FormGeometryHandler::describePropertyLine: huh?" );
491 catch(
const Exception& )
499 void SAL_CALL FormGeometryHandler::addPropertyChangeListener(
const Reference< XPropertyChangeListener >& _listener )
501 ::osl::MutexGuard aGuard(
m_aMutex );
502 OSL_PRECOND( m_xChangeNotifier.is(),
"FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" );
503 if ( m_xChangeNotifier.is() )
504 m_xChangeNotifier->addPropertyChangeListener( _listener );
508 void SAL_CALL FormGeometryHandler::removePropertyChangeListener(
const Reference< XPropertyChangeListener >& _listener )
510 ::osl::MutexGuard aGuard(
m_aMutex );
511 OSL_PRECOND( m_xChangeNotifier.is(),
"FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" );
512 if ( m_xChangeNotifier.is() )
513 m_xChangeNotifier->removePropertyChangeListener( _listener );
517 Sequence< OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( )
520 return aInterestedIn;
524 void SAL_CALL FormGeometryHandler::actuatingPropertyChanged(
const OUString& _rActuatingPropertyName,
const Any& _rNewValue,
const Any& ,
const Reference< XObjectInspectorUI >& _rxInspectorUI,
sal_Bool )
526 if ( !_rxInspectorUI.is() )
527 throw NullPointerException();
529 ::osl::MutexGuard aGuard(
m_aMutex );
530 PropertyId nActuatingPropId( impl_getPropertyId_nothrow( _rActuatingPropertyName ) );
532 switch ( nActuatingPropId )
536 TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH );
537 OSL_VERIFY( _rNewValue >>= eAnchorType );
538 _rxInspectorUI->enablePropertyUI(
PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER );
545 OSL_FAIL(
"FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" );
551 Sequence< Property > FormGeometryHandler::doDescribeSupportedProperties()
const
553 if ( !m_xAssociatedShape.is() )
554 return Sequence< Property >();
563 if ( impl_haveTextAnchorType_nothrow() )
566 if ( impl_haveSheetAnchorType_nothrow() )
573 void SAL_CALL FormGeometryHandler::disposing()
575 PropertyHandlerComponent::disposing();
577 if ( m_xChangeNotifier.is() )
579 m_xChangeNotifier->dispose();
580 m_xChangeNotifier.clear();
585 bool FormGeometryHandler::impl_haveTextAnchorType_nothrow()
const
587 ENSURE_OR_THROW( m_xShapeProperties.is(),
"not to be called without shape properties" );
590 Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
594 catch(
const Exception& )
602 bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow()
const
604 ENSURE_OR_THROW( m_xShapeProperties.is(),
"not to be called without shape properties" );
607 Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
610 Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW );
611 if ( xSI->supportsService(
"com.sun.star.sheet.Shape") )
614 catch(
const Exception& )
624 sal_Int32 lcl_getLowerBoundRowOrColumn(
const Reference< XIndexAccess >& _rxRowsOrColumns,
const bool _bRows,
625 const css::awt::Point& _rRelativePosition )
627 sal_Int32 nAccumulated = 0;
629 const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X;
631 sal_Int32
nElements = _rxRowsOrColumns->getCount();
632 sal_Int32 currentPos = 0;
633 for ( currentPos=0; currentPos<
nElements; ++currentPos )
635 Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW );
637 bool bIsVisible =
true;
642 sal_Int32 nHeightOrWidth( 0 );
645 if ( nAccumulated + nHeightOrWidth > rRelativePos )
648 nAccumulated += nHeightOrWidth;
656 void FormGeometryHandler::impl_setSheetAnchorType_nothrow(
const sal_Int32 _nAnchorType )
const
658 ENSURE_OR_THROW( m_xShapeProperties.is(),
"illegal to be called without shape properties." );
661 CellBindingHelper
aHelper( m_xComponent, impl_getContextDocument_nothrow() );
663 Reference< XSpreadsheet > xSheet;
664 aHelper.getControlSheetIndex( xSheet );
666 switch ( _nAnchorType )
669 OSL_ENSURE( xSheet.is(),
670 "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" );
673 css::awt::Point aPreservePosition( m_xAssociatedShape->getPosition() );
675 m_xAssociatedShape->setPosition( aPreservePosition );
681 Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW );
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!" );
689 css::awt::Point aRelativePosition( m_xAssociatedShape->getPosition() );
691 Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW );
692 sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols,
false, aRelativePosition );
694 Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW );
695 sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows,
true, aRelativePosition );
697 Any aNewAnchorCell( xSheet->getCellByPosition( nNewAnchorCol, nNewAnchorRow ) );
698 m_xShapeProperties->setPropertyValue(
PROPERTY_ANCHOR, aNewAnchorCell );
703 OSL_FAIL(
"FormGeometryHandler::impl_setSheetAnchorType_nothrow: illegal anchor type!" );
707 catch(
const Exception& )
718 struct EventTranslation
720 OUString sPropertyName;
721 Any aNewPropertyValue;
723 EventTranslation( OUString _propertyName, Any _newPropertyValue )
724 :sPropertyName(
std::move( _propertyName ))
725 ,aNewPropertyValue(
std::move( _newPropertyValue ))
732 void SAL_CALL ShapeGeometryChangeNotifier::propertyChange(
const PropertyChangeEvent& _event )
739 if ( _event.PropertyName ==
"Position" )
741 css::awt::Point aPos = m_xShape->getPosition();
745 else if ( _event.PropertyName ==
"Size" )
747 css::awt::Size aSize = m_xShape->getSize();
760 PropertyChangeEvent aTranslatedEvent( _event );
764 for (
auto const& eventTranslation : aEventTranslations)
766 aTranslatedEvent.PropertyName = eventTranslation.sPropertyName;
767 aTranslatedEvent.NewValue = eventTranslation.aNewPropertyValue;
768 m_aPropertyChangeListeners.notifyEach( &XPropertyChangeListener::propertyChange, aTranslatedEvent );
773 void SAL_CALL ShapeGeometryChangeNotifier::disposing(
const EventObject& )
776 impl_dispose_nothrow();
780 void ShapeGeometryChangeNotifier::impl_init_nothrow()
782 osl_atomic_increment( &m_refCount );
785 Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW );
786 xShapeProperties->addPropertyChangeListener( OUString(),
this );
788 catch(
const Exception& )
792 osl_atomic_decrement( &m_refCount );
796 void ShapeGeometryChangeNotifier::impl_dispose_nothrow()
800 Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW );
801 xShapeProperties->removePropertyChangeListener( OUString(),
this );
803 catch(
const Exception& )
808 getBroadcastHelper().bDisposed =
true;
814extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
816 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any>
const&)
818 return cppu::acquire(
new pcr::FormGeometryHandler(context));
PropertiesInfo aProperties
#define ENSURE_OR_THROW(c, m)
#define DBG_UNHANDLED_EXCEPTION(...)
#define ENSURE_OR_THROW2(c, m, ifc)
Reference< XComponentContext > m_xContext
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
::osl::Mutex & getMutex()
VBAHELPER_DLLPUBLIC bool setPropertyValue(css::uno::Sequence< css::beans::PropertyValue > &aProp, const OUString &aName, const css::uno::Any &aValue)
a property handler for any virtual string properties
::comphelper::ComponentBase ShapeGeometryChangeNotifier_CBase
helper class to work around the ...unfortunate implementation of property change broadcasts in the XS...
::cppu::WeakImplHelper< css::beans::XPropertyChangeListener > ShapeGeometryChangeNotifier_IBase
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
const XMLEventNameTranslation aEventTranslations[]