Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "propertyhandler.hxx"
22 : #include "formmetadata.hxx"
23 : #include "formstrings.hxx"
24 : #include "handlerhelper.hxx"
25 : #include "cellbindinghelper.hxx"
26 :
27 : #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
28 : #include <com/sun/star/awt/XControlModel.hpp>
29 : #include <com/sun/star/drawing/XControlShape.hpp>
30 : #include <com/sun/star/container/XMap.hpp>
31 : #include <com/sun/star/inspection/XNumericControl.hpp>
32 : #include <com/sun/star/util/MeasureUnit.hpp>
33 : #include <com/sun/star/text/TextContentAnchorType.hpp>
34 : #include <com/sun/star/lang/XServiceInfo.hpp>
35 : #include <com/sun/star/sheet/XSpreadsheet.hpp>
36 : #include <com/sun/star/table/XColumnRowRange.hpp>
37 : #include <com/sun/star/table/XCellRange.hpp>
38 : #include <com/sun/star/container/XChild.hpp>
39 : #include <com/sun/star/form/XGridColumnFactory.hpp>
40 :
41 : #include <cppuhelper/interfacecontainer.hxx>
42 : #include <comphelper/componentbase.hxx>
43 : #include <tools/debug.hxx>
44 : #include <tools/diagnose_ex.h>
45 :
46 : //........................................................................
47 : namespace pcr
48 : {
49 : //........................................................................
50 :
51 : /** === begin UNO using === **/
52 : using ::com::sun::star::uno::Reference;
53 : using ::com::sun::star::uno::XInterface;
54 : using ::com::sun::star::uno::UNO_QUERY;
55 : using ::com::sun::star::uno::UNO_QUERY_THROW;
56 : using ::com::sun::star::uno::UNO_SET_THROW;
57 : using ::com::sun::star::uno::Exception;
58 : using ::com::sun::star::uno::RuntimeException;
59 : using ::com::sun::star::uno::Any;
60 : using ::com::sun::star::uno::makeAny;
61 : using ::com::sun::star::uno::Sequence;
62 : using ::com::sun::star::uno::Type;
63 : using ::com::sun::star::uno::XComponentContext;
64 : using ::com::sun::star::beans::UnknownPropertyException;
65 : using ::com::sun::star::beans::Property;
66 : using ::com::sun::star::awt::XControlModel;
67 : using ::com::sun::star::drawing::XControlShape;
68 : using ::com::sun::star::container::XMap;
69 : using ::com::sun::star::inspection::LineDescriptor;
70 : using ::com::sun::star::inspection::XPropertyControlFactory;
71 : using ::com::sun::star::lang::NullPointerException;
72 : using ::com::sun::star::beans::Optional;
73 : using ::com::sun::star::inspection::XNumericControl;
74 : using ::com::sun::star::drawing::XShape;
75 : using ::com::sun::star::beans::PropertyChangeEvent;
76 : using ::com::sun::star::lang::EventObject;
77 : using ::com::sun::star::beans::XPropertySet;
78 : using ::com::sun::star::beans::XPropertyChangeListener;
79 : using ::com::sun::star::text::TextContentAnchorType;
80 : using ::com::sun::star::text::TextContentAnchorType_AT_PARAGRAPH;
81 : using ::com::sun::star::text::TextContentAnchorType_AS_CHARACTER;
82 : using ::com::sun::star::beans::XPropertySetInfo;
83 : using ::com::sun::star::inspection::XObjectInspectorUI;
84 : using ::com::sun::star::lang::XServiceInfo;
85 : using ::com::sun::star::sheet::XSpreadsheet;
86 : using ::com::sun::star::table::XColumnRowRange;
87 : using ::com::sun::star::table::XTableColumns;
88 : using ::com::sun::star::table::XTableRows;
89 : using ::com::sun::star::table::XCellRange;
90 : using ::com::sun::star::container::XIndexAccess;
91 : using ::com::sun::star::container::XChild;
92 : using ::com::sun::star::form::XGridColumnFactory;
93 : /** === end UNO using === **/
94 : namespace MeasureUnit = ::com::sun::star::util::MeasureUnit;
95 :
96 : typedef ::com::sun::star::awt::Point AwtPoint;
97 : typedef ::com::sun::star::awt::Size AwtSize;
98 :
99 : #define ANCHOR_TO_SHEET 0
100 : #define ANCHOR_TO_CELL 1
101 :
102 : //====================================================================
103 : //= BroadcastHelperBase
104 : //====================================================================
105 0 : class BroadcastHelperBase
106 : {
107 : protected:
108 0 : BroadcastHelperBase( ::osl::Mutex& _rMutex )
109 0 : :maBHelper( _rMutex )
110 : {
111 0 : }
112 :
113 : protected:
114 0 : ::cppu::OBroadcastHelper& getBroadcastHelper() { return maBHelper; }
115 :
116 : private:
117 : ::cppu::OBroadcastHelper maBHelper;
118 : };
119 :
120 : //====================================================================
121 : //= ShapeGeometryChangeNotifier - declaration
122 : //====================================================================
123 : /** helper class to work around the ...unfortunate implementation of property change broadcasts
124 : in the XShape implementation, which broadcasts way too generous and unspecified
125 : */
126 : typedef ::comphelper::ComponentBase ShapeGeometryChangeNotifier_CBase;
127 : typedef ::cppu::WeakImplHelper1 < ::com::sun::star::beans::XPropertyChangeListener
128 : > ShapeGeometryChangeNotifier_IBase;
129 :
130 : class ShapeGeometryChangeNotifier :public BroadcastHelperBase
131 : ,public ShapeGeometryChangeNotifier_CBase
132 : ,public ShapeGeometryChangeNotifier_IBase
133 : {
134 : public:
135 0 : ShapeGeometryChangeNotifier( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rParentMutex, const Reference< XShape >& _shape )
136 : :BroadcastHelperBase( _rParentMutex )
137 0 : ,ShapeGeometryChangeNotifier_CBase( BroadcastHelperBase::getBroadcastHelper(), ::comphelper::ComponentBase::NoInitializationNeeded() )
138 : ,ShapeGeometryChangeNotifier_IBase()
139 : ,m_rParent( _rParent )
140 : ,m_aPropertyChangeListeners( _rParentMutex )
141 0 : ,m_xShape( _shape )
142 : {
143 0 : ENSURE_OR_THROW( m_xShape.is(), "illegal shape!" );
144 0 : impl_init_nothrow();
145 0 : }
146 :
147 : // property change broadcasting
148 0 : void addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener )
149 : {
150 0 : m_aPropertyChangeListeners.addInterface( _listener );
151 0 : }
152 0 : void removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener )
153 : {
154 0 : m_aPropertyChangeListeners.removeInterface( _listener );
155 0 : }
156 :
157 : // XComponent equivalent
158 0 : void dispose()
159 : {
160 0 : ::osl::MutexGuard aGuard( getMutex() );
161 0 : impl_dispose_nothrow();
162 0 : }
163 :
164 : // XInterface
165 0 : virtual void SAL_CALL acquire( ) throw ()
166 : {
167 0 : m_rParent.acquire();
168 0 : }
169 :
170 0 : virtual void SAL_CALL release( ) throw ()
171 : {
172 0 : m_rParent.release();
173 0 : }
174 :
175 : // XPropertyChangeListener
176 : virtual void SAL_CALL propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException);
177 :
178 : // XEventListener
179 : virtual void SAL_CALL disposing( const EventObject& _event ) throw (RuntimeException);
180 :
181 : protected:
182 0 : virtual ~ShapeGeometryChangeNotifier()
183 0 : {
184 0 : if ( !getBroadcastHelper().bDisposed )
185 : {
186 0 : acquire();
187 0 : dispose();
188 : }
189 0 : }
190 :
191 : protected:
192 0 : ::cppu::OBroadcastHelper& getBroadcastHelper() { return BroadcastHelperBase::getBroadcastHelper(); }
193 :
194 : private:
195 : void impl_init_nothrow();
196 : void impl_dispose_nothrow();
197 :
198 : private:
199 : ::cppu::OWeakObject& m_rParent;
200 : ::cppu::OInterfaceContainerHelper m_aPropertyChangeListeners;
201 : Reference< XShape > m_xShape;
202 : };
203 :
204 : //====================================================================
205 : //= FormGeometryHandler - declaration
206 : //====================================================================
207 : class FormGeometryHandler;
208 : typedef HandlerComponentBase< FormGeometryHandler > FormGeometryHandler_Base;
209 : /** a property handler for any virtual string properties
210 : */
211 : class FormGeometryHandler : public FormGeometryHandler_Base
212 : {
213 : public:
214 : FormGeometryHandler(
215 : const Reference< XComponentContext >& _rxContext
216 : );
217 :
218 : static ::rtl::OUString SAL_CALL getImplementationName_static( ) throw (RuntimeException);
219 : static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( ) throw (RuntimeException);
220 :
221 : protected:
222 : ~FormGeometryHandler();
223 :
224 : protected:
225 : // XPropertyHandler overriables
226 : virtual Any SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException);
227 : virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException);
228 : 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);
229 : virtual void SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException);
230 : virtual void SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException);
231 : virtual Sequence< ::rtl::OUString > SAL_CALL getActuatingProperties( ) throw (RuntimeException);
232 : 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);
233 :
234 : // OComponentHandler overridables
235 : virtual void SAL_CALL disposing();
236 :
237 : // PropertyHandler overridables
238 : virtual Sequence< Property > SAL_CALL doDescribeSupportedProperties() const;
239 :
240 : protected:
241 : virtual void onNewComponent();
242 :
243 : private:
244 : bool impl_haveTextAnchorType_nothrow() const;
245 : bool impl_haveSheetAnchorType_nothrow() const;
246 : void impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const;
247 :
248 : private:
249 : Reference< XControlShape > m_xAssociatedShape;
250 : Reference< XPropertySet > m_xShapeProperties;
251 : ::rtl::Reference< ShapeGeometryChangeNotifier > m_xChangeNotifier;
252 : };
253 :
254 : //====================================================================
255 : //= FormGeometryHandler - implementation
256 : //====================================================================
257 : DBG_NAME( FormGeometryHandler )
258 : //--------------------------------------------------------------------
259 0 : FormGeometryHandler::FormGeometryHandler( const Reference< XComponentContext >& _rxContext )
260 0 : :FormGeometryHandler_Base( _rxContext )
261 : {
262 : DBG_CTOR( FormGeometryHandler, NULL );
263 0 : }
264 :
265 : //--------------------------------------------------------------------
266 0 : FormGeometryHandler::~FormGeometryHandler( )
267 : {
268 0 : if ( !rBHelper.bDisposed )
269 : {
270 0 : acquire();
271 0 : dispose();
272 : }
273 :
274 : DBG_DTOR( FormGeometryHandler, NULL );
275 0 : }
276 :
277 : //--------------------------------------------------------------------
278 0 : void FormGeometryHandler::onNewComponent()
279 : {
280 0 : if ( m_xChangeNotifier.is() )
281 : {
282 0 : m_xChangeNotifier->dispose();
283 0 : m_xChangeNotifier.clear();
284 : }
285 0 : m_xAssociatedShape.clear();
286 0 : m_xShapeProperties.clear();
287 :
288 0 : FormGeometryHandler_Base::onNewComponent();
289 :
290 : try
291 : {
292 0 : Reference< XControlModel > xControlModel( m_xComponent, UNO_QUERY );
293 0 : if ( xControlModel.is() )
294 : {
295 : // do not ask the map for shapes for grid control columns ....
296 0 : Reference< XChild > xCompChild( m_xComponent, UNO_QUERY_THROW );
297 0 : Reference< XGridColumnFactory > xCheckGrid( xCompChild->getParent(), UNO_QUERY );
298 0 : if ( !xCheckGrid.is() )
299 : {
300 0 : Reference< XMap > xControlMap( m_aContext.getContextValueByAsciiName( "ControlShapeAccess" ), UNO_QUERY_THROW );
301 0 : m_xAssociatedShape.set( xControlMap->get( makeAny( xControlModel ) ), UNO_QUERY_THROW );
302 0 : m_xShapeProperties.set( m_xAssociatedShape, UNO_QUERY_THROW );
303 0 : }
304 0 : }
305 : }
306 0 : catch( const Exception& )
307 : {
308 : DBG_UNHANDLED_EXCEPTION();
309 : }
310 :
311 0 : if ( m_xAssociatedShape.is() )
312 0 : m_xChangeNotifier = new ShapeGeometryChangeNotifier( *this, m_aMutex, m_xAssociatedShape.get() );
313 0 : }
314 :
315 : //--------------------------------------------------------------------
316 0 : ::rtl::OUString SAL_CALL FormGeometryHandler::getImplementationName_static( ) throw (RuntimeException)
317 : {
318 0 : return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.FormGeometryHandler" ) );
319 : }
320 :
321 : //--------------------------------------------------------------------
322 0 : Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getSupportedServiceNames_static( ) throw (RuntimeException)
323 : {
324 0 : Sequence< ::rtl::OUString > aSupported( 1 );
325 0 : aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.FormGeometryHandler" ) );
326 0 : return aSupported;
327 : }
328 :
329 : //--------------------------------------------------------------------
330 0 : Any SAL_CALL FormGeometryHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
331 : {
332 0 : ::osl::MutexGuard aGuard( m_aMutex );
333 0 : PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
334 :
335 0 : ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this );
336 0 : ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: no shape properties!", *this );
337 :
338 0 : Any aReturn;
339 : try
340 : {
341 0 : switch ( nPropId )
342 : {
343 : case PROPERTY_ID_POSITIONX:
344 0 : aReturn <<= m_xAssociatedShape->getPosition().X;
345 0 : break;
346 : case PROPERTY_ID_POSITIONY:
347 0 : aReturn <<= m_xAssociatedShape->getPosition().Y;
348 0 : break;
349 : case PROPERTY_ID_WIDTH:
350 0 : aReturn <<= m_xAssociatedShape->getSize().Width;
351 0 : break;
352 : case PROPERTY_ID_HEIGHT:
353 0 : aReturn <<= m_xAssociatedShape->getSize().Height;
354 0 : break;
355 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
356 0 : aReturn = m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR_TYPE );
357 : OSL_ENSURE( aReturn.hasValue(), "FormGeometryHandler::getPropertyValue: illegal anchor type!" );
358 0 : break;
359 : case PROPERTY_ID_SHEET_ANCHOR_TYPE:
360 : {
361 0 : Reference< XSpreadsheet > xAnchorSheet( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ), UNO_QUERY );
362 0 : aReturn <<= sal_Int32( xAnchorSheet.is() ? ANCHOR_TO_SHEET : ANCHOR_TO_CELL );
363 : }
364 0 : break;
365 :
366 : default:
367 : OSL_FAIL( "FormGeometryHandler::getPropertyValue: huh?" );
368 0 : break;
369 : }
370 : }
371 0 : catch( const Exception& )
372 : {
373 : DBG_UNHANDLED_EXCEPTION();
374 : }
375 0 : return aReturn;
376 : }
377 :
378 : //--------------------------------------------------------------------
379 0 : void SAL_CALL FormGeometryHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
380 : {
381 0 : ::osl::MutexGuard aGuard( m_aMutex );
382 0 : PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
383 :
384 0 : ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this );
385 0 : ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: properties, but no shape!", *this );
386 :
387 : try
388 : {
389 0 : switch ( nPropId )
390 : {
391 : case PROPERTY_ID_POSITIONX:
392 : case PROPERTY_ID_POSITIONY:
393 : {
394 0 : sal_Int32 nPosition(0);
395 0 : OSL_VERIFY( _rValue >>= nPosition );
396 :
397 0 : AwtPoint aPos( m_xAssociatedShape->getPosition() );
398 0 : if ( nPropId == PROPERTY_ID_POSITIONX )
399 0 : aPos.X = nPosition;
400 : else
401 0 : aPos.Y = nPosition;
402 0 : m_xAssociatedShape->setPosition( aPos );
403 : }
404 0 : break;
405 :
406 : case PROPERTY_ID_WIDTH:
407 : case PROPERTY_ID_HEIGHT:
408 : {
409 0 : sal_Int32 nSize(0);
410 0 : OSL_VERIFY( _rValue >>= nSize );
411 :
412 0 : AwtSize aSize( m_xAssociatedShape->getSize() );
413 0 : if ( nPropId == PROPERTY_ID_WIDTH )
414 0 : aSize.Width = nSize;
415 : else
416 0 : aSize.Height = nSize;
417 0 : m_xAssociatedShape->setSize( aSize );
418 : }
419 0 : break;
420 :
421 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
422 0 : m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR_TYPE, _rValue );
423 0 : break;
424 :
425 : case PROPERTY_ID_SHEET_ANCHOR_TYPE:
426 : {
427 0 : sal_Int32 nSheetAnchorType = 0;
428 0 : OSL_VERIFY( _rValue >>= nSheetAnchorType );
429 0 : impl_setSheetAnchorType_nothrow( nSheetAnchorType );
430 : }
431 0 : break;
432 :
433 : default:
434 : OSL_FAIL( "FormGeometryHandler::getPropertyValue: huh?" );
435 0 : break;
436 : }
437 : }
438 0 : catch( const Exception& )
439 : {
440 : DBG_UNHANDLED_EXCEPTION();
441 0 : }
442 0 : }
443 :
444 : //--------------------------------------------------------------------
445 0 : LineDescriptor SAL_CALL FormGeometryHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
446 : const Reference< XPropertyControlFactory >& _rxControlFactory )
447 : throw (UnknownPropertyException, NullPointerException, RuntimeException)
448 : {
449 0 : ::osl::MutexGuard aGuard( m_aMutex );
450 0 : PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
451 :
452 0 : LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) );
453 : try
454 : {
455 0 : bool bIsSize = false;
456 0 : switch ( nPropId )
457 : {
458 : case PROPERTY_ID_WIDTH:
459 : case PROPERTY_ID_HEIGHT:
460 0 : bIsSize = true;
461 : // NO break!
462 : case PROPERTY_ID_POSITIONX:
463 : case PROPERTY_ID_POSITIONY:
464 : {
465 0 : Optional< double > aZero( sal_True, 0 );
466 0 : Optional< double > aValueNotPresent( sal_False, 0 );
467 : aLineDesc.Control = PropertyHandlerHelper::createNumericControl(
468 0 : _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent, sal_False );
469 :
470 0 : Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW );
471 0 : xNumericControl->setValueUnit( MeasureUnit::MM_100TH );
472 0 : xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() );
473 : }
474 0 : break;
475 :
476 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
477 : case PROPERTY_ID_SHEET_ANCHOR_TYPE:
478 : // default handling from PropertyHandler is sufficient
479 0 : break;
480 :
481 : default:
482 : OSL_FAIL( "FormGeometryHandler::describePropertyLine: huh?" );
483 0 : break;
484 : }
485 : }
486 0 : catch( const Exception& )
487 : {
488 : DBG_UNHANDLED_EXCEPTION();
489 : }
490 0 : return aLineDesc;
491 : }
492 :
493 : //--------------------------------------------------------------------
494 0 : void SAL_CALL FormGeometryHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException)
495 : {
496 0 : ::osl::MutexGuard aGuard( m_aMutex );
497 : OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" );
498 0 : if ( m_xChangeNotifier.is() )
499 0 : m_xChangeNotifier->addPropertyChangeListener( _listener );
500 0 : }
501 :
502 : //--------------------------------------------------------------------
503 0 : void SAL_CALL FormGeometryHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException)
504 : {
505 0 : ::osl::MutexGuard aGuard( m_aMutex );
506 : OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" );
507 0 : if ( m_xChangeNotifier.is() )
508 0 : m_xChangeNotifier->removePropertyChangeListener( _listener );
509 0 : }
510 :
511 : //--------------------------------------------------------------------
512 0 : Sequence< ::rtl::OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( ) throw (RuntimeException)
513 : {
514 0 : Sequence< ::rtl::OUString > aInterestedIn(1);
515 0 : aInterestedIn[0] = PROPERTY_TEXT_ANCHOR_TYPE;
516 0 : return aInterestedIn;
517 : }
518 :
519 : //--------------------------------------------------------------------
520 0 : 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)
521 : {
522 0 : if ( !_rxInspectorUI.is() )
523 0 : throw NullPointerException();
524 :
525 0 : ::osl::MutexGuard aGuard( m_aMutex );
526 0 : PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) );
527 :
528 0 : switch ( nActuatingPropId )
529 : {
530 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
531 : {
532 0 : TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH );
533 0 : OSL_VERIFY( _rNewValue >>= eAnchorType );
534 0 : _rxInspectorUI->enablePropertyUI( PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER );
535 : }
536 0 : break;
537 : default:
538 : OSL_FAIL( "FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" );
539 0 : break;
540 0 : }
541 0 : }
542 :
543 : //--------------------------------------------------------------------
544 0 : Sequence< Property > SAL_CALL FormGeometryHandler::doDescribeSupportedProperties() const
545 : {
546 0 : if ( !m_xAssociatedShape.is() )
547 0 : return Sequence< Property >();
548 :
549 0 : ::std::vector< Property > aProperties;
550 :
551 0 : addInt32PropertyDescription( aProperties, PROPERTY_POSITIONX );
552 0 : addInt32PropertyDescription( aProperties, PROPERTY_POSITIONY );
553 0 : addInt32PropertyDescription( aProperties, PROPERTY_WIDTH );
554 0 : addInt32PropertyDescription( aProperties, PROPERTY_HEIGHT );
555 :
556 0 : if ( impl_haveTextAnchorType_nothrow() )
557 0 : implAddPropertyDescription( aProperties, PROPERTY_TEXT_ANCHOR_TYPE, ::cppu::UnoType< TextContentAnchorType >::get() );
558 :
559 0 : if ( impl_haveSheetAnchorType_nothrow() )
560 0 : addInt32PropertyDescription( aProperties, PROPERTY_SHEET_ANCHOR_TYPE );
561 :
562 0 : return Sequence< Property >( &(*aProperties.begin()), aProperties.size() );
563 : }
564 :
565 : //--------------------------------------------------------------------
566 0 : void SAL_CALL FormGeometryHandler::disposing()
567 : {
568 0 : FormGeometryHandler_Base::disposing();
569 :
570 0 : if ( m_xChangeNotifier.is() )
571 : {
572 0 : m_xChangeNotifier->dispose();
573 0 : m_xChangeNotifier.clear();
574 : }
575 0 : }
576 :
577 : //--------------------------------------------------------------------
578 0 : bool FormGeometryHandler::impl_haveTextAnchorType_nothrow() const
579 : {
580 0 : ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" );
581 : try
582 : {
583 0 : Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
584 0 : if ( xPSI->hasPropertyByName( PROPERTY_ANCHOR_TYPE ) )
585 0 : return true;
586 : }
587 0 : catch( const Exception& )
588 : {
589 : DBG_UNHANDLED_EXCEPTION();
590 : }
591 0 : return false;
592 : }
593 :
594 : //--------------------------------------------------------------------
595 0 : bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow() const
596 : {
597 0 : ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" );
598 : try
599 : {
600 0 : Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
601 0 : if ( !xPSI->hasPropertyByName( PROPERTY_ANCHOR ) )
602 0 : return false;
603 0 : Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW );
604 0 : if ( xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) ) ) )
605 0 : return true;
606 : }
607 0 : catch( const Exception& )
608 : {
609 : DBG_UNHANDLED_EXCEPTION();
610 : }
611 0 : return false;
612 : }
613 :
614 : //--------------------------------------------------------------------
615 : namespace
616 : {
617 0 : static sal_Int32 lcl_getLowerBoundRowOrColumn( const Reference< XIndexAccess >& _rxRowsOrColumns, const bool _bRows,
618 : const AwtPoint& _rRelativePosition )
619 : {
620 0 : sal_Int32 nAccumulated = 0;
621 :
622 0 : const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X;
623 :
624 0 : sal_Int32 nElements = _rxRowsOrColumns->getCount();
625 0 : sal_Int32 currentPos = 0;
626 0 : for ( currentPos=0; currentPos<nElements; ++currentPos )
627 : {
628 0 : Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW );
629 :
630 0 : sal_Bool bIsVisible = sal_True;
631 0 : OSL_VERIFY( xRowOrColumn->getPropertyValue( PROPERTY_IS_VISIBLE ) >>= bIsVisible );
632 0 : if ( !bIsVisible )
633 0 : continue;
634 :
635 0 : sal_Int32 nHeightOrWidth( 0 );
636 0 : OSL_VERIFY( xRowOrColumn->getPropertyValue( _bRows ? PROPERTY_HEIGHT : PROPERTY_WIDTH ) >>= nHeightOrWidth );
637 :
638 0 : if ( nAccumulated + nHeightOrWidth > rRelativePos )
639 : break;
640 :
641 0 : nAccumulated += nHeightOrWidth;
642 0 : }
643 :
644 0 : return currentPos;
645 : }
646 : }
647 :
648 : //--------------------------------------------------------------------
649 0 : void FormGeometryHandler::impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const
650 : {
651 0 : ENSURE_OR_THROW( m_xShapeProperties.is(), "illegal to be called without shape properties." );
652 : try
653 : {
654 0 : CellBindingHelper aHelper( m_xComponent, impl_getContextDocument_nothrow() );
655 : // find the sheet which the control belongs to
656 0 : Reference< XSpreadsheet > xSheet;
657 0 : aHelper.getControlSheetIndex( xSheet );
658 :
659 0 : switch ( _nAnchorType )
660 : {
661 : case ANCHOR_TO_SHEET:
662 : OSL_ENSURE( xSheet.is(),
663 : "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" );
664 0 : if ( xSheet.is() )
665 : {
666 0 : AwtPoint aPreservePosition( m_xAssociatedShape->getPosition() );
667 0 : m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, makeAny( xSheet ) );
668 0 : m_xAssociatedShape->setPosition( aPreservePosition );
669 : }
670 0 : break;
671 :
672 : case ANCHOR_TO_CELL:
673 : {
674 0 : Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW );
675 :
676 : // get the current anchor
677 0 : Reference< XSpreadsheet > xCurrentAnchor;
678 0 : OSL_VERIFY( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ) >>= xCurrentAnchor );
679 : OSL_ENSURE( xCurrentAnchor.is(), "FormGeometryHandler::impl_setSheetAnchorType_nothrow: only to be called when currently anchored to a sheet!" );
680 :
681 : // get the current position
682 0 : AwtPoint aRelativePosition( m_xAssociatedShape->getPosition() );
683 :
684 0 : Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW );
685 0 : sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols.get(), false, aRelativePosition );
686 :
687 0 : Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW );
688 0 : sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows.get(), true, aRelativePosition );
689 :
690 0 : Reference< XCellRange > xSheetCellRange( xSheet, UNO_QUERY_THROW );
691 0 : Any aNewAnchorCell( xSheetCellRange->getCellByPosition( nNewAnchorCol, nNewAnchorRow ) );
692 0 : m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, aNewAnchorCell );
693 : }
694 0 : break;
695 :
696 : default:
697 : OSL_FAIL( "FormGeometryHandler::impl_setSheetAnchorType_nothrow: illegal anchor type!" );
698 0 : break;
699 0 : }
700 : }
701 0 : catch( const Exception& )
702 : {
703 : DBG_UNHANDLED_EXCEPTION();
704 : }
705 0 : }
706 :
707 : //====================================================================
708 : //= ShapeGeometryChangeNotifier - implementation
709 : //====================================================================
710 : namespace
711 : {
712 0 : struct EventTranslation
713 : {
714 : ::rtl::OUString sPropertyName;
715 : Any aNewPropertyValue;
716 :
717 0 : EventTranslation( const ::rtl::OUString& _propertyName, const Any& _newPropertyValue )
718 : :sPropertyName( _propertyName )
719 0 : ,aNewPropertyValue( _newPropertyValue )
720 : {
721 0 : }
722 : };
723 : }
724 :
725 : //--------------------------------------------------------------------
726 0 : void SAL_CALL ShapeGeometryChangeNotifier::propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException)
727 : {
728 0 : ::comphelper::ComponentMethodGuard aGuard( *this );
729 :
730 0 : ::std::vector< EventTranslation > aEventTranslations;
731 0 : aEventTranslations.reserve(2);
732 :
733 0 : if ( _event.PropertyName == "Position" )
734 : {
735 0 : AwtPoint aPos = m_xShape->getPosition();
736 0 : aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONX, makeAny( aPos.X ) ) );
737 0 : aEventTranslations.push_back( EventTranslation( PROPERTY_POSITIONY, makeAny( aPos.Y ) ) );
738 : }
739 0 : else if ( _event.PropertyName == "Size" )
740 : {
741 0 : AwtSize aSize = m_xShape->getSize();
742 0 : aEventTranslations.push_back( EventTranslation( PROPERTY_WIDTH, makeAny( aSize.Width ) ) );
743 0 : aEventTranslations.push_back( EventTranslation( PROPERTY_HEIGHT, makeAny( aSize.Height ) ) );
744 : }
745 0 : else if ( _event.PropertyName == PROPERTY_ANCHOR_TYPE )
746 : {
747 0 : aEventTranslations.push_back( EventTranslation( PROPERTY_TEXT_ANCHOR_TYPE, makeAny( _event.NewValue ) ) );
748 : }
749 0 : else if ( _event.PropertyName == PROPERTY_ANCHOR )
750 : {
751 0 : aEventTranslations.push_back( EventTranslation( PROPERTY_SHEET_ANCHOR_TYPE, makeAny( _event.NewValue ) ) );
752 : }
753 :
754 0 : PropertyChangeEvent aTranslatedEvent( _event );
755 0 : aTranslatedEvent.Source = m_rParent;
756 :
757 0 : aGuard.clear();
758 0 : for ( ::std::vector< EventTranslation >::const_iterator t = aEventTranslations.begin();
759 0 : t != aEventTranslations.end();
760 : ++t
761 : )
762 : {
763 0 : aTranslatedEvent.PropertyName = t->sPropertyName;
764 0 : aTranslatedEvent.NewValue = t->aNewPropertyValue;
765 0 : m_aPropertyChangeListeners.notifyEach( &XPropertyChangeListener::propertyChange, aTranslatedEvent );
766 0 : }
767 0 : }
768 :
769 : //--------------------------------------------------------------------
770 0 : void SAL_CALL ShapeGeometryChangeNotifier::disposing( const EventObject& /*_event*/ ) throw (RuntimeException)
771 : {
772 0 : ::comphelper::ComponentMethodGuard aGuard( *this );
773 0 : impl_dispose_nothrow();
774 0 : }
775 :
776 : //--------------------------------------------------------------------
777 0 : void ShapeGeometryChangeNotifier::impl_init_nothrow()
778 : {
779 0 : osl_atomic_increment( &m_refCount );
780 : try
781 : {
782 0 : Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW );
783 0 : xShapeProperties->addPropertyChangeListener( ::rtl::OUString(), this );
784 : }
785 0 : catch( const Exception& )
786 : {
787 : DBG_UNHANDLED_EXCEPTION();
788 : }
789 0 : osl_atomic_decrement( &m_refCount );
790 0 : }
791 :
792 : //--------------------------------------------------------------------
793 0 : void ShapeGeometryChangeNotifier::impl_dispose_nothrow()
794 : {
795 : try
796 : {
797 0 : Reference< XPropertySet > xShapeProperties( m_xShape, UNO_QUERY_THROW );
798 0 : xShapeProperties->removePropertyChangeListener( ::rtl::OUString(), this );
799 : }
800 0 : catch( const Exception& )
801 : {
802 : DBG_UNHANDLED_EXCEPTION();
803 : }
804 :
805 0 : getBroadcastHelper().bDisposed = true;
806 0 : }
807 :
808 : //........................................................................
809 : } // namespace pcr
810 : //........................................................................
811 :
812 0 : extern "C" void SAL_CALL createRegistryInfo_FormGeometryHandler()
813 : {
814 0 : ::pcr::FormGeometryHandler::registerImplementation();
815 0 : }
816 :
817 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|