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 : using ::com::sun::star::uno::Reference;
52 : using ::com::sun::star::uno::XInterface;
53 : using ::com::sun::star::uno::UNO_QUERY;
54 : using ::com::sun::star::uno::UNO_QUERY_THROW;
55 : using ::com::sun::star::uno::UNO_SET_THROW;
56 : using ::com::sun::star::uno::Exception;
57 : using ::com::sun::star::uno::RuntimeException;
58 : using ::com::sun::star::uno::Any;
59 : using ::com::sun::star::uno::makeAny;
60 : using ::com::sun::star::uno::Sequence;
61 : using ::com::sun::star::uno::Type;
62 : using ::com::sun::star::uno::XComponentContext;
63 : using ::com::sun::star::beans::UnknownPropertyException;
64 : using ::com::sun::star::beans::Property;
65 : using ::com::sun::star::awt::XControlModel;
66 : using ::com::sun::star::drawing::XControlShape;
67 : using ::com::sun::star::container::XMap;
68 : using ::com::sun::star::inspection::LineDescriptor;
69 : using ::com::sun::star::inspection::XPropertyControlFactory;
70 : using ::com::sun::star::lang::NullPointerException;
71 : using ::com::sun::star::beans::Optional;
72 : using ::com::sun::star::inspection::XNumericControl;
73 : using ::com::sun::star::drawing::XShape;
74 : using ::com::sun::star::beans::PropertyChangeEvent;
75 : using ::com::sun::star::lang::EventObject;
76 : using ::com::sun::star::beans::XPropertySet;
77 : using ::com::sun::star::beans::XPropertyChangeListener;
78 : using ::com::sun::star::text::TextContentAnchorType;
79 : using ::com::sun::star::text::TextContentAnchorType_AT_PARAGRAPH;
80 : using ::com::sun::star::text::TextContentAnchorType_AS_CHARACTER;
81 : using ::com::sun::star::beans::XPropertySetInfo;
82 : using ::com::sun::star::inspection::XObjectInspectorUI;
83 : using ::com::sun::star::lang::XServiceInfo;
84 : using ::com::sun::star::sheet::XSpreadsheet;
85 : using ::com::sun::star::table::XColumnRowRange;
86 : using ::com::sun::star::table::XTableColumns;
87 : using ::com::sun::star::table::XTableRows;
88 : using ::com::sun::star::table::XCellRange;
89 : using ::com::sun::star::container::XIndexAccess;
90 : using ::com::sun::star::container::XChild;
91 : using ::com::sun::star::form::XGridColumnFactory;
92 :
93 : namespace MeasureUnit = ::com::sun::star::util::MeasureUnit;
94 :
95 : typedef ::com::sun::star::awt::Point AwtPoint;
96 : typedef ::com::sun::star::awt::Size AwtSize;
97 :
98 : #define ANCHOR_TO_SHEET 0
99 : #define ANCHOR_TO_CELL 1
100 :
101 :
102 : //= BroadcastHelperBase
103 :
104 0 : class BroadcastHelperBase
105 : {
106 : protected:
107 0 : BroadcastHelperBase( ::osl::Mutex& _rMutex )
108 0 : :maBHelper( _rMutex )
109 : {
110 0 : }
111 :
112 : protected:
113 0 : ::cppu::OBroadcastHelper& getBroadcastHelper() { return maBHelper; }
114 :
115 : private:
116 : ::cppu::OBroadcastHelper maBHelper;
117 : };
118 :
119 :
120 : //= ShapeGeometryChangeNotifier - declaration
121 :
122 : /** helper class to work around the ...unfortunate implementation of property change broadcasts
123 : in the XShape implementation, which broadcasts way too generous and unspecified
124 : */
125 : typedef ::comphelper::ComponentBase ShapeGeometryChangeNotifier_CBase;
126 : typedef ::cppu::WeakImplHelper1 < ::com::sun::star::beans::XPropertyChangeListener
127 : > ShapeGeometryChangeNotifier_IBase;
128 :
129 : class ShapeGeometryChangeNotifier :public BroadcastHelperBase
130 : ,public ShapeGeometryChangeNotifier_CBase
131 : ,public ShapeGeometryChangeNotifier_IBase
132 : {
133 : public:
134 0 : ShapeGeometryChangeNotifier( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rParentMutex, const Reference< XShape >& _shape )
135 : :BroadcastHelperBase( _rParentMutex )
136 0 : ,ShapeGeometryChangeNotifier_CBase( BroadcastHelperBase::getBroadcastHelper(), ::comphelper::ComponentBase::NoInitializationNeeded() )
137 : ,ShapeGeometryChangeNotifier_IBase()
138 : ,m_rParent( _rParent )
139 : ,m_aPropertyChangeListeners( _rParentMutex )
140 0 : ,m_xShape( _shape )
141 : {
142 0 : ENSURE_OR_THROW( m_xShape.is(), "illegal shape!" );
143 0 : impl_init_nothrow();
144 0 : }
145 :
146 : // property change broadcasting
147 0 : void addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener )
148 : {
149 0 : m_aPropertyChangeListeners.addInterface( _listener );
150 0 : }
151 0 : void removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener )
152 : {
153 0 : m_aPropertyChangeListeners.removeInterface( _listener );
154 0 : }
155 :
156 : // XComponent equivalent
157 0 : void dispose()
158 : {
159 0 : ::osl::MutexGuard aGuard( getMutex() );
160 0 : impl_dispose_nothrow();
161 0 : }
162 :
163 : // XInterface
164 0 : virtual void SAL_CALL acquire( ) throw () SAL_OVERRIDE
165 : {
166 0 : m_rParent.acquire();
167 0 : }
168 :
169 0 : virtual void SAL_CALL release( ) throw () SAL_OVERRIDE
170 : {
171 0 : m_rParent.release();
172 0 : }
173 :
174 : // XPropertyChangeListener
175 : virtual void SAL_CALL propertyChange( const PropertyChangeEvent& _event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
176 :
177 : // XEventListener
178 : virtual void SAL_CALL disposing( const EventObject& _event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
179 :
180 : protected:
181 0 : virtual ~ShapeGeometryChangeNotifier()
182 0 : {
183 0 : if ( !getBroadcastHelper().bDisposed )
184 : {
185 0 : acquire();
186 0 : dispose();
187 : }
188 0 : }
189 :
190 : protected:
191 0 : ::cppu::OBroadcastHelper& getBroadcastHelper() { return BroadcastHelperBase::getBroadcastHelper(); }
192 :
193 : private:
194 : void impl_init_nothrow();
195 : void impl_dispose_nothrow();
196 :
197 : private:
198 : ::cppu::OWeakObject& m_rParent;
199 : ::cppu::OInterfaceContainerHelper m_aPropertyChangeListeners;
200 : Reference< XShape > m_xShape;
201 : };
202 :
203 :
204 : //= FormGeometryHandler - declaration
205 :
206 : class FormGeometryHandler;
207 : typedef HandlerComponentBase< FormGeometryHandler > FormGeometryHandler_Base;
208 : /** a property handler for any virtual string properties
209 : */
210 : class FormGeometryHandler : public FormGeometryHandler_Base
211 : {
212 : public:
213 : FormGeometryHandler(
214 : const Reference< XComponentContext >& _rxContext
215 : );
216 :
217 : static OUString SAL_CALL getImplementationName_static( ) throw (RuntimeException);
218 : static Sequence< OUString > SAL_CALL getSupportedServiceNames_static( ) throw (RuntimeException);
219 :
220 : protected:
221 : virtual ~FormGeometryHandler();
222 :
223 : protected:
224 : // XPropertyHandler overriables
225 : virtual Any SAL_CALL getPropertyValue( const OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException, std::exception) SAL_OVERRIDE;
226 : virtual void SAL_CALL setPropertyValue( const OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException, std::exception) SAL_OVERRIDE;
227 : virtual LineDescriptor SAL_CALL describePropertyLine( const 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, std::exception) SAL_OVERRIDE;
228 : virtual void SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
229 : virtual void SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
230 : virtual Sequence< OUString > SAL_CALL getActuatingProperties( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
231 : virtual void SAL_CALL actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (NullPointerException, RuntimeException, std::exception) SAL_OVERRIDE;
232 :
233 : // OComponentHandler overridables
234 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
235 :
236 : // PropertyHandler overridables
237 : virtual Sequence< Property > SAL_CALL doDescribeSupportedProperties() const SAL_OVERRIDE;
238 :
239 : protected:
240 : virtual void onNewComponent() SAL_OVERRIDE;
241 :
242 : private:
243 : bool impl_haveTextAnchorType_nothrow() const;
244 : bool impl_haveSheetAnchorType_nothrow() const;
245 : void impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const;
246 :
247 : private:
248 : Reference< XControlShape > m_xAssociatedShape;
249 : Reference< XPropertySet > m_xShapeProperties;
250 : ::rtl::Reference< ShapeGeometryChangeNotifier > m_xChangeNotifier;
251 : };
252 :
253 :
254 : //= FormGeometryHandler - implementation
255 :
256 :
257 0 : FormGeometryHandler::FormGeometryHandler( const Reference< XComponentContext >& _rxContext )
258 0 : :FormGeometryHandler_Base( _rxContext )
259 : {
260 0 : }
261 :
262 :
263 0 : FormGeometryHandler::~FormGeometryHandler( )
264 : {
265 0 : if ( !rBHelper.bDisposed )
266 : {
267 0 : acquire();
268 0 : dispose();
269 : }
270 :
271 0 : }
272 :
273 :
274 0 : void FormGeometryHandler::onNewComponent()
275 : {
276 0 : if ( m_xChangeNotifier.is() )
277 : {
278 0 : m_xChangeNotifier->dispose();
279 0 : m_xChangeNotifier.clear();
280 : }
281 0 : m_xAssociatedShape.clear();
282 0 : m_xShapeProperties.clear();
283 :
284 0 : FormGeometryHandler_Base::onNewComponent();
285 :
286 : try
287 : {
288 0 : Reference< XControlModel > xControlModel( m_xComponent, UNO_QUERY );
289 0 : if ( xControlModel.is() )
290 : {
291 : // do not ask the map for shapes for grid control columns ....
292 0 : Reference< XChild > xCompChild( m_xComponent, UNO_QUERY_THROW );
293 0 : Reference< XGridColumnFactory > xCheckGrid( xCompChild->getParent(), UNO_QUERY );
294 0 : if ( !xCheckGrid.is() )
295 : {
296 0 : Reference< XMap > xControlMap;
297 0 : Any any = m_xContext->getValueByName( "ControlShapeAccess" );
298 0 : any >>= xControlMap;
299 0 : m_xAssociatedShape.set( xControlMap->get( makeAny( xControlModel ) ), UNO_QUERY_THROW );
300 0 : m_xShapeProperties.set( m_xAssociatedShape, UNO_QUERY_THROW );
301 0 : }
302 0 : }
303 : }
304 0 : catch( const Exception& )
305 : {
306 : DBG_UNHANDLED_EXCEPTION();
307 : }
308 :
309 0 : if ( m_xAssociatedShape.is() )
310 0 : m_xChangeNotifier = new ShapeGeometryChangeNotifier( *this, m_aMutex, m_xAssociatedShape.get() );
311 0 : }
312 :
313 :
314 0 : OUString SAL_CALL FormGeometryHandler::getImplementationName_static( ) throw (RuntimeException)
315 : {
316 0 : return OUString( "com.sun.star.comp.extensions.FormGeometryHandler" );
317 : }
318 :
319 :
320 0 : Sequence< OUString > SAL_CALL FormGeometryHandler::getSupportedServiceNames_static( ) throw (RuntimeException)
321 : {
322 0 : Sequence< OUString > aSupported( 1 );
323 0 : aSupported[0] = "com.sun.star.form.inspection.FormGeometryHandler";
324 0 : return aSupported;
325 : }
326 :
327 :
328 0 : Any SAL_CALL FormGeometryHandler::getPropertyValue( const OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException, std::exception)
329 : {
330 0 : ::osl::MutexGuard aGuard( m_aMutex );
331 0 : PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
332 :
333 0 : ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this );
334 0 : ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: no shape properties!", *this );
335 :
336 0 : Any aReturn;
337 : try
338 : {
339 0 : switch ( nPropId )
340 : {
341 : case PROPERTY_ID_POSITIONX:
342 0 : aReturn <<= m_xAssociatedShape->getPosition().X;
343 0 : break;
344 : case PROPERTY_ID_POSITIONY:
345 0 : aReturn <<= m_xAssociatedShape->getPosition().Y;
346 0 : break;
347 : case PROPERTY_ID_WIDTH:
348 0 : aReturn <<= m_xAssociatedShape->getSize().Width;
349 0 : break;
350 : case PROPERTY_ID_HEIGHT:
351 0 : aReturn <<= m_xAssociatedShape->getSize().Height;
352 0 : break;
353 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
354 0 : aReturn = m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR_TYPE );
355 : OSL_ENSURE( aReturn.hasValue(), "FormGeometryHandler::getPropertyValue: illegal anchor type!" );
356 0 : break;
357 : case PROPERTY_ID_SHEET_ANCHOR_TYPE:
358 : {
359 0 : Reference< XSpreadsheet > xAnchorSheet( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ), UNO_QUERY );
360 0 : aReturn <<= sal_Int32( xAnchorSheet.is() ? ANCHOR_TO_SHEET : ANCHOR_TO_CELL );
361 : }
362 0 : break;
363 :
364 : default:
365 : OSL_FAIL( "FormGeometryHandler::getPropertyValue: huh?" );
366 0 : break;
367 : }
368 : }
369 0 : catch( const Exception& )
370 : {
371 : DBG_UNHANDLED_EXCEPTION();
372 : }
373 0 : return aReturn;
374 : }
375 :
376 :
377 0 : void SAL_CALL FormGeometryHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException, std::exception)
378 : {
379 0 : ::osl::MutexGuard aGuard( m_aMutex );
380 0 : PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
381 :
382 0 : ENSURE_OR_THROW2( m_xAssociatedShape.is(), "internal error: properties, but no shape!", *this );
383 0 : ENSURE_OR_THROW2( m_xShapeProperties.is(), "internal error: properties, but no shape!", *this );
384 :
385 : try
386 : {
387 0 : switch ( nPropId )
388 : {
389 : case PROPERTY_ID_POSITIONX:
390 : case PROPERTY_ID_POSITIONY:
391 : {
392 0 : sal_Int32 nPosition(0);
393 0 : OSL_VERIFY( _rValue >>= nPosition );
394 :
395 0 : AwtPoint aPos( m_xAssociatedShape->getPosition() );
396 0 : if ( nPropId == PROPERTY_ID_POSITIONX )
397 0 : aPos.X = nPosition;
398 : else
399 0 : aPos.Y = nPosition;
400 0 : m_xAssociatedShape->setPosition( aPos );
401 : }
402 0 : break;
403 :
404 : case PROPERTY_ID_WIDTH:
405 : case PROPERTY_ID_HEIGHT:
406 : {
407 0 : sal_Int32 nSize(0);
408 0 : OSL_VERIFY( _rValue >>= nSize );
409 :
410 0 : AwtSize aSize( m_xAssociatedShape->getSize() );
411 0 : if ( nPropId == PROPERTY_ID_WIDTH )
412 0 : aSize.Width = nSize;
413 : else
414 0 : aSize.Height = nSize;
415 0 : m_xAssociatedShape->setSize( aSize );
416 : }
417 0 : break;
418 :
419 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
420 0 : m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR_TYPE, _rValue );
421 0 : break;
422 :
423 : case PROPERTY_ID_SHEET_ANCHOR_TYPE:
424 : {
425 0 : sal_Int32 nSheetAnchorType = 0;
426 0 : OSL_VERIFY( _rValue >>= nSheetAnchorType );
427 0 : impl_setSheetAnchorType_nothrow( nSheetAnchorType );
428 : }
429 0 : break;
430 :
431 : default:
432 : OSL_FAIL( "FormGeometryHandler::getPropertyValue: huh?" );
433 0 : break;
434 : }
435 : }
436 0 : catch( const Exception& )
437 : {
438 : DBG_UNHANDLED_EXCEPTION();
439 0 : }
440 0 : }
441 :
442 :
443 0 : LineDescriptor SAL_CALL FormGeometryHandler::describePropertyLine( const OUString& _rPropertyName,
444 : const Reference< XPropertyControlFactory >& _rxControlFactory )
445 : throw (UnknownPropertyException, NullPointerException, RuntimeException, std::exception)
446 : {
447 0 : ::osl::MutexGuard aGuard( m_aMutex );
448 0 : PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
449 :
450 0 : LineDescriptor aLineDesc( PropertyHandler::describePropertyLine( _rPropertyName, _rxControlFactory ) );
451 : try
452 : {
453 0 : bool bIsSize = false;
454 0 : switch ( nPropId )
455 : {
456 : case PROPERTY_ID_WIDTH:
457 : case PROPERTY_ID_HEIGHT:
458 0 : bIsSize = true;
459 : // NO break!
460 : case PROPERTY_ID_POSITIONX:
461 : case PROPERTY_ID_POSITIONY:
462 : {
463 0 : Optional< double > aZero( sal_True, 0 );
464 0 : Optional< double > aValueNotPresent( sal_False, 0 );
465 0 : aLineDesc.Control = PropertyHandlerHelper::createNumericControl(
466 0 : _rxControlFactory, 2, bIsSize ? aZero : aValueNotPresent, aValueNotPresent, sal_False );
467 :
468 0 : Reference< XNumericControl > xNumericControl( aLineDesc.Control, UNO_QUERY_THROW );
469 0 : xNumericControl->setValueUnit( MeasureUnit::MM_100TH );
470 0 : xNumericControl->setDisplayUnit( impl_getDocumentMeasurementUnit_throw() );
471 : }
472 0 : break;
473 :
474 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
475 : case PROPERTY_ID_SHEET_ANCHOR_TYPE:
476 : // default handling from PropertyHandler is sufficient
477 0 : break;
478 :
479 : default:
480 : OSL_FAIL( "FormGeometryHandler::describePropertyLine: huh?" );
481 0 : break;
482 : }
483 : }
484 0 : catch( const Exception& )
485 : {
486 : DBG_UNHANDLED_EXCEPTION();
487 : }
488 0 : return aLineDesc;
489 : }
490 :
491 :
492 0 : void SAL_CALL FormGeometryHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException, std::exception)
493 : {
494 0 : ::osl::MutexGuard aGuard( m_aMutex );
495 : OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::addPropertyChangeListener: no notified, implies no shape!?" );
496 0 : if ( m_xChangeNotifier.is() )
497 0 : m_xChangeNotifier->addPropertyChangeListener( _listener );
498 0 : }
499 :
500 :
501 0 : void SAL_CALL FormGeometryHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _listener ) throw (RuntimeException, std::exception)
502 : {
503 0 : ::osl::MutexGuard aGuard( m_aMutex );
504 : OSL_PRECOND( m_xChangeNotifier.is(), "FormGeometryHandler::removePropertyChangeListener: no notified, implies no shape!?" );
505 0 : if ( m_xChangeNotifier.is() )
506 0 : m_xChangeNotifier->removePropertyChangeListener( _listener );
507 0 : }
508 :
509 :
510 0 : Sequence< OUString > SAL_CALL FormGeometryHandler::getActuatingProperties( ) throw (RuntimeException, std::exception)
511 : {
512 0 : Sequence< OUString > aInterestedIn(1);
513 0 : aInterestedIn[0] = PROPERTY_TEXT_ANCHOR_TYPE;
514 0 : return aInterestedIn;
515 : }
516 :
517 :
518 0 : void SAL_CALL FormGeometryHandler::actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException, std::exception)
519 : {
520 0 : if ( !_rxInspectorUI.is() )
521 0 : throw NullPointerException();
522 :
523 0 : ::osl::MutexGuard aGuard( m_aMutex );
524 0 : PropertyId nActuatingPropId( impl_getPropertyId_nothrow( _rActuatingPropertyName ) );
525 :
526 0 : switch ( nActuatingPropId )
527 : {
528 : case PROPERTY_ID_TEXT_ANCHOR_TYPE:
529 : {
530 0 : TextContentAnchorType eAnchorType( TextContentAnchorType_AT_PARAGRAPH );
531 0 : OSL_VERIFY( _rNewValue >>= eAnchorType );
532 0 : _rxInspectorUI->enablePropertyUI( PROPERTY_POSITIONX, eAnchorType != TextContentAnchorType_AS_CHARACTER );
533 : }
534 0 : break;
535 : case -1:
536 0 : throw RuntimeException();
537 : break;
538 : default:
539 : OSL_FAIL( "FormGeometryHandler::actuatingPropertyChanged: not registered for this property!" );
540 0 : break;
541 0 : }
542 0 : }
543 :
544 :
545 0 : Sequence< Property > SAL_CALL FormGeometryHandler::doDescribeSupportedProperties() const
546 : {
547 0 : if ( !m_xAssociatedShape.is() )
548 0 : return Sequence< Property >();
549 :
550 0 : ::std::vector< Property > aProperties;
551 :
552 0 : addInt32PropertyDescription( aProperties, PROPERTY_POSITIONX );
553 0 : addInt32PropertyDescription( aProperties, PROPERTY_POSITIONY );
554 0 : addInt32PropertyDescription( aProperties, PROPERTY_WIDTH );
555 0 : addInt32PropertyDescription( aProperties, PROPERTY_HEIGHT );
556 :
557 0 : if ( impl_haveTextAnchorType_nothrow() )
558 0 : implAddPropertyDescription( aProperties, PROPERTY_TEXT_ANCHOR_TYPE, ::cppu::UnoType< TextContentAnchorType >::get() );
559 :
560 0 : if ( impl_haveSheetAnchorType_nothrow() )
561 0 : addInt32PropertyDescription( aProperties, PROPERTY_SHEET_ANCHOR_TYPE );
562 :
563 0 : return Sequence< Property >( &(*aProperties.begin()), aProperties.size() );
564 : }
565 :
566 :
567 0 : void SAL_CALL FormGeometryHandler::disposing()
568 : {
569 0 : FormGeometryHandler_Base::disposing();
570 :
571 0 : if ( m_xChangeNotifier.is() )
572 : {
573 0 : m_xChangeNotifier->dispose();
574 0 : m_xChangeNotifier.clear();
575 : }
576 0 : }
577 :
578 :
579 0 : bool FormGeometryHandler::impl_haveTextAnchorType_nothrow() const
580 : {
581 0 : ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" );
582 : try
583 : {
584 0 : Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
585 0 : if ( xPSI->hasPropertyByName( PROPERTY_ANCHOR_TYPE ) )
586 0 : return true;
587 : }
588 0 : catch( const Exception& )
589 : {
590 : DBG_UNHANDLED_EXCEPTION();
591 : }
592 0 : return false;
593 : }
594 :
595 :
596 0 : bool FormGeometryHandler::impl_haveSheetAnchorType_nothrow() const
597 : {
598 0 : ENSURE_OR_THROW( m_xShapeProperties.is(), "not to be called without shape properties" );
599 : try
600 : {
601 0 : Reference< XPropertySetInfo > xPSI( m_xShapeProperties->getPropertySetInfo(), UNO_SET_THROW );
602 0 : if ( !xPSI->hasPropertyByName( PROPERTY_ANCHOR ) )
603 0 : return false;
604 0 : Reference< XServiceInfo > xSI( m_xAssociatedShape, UNO_QUERY_THROW );
605 0 : if ( xSI->supportsService("com.sun.star.sheet.Shape") )
606 0 : return true;
607 : }
608 0 : catch( const Exception& )
609 : {
610 : DBG_UNHANDLED_EXCEPTION();
611 : }
612 0 : return false;
613 : }
614 :
615 :
616 : namespace
617 : {
618 0 : static sal_Int32 lcl_getLowerBoundRowOrColumn( const Reference< XIndexAccess >& _rxRowsOrColumns, const bool _bRows,
619 : const AwtPoint& _rRelativePosition )
620 : {
621 0 : sal_Int32 nAccumulated = 0;
622 :
623 0 : const sal_Int32& rRelativePos = _bRows ? _rRelativePosition.Y : _rRelativePosition.X;
624 :
625 0 : sal_Int32 nElements = _rxRowsOrColumns->getCount();
626 0 : sal_Int32 currentPos = 0;
627 0 : for ( currentPos=0; currentPos<nElements; ++currentPos )
628 : {
629 0 : Reference< XPropertySet > xRowOrColumn( _rxRowsOrColumns->getByIndex( currentPos ), UNO_QUERY_THROW );
630 :
631 0 : sal_Bool bIsVisible = sal_True;
632 0 : OSL_VERIFY( xRowOrColumn->getPropertyValue( PROPERTY_IS_VISIBLE ) >>= bIsVisible );
633 0 : if ( !bIsVisible )
634 0 : continue;
635 :
636 0 : sal_Int32 nHeightOrWidth( 0 );
637 0 : OSL_VERIFY( xRowOrColumn->getPropertyValue( _bRows ? OUString(PROPERTY_HEIGHT) : OUString(PROPERTY_WIDTH) ) >>= nHeightOrWidth );
638 :
639 0 : if ( nAccumulated + nHeightOrWidth > rRelativePos )
640 0 : break;
641 :
642 0 : nAccumulated += nHeightOrWidth;
643 0 : }
644 :
645 0 : return currentPos;
646 : }
647 : }
648 :
649 :
650 0 : void FormGeometryHandler::impl_setSheetAnchorType_nothrow( const sal_Int32 _nAnchorType ) const
651 : {
652 0 : ENSURE_OR_THROW( m_xShapeProperties.is(), "illegal to be called without shape properties." );
653 : try
654 : {
655 0 : CellBindingHelper aHelper( m_xComponent, impl_getContextDocument_nothrow() );
656 : // find the sheet which the control belongs to
657 0 : Reference< XSpreadsheet > xSheet;
658 0 : aHelper.getControlSheetIndex( xSheet );
659 :
660 0 : switch ( _nAnchorType )
661 : {
662 : case ANCHOR_TO_SHEET:
663 : OSL_ENSURE( xSheet.is(),
664 : "FormGeometryHandler::impl_setSheetAnchorType_nothrow: sheet not found!" );
665 0 : if ( xSheet.is() )
666 : {
667 0 : AwtPoint aPreservePosition( m_xAssociatedShape->getPosition() );
668 0 : m_xShapeProperties->setPropertyValue( PROPERTY_ANCHOR, makeAny( xSheet ) );
669 0 : m_xAssociatedShape->setPosition( aPreservePosition );
670 : }
671 0 : break;
672 :
673 : case ANCHOR_TO_CELL:
674 : {
675 0 : Reference< XColumnRowRange > xColsRows( xSheet, UNO_QUERY_THROW );
676 :
677 : // get the current anchor
678 0 : Reference< XSpreadsheet > xCurrentAnchor;
679 0 : OSL_VERIFY( m_xShapeProperties->getPropertyValue( PROPERTY_ANCHOR ) >>= xCurrentAnchor );
680 : OSL_ENSURE( xCurrentAnchor.is(), "FormGeometryHandler::impl_setSheetAnchorType_nothrow: only to be called when currently anchored to a sheet!" );
681 :
682 : // get the current position
683 0 : AwtPoint aRelativePosition( m_xAssociatedShape->getPosition() );
684 :
685 0 : Reference< XTableColumns > xCols( xColsRows->getColumns(), UNO_SET_THROW );
686 0 : sal_Int32 nNewAnchorCol = lcl_getLowerBoundRowOrColumn( xCols.get(), false, aRelativePosition );
687 :
688 0 : Reference< XTableRows > xRows( xColsRows->getRows(), UNO_SET_THROW );
689 0 : sal_Int32 nNewAnchorRow = lcl_getLowerBoundRowOrColumn( xRows.get(), true, aRelativePosition );
690 :
691 0 : Any aNewAnchorCell( xSheet->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 : OUString sPropertyName;
715 : Any aNewPropertyValue;
716 :
717 0 : EventTranslation( const 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, std::exception)
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, std::exception)
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( 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( 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: */
|