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