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:
BroadcastHelperBase(::osl::Mutex & _rMutex)116         BroadcastHelperBase( ::osl::Mutex& _rMutex )
117             :maBHelper( _rMutex )
118         {
119         }
120 
121     protected:
getBroadcastHelper()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:
ShapeGeometryChangeNotifier(::cppu::OWeakObject & _rParent,::osl::Mutex & _rParentMutex,const Reference<XShape> & _shape)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
addPropertyChangeListener(const Reference<XPropertyChangeListener> & _listener)156         void addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener )
157         {
158             m_aPropertyChangeListeners.addInterface( _listener );
159         }
removePropertyChangeListener(const Reference<XPropertyChangeListener> & _listener)160         void removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener )
161         {
162             m_aPropertyChangeListeners.removeInterface( _listener );
163         }
164 
165         // XComponent equivalent
dispose()166         void dispose()
167         {
168             ::osl::MutexGuard aGuard( getMutex() );
169             impl_dispose_nothrow();
170         }
171 
172         // XInterface
acquire()173         virtual void SAL_CALL acquire(  ) throw ()
174         {
175             m_rParent.acquire();
176         }
177 
release()178         virtual void SAL_CALL release(  ) throw ()
179         {
180             m_rParent.release();
181         }
182 
183         // XPropertyChangeListener
184         virtual void SAL_CALL propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException);
185 
186         // XEventListener
187         virtual void SAL_CALL disposing( const EventObject& _event ) throw (RuntimeException);
188 
189     protected:
~ShapeGeometryChangeNotifier()190         virtual ~ShapeGeometryChangeNotifier()
191         {
192             if ( !getBroadcastHelper().bDisposed )
193             {
194                 acquire();
195                 dispose();
196             }
197         }
198 
199     protected:
getBroadcastHelper()200         ::cppu::OBroadcastHelper& getBroadcastHelper() { return BroadcastHelperBase::getBroadcastHelper(); }
201 
202     private:
203         void    impl_init_nothrow();
204         void    impl_dispose_nothrow();
205 
206     private:
207         ::cppu::OWeakObject&                m_rParent;
208         ::cppu::OInterfaceContainerHelper   m_aPropertyChangeListeners;
209         Reference< XShape >                 m_xShape;
210     };
211 
212 	//====================================================================
213 	//= FormGeometryHandler - declaration
214 	//====================================================================
215     class FormGeometryHandler;
216     typedef HandlerComponentBase< FormGeometryHandler > FormGeometryHandler_Base;
217     /** a property handler for any virtual string properties
218     */
219     class FormGeometryHandler : public FormGeometryHandler_Base
220 	{
221     public:
222         FormGeometryHandler(
223             const Reference< XComponentContext >& _rxContext
224         );
225 
226         static ::rtl::OUString SAL_CALL getImplementationName_static(  ) throw (RuntimeException);
227         static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(  ) throw (RuntimeException);
228 
229     protected:
230         ~FormGeometryHandler();
231 
232     protected:
233         // XPropertyHandler overriables
234         virtual Any                         SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException);
235         virtual void                        SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException);
236         virtual LineDescriptor              SAL_CALL describePropertyLine( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException);
237         virtual void                        SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException);
238         virtual void                        SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException);
239         virtual Sequence< ::rtl::OUString > SAL_CALL getActuatingProperties( ) throw (RuntimeException);
240         virtual void                        SAL_CALL actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (NullPointerException, RuntimeException);
241 
242         // OComponentHandler overridables
243         virtual void SAL_CALL disposing();
244 
245         // PropertyHandler overridables
246         virtual Sequence< Property >        SAL_CALL doDescribeSupportedProperties() const;
247 
248     protected:
249         virtual void onNewComponent();
250 
251     private:
252         bool    impl_haveTextAnchorType_nothrow() const;
253         bool    impl_haveSheetAnchorType_nothrow() const;
254         void    impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const;
255 
256     private:
257         Reference< XControlShape >                      m_xAssociatedShape;
258         Reference< XPropertySet >                       m_xShapeProperties;
259         ::rtl::Reference< ShapeGeometryChangeNotifier > m_xChangeNotifier;
260 	};
261 
262     //====================================================================
263 	//= FormGeometryHandler - implementation
264 	//====================================================================
DBG_NAME(FormGeometryHandler)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 	//--------------------------------------------------------------------
~FormGeometryHandler()274     FormGeometryHandler::~FormGeometryHandler( )
275     {
276         if ( !rBHelper.bDisposed )
277         {
278             acquire();
279             dispose();
280         }
281 
282         DBG_DTOR( FormGeometryHandler, NULL );
283     }
284 
285     //--------------------------------------------------------------------
onNewComponent()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     //--------------------------------------------------------------------
getImplementationName_static()324     ::rtl::OUString SAL_CALL FormGeometryHandler::getImplementationName_static(  ) throw (RuntimeException)
325     {
326         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.FormGeometryHandler" ) );
327     }
328 
329     //--------------------------------------------------------------------
getSupportedServiceNames_static()330     Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getSupportedServiceNames_static(  ) throw (RuntimeException)
331     {
332         Sequence< ::rtl::OUString > aSupported( 1 );
333         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.FormGeometryHandler" ) );
334         return aSupported;
335     }
336 
337     //--------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & _rPropertyName)338     Any SAL_CALL FormGeometryHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
339     {
340         ::osl::MutexGuard aGuard( m_aMutex );
341         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
342 
343         ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this );
344         ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: no shape properties!", *this );
345 
346         Any aReturn;
347         try
348         {
349             switch ( nPropId )
350             {
351             case PROPERTY_ID_POSITIONX:
352                 aReturn <<= m_xAssociatedShape->getPosition().X;
353                 break;
354             case PROPERTY_ID_POSITIONY:
355                 aReturn <<= m_xAssociatedShape->getPosition().Y;
356                 break;
357             case PROPERTY_ID_WIDTH:
358                 aReturn <<= m_xAssociatedShape->getSize().Width;
359                 break;
360             case PROPERTY_ID_HEIGHT:
361                 aReturn <<= m_xAssociatedShape->getSize().Height;
362                 break;
363             case PROPERTY_ID_TEXT_ANCHOR_TYPE:
364                 aReturn = m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR_TYPE );
365                 OSL_ENSURE( aReturn.hasValue(), "FormGeometryHandler::getPropertyValue: illegal anchor type!" );
366                 break;
367             case PROPERTY_ID_SHEET_ANCHOR_TYPE:
368             {
369                 Reference< XSpreadsheet > xAnchorSheet( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ), UNO_QUERY );
370                 aReturn <<= sal_Int32( xAnchorSheet.is() ? ANCHOR_TO_SHEET : ANCHOR_TO_CELL );
371             }
372             break;
373 
374             default:
375                 OSL_ENSURE( false, "FormGeometryHandler::getPropertyValue: huh?" );
376                 break;
377             }
378         }
379         catch( const Exception& )
380         {
381         	DBG_UNHANDLED_EXCEPTION();
382         }
383         return aReturn;
384     }
385 
386     //--------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rValue)387     void SAL_CALL FormGeometryHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
388     {
389         ::osl::MutexGuard aGuard( m_aMutex );
390         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
391 
392         ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this );
393         ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: properties, but no shape!", *this );
394 
395         try
396         {
397             switch ( nPropId )
398             {
399             case PROPERTY_ID_POSITIONX:
400             case PROPERTY_ID_POSITIONY:
401             {
402                 sal_Int32 nPosition(0);
403                 OSL_VERIFY( _rValue >>= nPosition );
404 
405                 AwtPoint aPos( m_xAssociatedShape->getPosition() );
406                 if ( nPropId == PROPERTY_ID_POSITIONX )
407                     aPos.X = nPosition;
408                 else
409                     aPos.Y = nPosition;
410                 m_xAssociatedShape->setPosition( aPos );
411             }
412             break;
413 
414             case PROPERTY_ID_WIDTH:
415             case PROPERTY_ID_HEIGHT:
416             {
417                 sal_Int32 nSize(0);
418                 OSL_VERIFY( _rValue >>= nSize );
419 
420                 AwtSize aSize( m_xAssociatedShape->getSize() );
421                 if ( nPropId == PROPERTY_ID_WIDTH )
422                     aSize.Width = nSize;
423                 else
424                     aSize.Height = nSize;
425 				m_xAssociatedShape->setSize( aSize );
426             }
427             break;
428 
429             case PROPERTY_ID_TEXT_ANCHOR_TYPE:
430                 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR_TYPE, _rValue );
431                 break;
432 
433             case PROPERTY_ID_SHEET_ANCHOR_TYPE:
434             {
435                 sal_Int32 nSheetAnchorType = 0;
436                 OSL_VERIFY( _rValue >>= nSheetAnchorType );
437                 impl_setSheetAnchorType_nothrow( nSheetAnchorType );
438             }
439             break;
440 
441             default:
442                 OSL_ENSURE( false, "FormGeometryHandler::getPropertyValue: huh?" );
443                 break;
444             }
445         }
446         catch( const Exception& )
447         {
448         	DBG_UNHANDLED_EXCEPTION();
449         }
450     }
451 
452     //--------------------------------------------------------------------
describePropertyLine(const::rtl::OUString & _rPropertyName,const Reference<XPropertyControlFactory> & _rxControlFactory)453     LineDescriptor SAL_CALL FormGeometryHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
454             const Reference< XPropertyControlFactory >& _rxControlFactory )
455         throw (UnknownPropertyException, NullPointerException, RuntimeException)
456     {
457         ::osl::MutexGuard aGuard( m_aMutex );
458         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
459 
460         LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) );
461         try
462         {
463             bool bIsSize = false;
464             switch ( nPropId )
465             {
466             case PROPERTY_ID_WIDTH:
467             case PROPERTY_ID_HEIGHT:
468                 bIsSize = true;
469                 // NO break!
470             case PROPERTY_ID_POSITIONX:
471             case PROPERTY_ID_POSITIONY:
472             {
473                 Optional< double > aZero( sal_True, 0 );
474                 Optional< double > aValueNotPresent( sal_False, 0 );
475                 aLineDesc.Control = PropertyHandlerHelper::createNumericControl(
476                     _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent, sal_False );
477 
478                 Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW );
479                 xNumericControl->setValueUnit( MeasureUnit::MM_100TH );
480                 xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() );
481             }
482             break;
483 
484             case PROPERTY_ID_TEXT_ANCHOR_TYPE:
485             case PROPERTY_ID_SHEET_ANCHOR_TYPE:
486                 // default handling from PropertyHandler is sufficient
487                 break;
488 
489             default:
490                 OSL_ENSURE( false, "FormGeometryHandler::describePropertyLine: huh?" );
491                 break;
492             }
493         }
494         catch( const Exception& )
495         {
496         	DBG_UNHANDLED_EXCEPTION();
497         }
498         return aLineDesc;
499     }
500 
501     //--------------------------------------------------------------------
addPropertyChangeListener(const Reference<XPropertyChangeListener> & _listener)502     void SAL_CALL FormGeometryHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException)
503     {
504         ::osl::MutexGuard aGuard( m_aMutex );
505         OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" );
506         if ( m_xChangeNotifier.is() )
507             m_xChangeNotifier->addPropertyChangeListener( _listener );
508     }
509 
510     //--------------------------------------------------------------------
removePropertyChangeListener(const Reference<XPropertyChangeListener> & _listener)511     void SAL_CALL FormGeometryHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException)
512     {
513         ::osl::MutexGuard aGuard( m_aMutex );
514         OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" );
515         if ( m_xChangeNotifier.is() )
516             m_xChangeNotifier->removePropertyChangeListener( _listener );
517     }
518 
519     //--------------------------------------------------------------------
getActuatingProperties()520     Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( ) throw (RuntimeException)
521     {
522         Sequence< ::rtl::OUString > aInterestedIn(1);
523         aInterestedIn[0] = PROPERTY_TEXT_ANCHOR_TYPE;
524         return aInterestedIn;
525     }
526 
527     //--------------------------------------------------------------------
actuatingPropertyChanged(const::rtl::OUString & _rActuatingPropertyName,const Any & _rNewValue,const Any &,const Reference<XObjectInspectorUI> & _rxInspectorUI,sal_Bool)528     void SAL_CALL FormGeometryHandler::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException)
529     {
530         if ( !_rxInspectorUI.is() )
531             throw NullPointerException();
532 
533         ::osl::MutexGuard aGuard( m_aMutex );
534         PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) );
535 
536         switch ( nActuatingPropId )
537         {
538         case PROPERTY_ID_TEXT_ANCHOR_TYPE:
539         {
540             TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH );
541             OSL_VERIFY( _rNewValue >>= eAnchorType );
542             _rxInspectorUI->enablePropertyUI( PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER );
543         }
544         break;
545         default:
546             OSL_ENSURE( false, "FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" );
547             break;
548         }
549     }
550 
551     //--------------------------------------------------------------------
doDescribeSupportedProperties() const552     Sequence< Property > SAL_CALL FormGeometryHandler::doDescribeSupportedProperties() const
553     {
554         if ( !m_xAssociatedShape.is() )
555             return Sequence< Property >();
556 
557         ::std::vector< Property > aProperties;
558 
559         addInt32PropertyDescription( aProperties, PROPERTY_POSITIONX );
560         addInt32PropertyDescription( aProperties, PROPERTY_POSITIONY );
561         addInt32PropertyDescription( aProperties, PROPERTY_WIDTH );
562         addInt32PropertyDescription( aProperties, PROPERTY_HEIGHT );
563 
564         if ( impl_haveTextAnchorType_nothrow() )
565             implAddPropertyDescription( aProperties, PROPERTY_TEXT_ANCHOR_TYPE, ::cppu::UnoType< TextContentAnchorType >::get() );
566 
567         if ( impl_haveSheetAnchorType_nothrow() )
568             addInt32PropertyDescription( aProperties, PROPERTY_SHEET_ANCHOR_TYPE );
569 
570         return Sequence< Property >( &(*aProperties.begin()), aProperties.size() );
571     }
572 
573     //--------------------------------------------------------------------
disposing()574     void SAL_CALL FormGeometryHandler::disposing()
575     {
576         FormGeometryHandler_Base::disposing();
577 
578         if ( m_xChangeNotifier.is() )
579         {
580             m_xChangeNotifier->dispose();
581             m_xChangeNotifier.clear();
582         }
583     }
584 
585     //--------------------------------------------------------------------
impl_haveTextAnchorType_nothrow() const586     bool FormGeometryHandler::impl_haveTextAnchorType_nothrow() const
587     {
588         ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" );
589         try
590         {
591             Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
592             if ( xPSI->hasPropertyByName( PROPERTY_ANCHOR_TYPE ) )
593                 return true;
594         }
595         catch( const Exception& )
596         {
597         	DBG_UNHANDLED_EXCEPTION();
598         }
599         return false;
600     }
601 
602     //--------------------------------------------------------------------
impl_haveSheetAnchorType_nothrow() const603     bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow() const
604     {
605         ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" );
606         try
607         {
608             Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
609             if ( !xPSI->hasPropertyByName( PROPERTY_ANCHOR ) )
610                 return false;
611             Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW );
612             if ( xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) ) ) )
613                 return true;
614         }
615         catch( const Exception& )
616         {
617         	DBG_UNHANDLED_EXCEPTION();
618         }
619         return false;
620     }
621 
622     //--------------------------------------------------------------------
623     namespace
624     {
lcl_getLowerBoundRowOrColumn(const Reference<XIndexAccess> & _rxRowsOrColumns,const bool _bRows,const AwtPoint & _rRelativePosition)625         static sal_Int32 lcl_getLowerBoundRowOrColumn( const Reference< XIndexAccess >& _rxRowsOrColumns, const bool _bRows,
626             const AwtPoint& _rRelativePosition )
627         {
628             sal_Int32 nAccumulated = 0;
629 
630             const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X;
631 
632             sal_Int32 nElements = _rxRowsOrColumns->getCount();
633             sal_Int32 currentPos = 0;
634             for ( currentPos=0; currentPos<nElements; ++currentPos )
635             {
636                 Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW );
637 
638                 sal_Bool bIsVisible = sal_True;
639                 OSL_VERIFY( xRowOrColumn->getPropertyValue( PROPERTY_IS_VISIBLE ) >>= bIsVisible );
640                 if ( !bIsVisible )
641                     continue;
642 
643                 sal_Int32 nHeightOrWidth( 0 );
644                 OSL_VERIFY( xRowOrColumn->getPropertyValue( _bRows ? PROPERTY_HEIGHT : PROPERTY_WIDTH ) >>= nHeightOrWidth );
645 
646                 if ( nAccumulated + nHeightOrWidth > rRelativePos )
647                     break;
648 
649                 nAccumulated += nHeightOrWidth;
650             }
651 
652             return currentPos;
653         }
654     }
655 
656     //--------------------------------------------------------------------
impl_setSheetAnchorType_nothrow(const sal_Int32 _nAnchorType) const657     void FormGeometryHandler::impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const
658     {
659         ENSURE_OR_THROW( m_xShapeProperties.is(), "illegal to be called without shape properties." );
660         try
661         {
662             CellBindingHelper aHelper( m_xComponent, impl_getContextDocument_nothrow() );
663             // find the sheet which the control belongs to
664             Reference< XSpreadsheet > xSheet;
665             aHelper.getControlSheetIndex( xSheet );
666 
667             switch ( _nAnchorType )
668             {
669             case ANCHOR_TO_SHEET:
670                 OSL_ENSURE( xSheet.is(),
671                     "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" );
672                 if ( xSheet.is() )
673                 {
674                     AwtPoint aPreservePosition( m_xAssociatedShape->getPosition() );
675                     m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, makeAny( xSheet ) );
676                     m_xAssociatedShape->setPosition( aPreservePosition );
677                 }
678                 break;
679 
680             case ANCHOR_TO_CELL:
681             {
682                 Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW );
683 
684                 // get the current anchor
685                 Reference< XSpreadsheet > xCurrentAnchor;
686                 OSL_VERIFY( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ) >>= xCurrentAnchor );
687                 OSL_ENSURE( xCurrentAnchor.is(), "FormGeometryHandler::impl_setSheetAnchorType_nothrow: only to be called when currently anchored to a sheet!" );
688 
689                 // get the current position
690                 AwtPoint aRelativePosition( m_xAssociatedShape->getPosition() );
691 
692                 Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW );
693                 sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols.get(), false, aRelativePosition );
694 
695                 Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW );
696                 sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows.get(), true, aRelativePosition );
697 
698                 Reference< XCellRange > xSheetCellRange( xSheet, UNO_QUERY_THROW );
699                 Any aNewAnchorCell( xSheetCellRange->getCellByPosition( nNewAnchorCol, nNewAnchorRow ) );
700                 m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, aNewAnchorCell );
701             }
702             break;
703 
704             default:
705                 OSL_ENSURE( false, "FormGeometryHandler::impl_setSheetAnchorType_nothrow: illegal anchor type!" );
706                 break;
707             }
708         }
709         catch( const Exception& )
710         {
711         	DBG_UNHANDLED_EXCEPTION();
712         }
713     }
714 
715     //====================================================================
716 	//= ShapeGeometryChangeNotifier - implementation
717 	//====================================================================
718     namespace
719     {
720         struct EventTranslation
721         {
722             ::rtl::OUString sPropertyName;
723             Any             aNewPropertyValue;
724 
EventTranslationpcr::__anon6c6d1ea30211::EventTranslation725             EventTranslation( const ::rtl::OUString& _propertyName, const Any& _newPropertyValue )
726                 :sPropertyName( _propertyName )
727                 ,aNewPropertyValue( _newPropertyValue )
728             {
729             }
730         };
731     }
732 
733     //--------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & _event)734     void SAL_CALL ShapeGeometryChangeNotifier::propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException)
735     {
736         ::comphelper::ComponentMethodGuard aGuard( *this );
737 
738         ::std::vector< EventTranslation > aEventTranslations;
739         aEventTranslations.reserve(2);
740 
741         if ( _event.PropertyName.equalsAscii( "Position" ) )
742         {
743             AwtPoint aPos = m_xShape->getPosition();
744             aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONX, makeAny( aPos.X ) ) );
745             aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONY, makeAny( aPos.Y ) ) );
746         }
747         else if ( _event.PropertyName.equalsAscii( "Size" ) )
748         {
749             AwtSize aSize = m_xShape->getSize();
750             aEventTranslations.push_back( EventTranslation( PROPERTY_WIDTH, makeAny( aSize.Width ) ) );
751             aEventTranslations.push_back( EventTranslation( PROPERTY_HEIGHT, makeAny( aSize.Height ) ) );
752         }
753         else if ( _event.PropertyName == PROPERTY_ANCHOR_TYPE )
754         {
755             aEventTranslations.push_back( EventTranslation( PROPERTY_TEXT_ANCHOR_TYPE, makeAny( _event.NewValue ) ) );
756         }
757         else if ( _event.PropertyName == PROPERTY_ANCHOR )
758         {
759             aEventTranslations.push_back( EventTranslation( PROPERTY_SHEET_ANCHOR_TYPE, makeAny( _event.NewValue ) ) );
760         }
761 
762         PropertyChangeEvent aTranslatedEvent( _event );
763         aTranslatedEvent.Source = m_rParent;
764 
765         aGuard.clear();
766         for ( ::std::vector< EventTranslation >::const_iterator t = aEventTranslations.begin();
767               t != aEventTranslations.end();
768               ++t
769             )
770         {
771             aTranslatedEvent.PropertyName = t->sPropertyName;
772             aTranslatedEvent.NewValue = t->aNewPropertyValue;
773             m_aPropertyChangeListeners.notifyEach( &XPropertyChangeListener::propertyChange, aTranslatedEvent );
774         }
775     }
776 
777     //--------------------------------------------------------------------
disposing(const EventObject &)778     void SAL_CALL ShapeGeometryChangeNotifier::disposing( const EventObject& /*_event*/ ) throw (RuntimeException)
779     {
780         ::comphelper::ComponentMethodGuard aGuard( *this );
781         impl_dispose_nothrow();
782     }
783 
784     //--------------------------------------------------------------------
impl_init_nothrow()785     void ShapeGeometryChangeNotifier::impl_init_nothrow()
786     {
787         osl_incrementInterlockedCount( &m_refCount );
788         try
789         {
790             Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW );
791             xShapeProperties->addPropertyChangeListener( ::rtl::OUString(), this );
792         }
793         catch( const Exception& )
794         {
795         	DBG_UNHANDLED_EXCEPTION();
796         }
797         osl_decrementInterlockedCount( &m_refCount );
798     }
799 
800     //--------------------------------------------------------------------
impl_dispose_nothrow()801     void ShapeGeometryChangeNotifier::impl_dispose_nothrow()
802     {
803         try
804         {
805             Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW );
806             xShapeProperties->removePropertyChangeListener( ::rtl::OUString(), this );
807         }
808         catch( const Exception& )
809         {
810         	DBG_UNHANDLED_EXCEPTION();
811         }
812 
813         getBroadcastHelper().bDisposed = true;
814     }
815 
816 //........................................................................
817 } // namespace pcr
818 //........................................................................
819 
createRegistryInfo_FormGeometryHandler()820 extern "C" void SAL_CALL createRegistryInfo_FormGeometryHandler()
821 {
822     ::pcr::FormGeometryHandler::registerImplementation();
823 }
824