nss: upgrade to release 3.73
[LibreOffice.git] / sc / source / ui / vba / vbasheetobjects.cxx
blobe0082be6b5a679f78f364128a96775bcc8358f27
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "vbasheetobjects.hxx"
21 #include <vector>
22 #include <rtl/math.hxx>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/container/XIndexContainer.hpp>
25 #include <com/sun/star/container/XNamed.hpp>
26 #include <com/sun/star/drawing/XControlShape.hpp>
27 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
28 #include <com/sun/star/drawing/XShapes.hpp>
29 #include <com/sun/star/form/FormComponentType.hpp>
30 #include <com/sun/star/form/XForm.hpp>
31 #include <com/sun/star/form/XFormComponent.hpp>
32 #include <com/sun/star/form/XFormsSupplier.hpp>
33 #include <com/sun/star/frame/XModel.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/sheet/XSpreadsheet.hpp>
36 #include "vbasheetobject.hxx"
37 #include <cppuhelper/implbase.hxx>
39 using namespace ::com::sun::star;
40 using namespace ::ooo::vba;
42 namespace {
44 template< typename Type >
45 bool lclGetProperty( Type& orValue, const uno::Reference< beans::XPropertySet >& rxPropSet, const OUString& rPropName )
47 try
49 return rxPropSet->getPropertyValue( rPropName ) >>= orValue;
51 catch( uno::Exception& )
54 return false;
57 /** Rounds the passed value to a multiple of 0.75 and converts it to 1/100 mm.
59 @throws uno::RuntimeException
61 double lclPointsToHmm( const uno::Any& rPoints )
63 return PointsToHmm( ::rtl::math::approxFloor( rPoints.get< double >() / 0.75 ) * 0.75 );
66 } // namespace
68 // Base implementations
70 /** Container for a specific type of drawing object in a spreadsheet.
72 Derived classes provide all required functionality specific to the type of
73 shapes covered by the container.
75 class ScVbaObjectContainer : public ::cppu::WeakImplHelper< container::XIndexAccess >
77 public:
78 /// @throws uno::RuntimeException
79 explicit ScVbaObjectContainer(
80 const uno::Reference< XHelperInterface >& rxParent,
81 const uno::Reference< uno::XComponentContext >& rxContext,
82 const uno::Reference< frame::XModel >& rxModel,
83 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
84 const uno::Type& rVbaType );
86 /** Returns the VBA helper interface of the VBA collection object. */
87 const uno::Reference< XHelperInterface >& getParent() const { return mxParent; }
88 /** Returns the component context of the VBA collection object. */
89 const uno::Reference< uno::XComponentContext >& getContext() const { return mxContext; }
90 /** Returns the VBA type information of the objects in this container. */
91 const uno::Type& getVbaType() const { return maVbaType; }
93 /** Collects all shapes supported by this instance and inserts them into
94 the internal shape vector.
96 @throws uno::RuntimeException
98 void collectShapes();
99 /** Creates and returns a new UNO shape.
101 @throws uno::RuntimeException
103 uno::Reference< drawing::XShape > createShape( const awt::Point& rPos, const awt::Size& rSize );
104 /** Inserts the passed shape into the draw page and into this container, and returns its index in the draw page.
106 @throws uno::RuntimeException
108 sal_Int32 insertShape( const uno::Reference< drawing::XShape >& rxShape );
109 /** Creates and returns a new VBA implementation object for the passed shape.
111 @throws uno::RuntimeException
113 ::rtl::Reference< ScVbaSheetObjectBase > createVbaObject( const uno::Reference< drawing::XShape >& rxShape );
114 /** Creates and returns a new VBA implementation object for the passed shape in an Any.
116 @throws uno::RuntimeException
118 uno::Any createCollectionObject( const uno::Any& rSource );
119 /** Returns the VBA implementation object with the specified name.
121 @throws uno::RuntimeException
123 uno::Any getItemByStringIndex( const OUString& rIndex );
125 // XIndexAccess
126 virtual sal_Int32 SAL_CALL getCount() override;
127 virtual uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) override;
129 // XElementAccess
130 virtual uno::Type SAL_CALL getElementType() override;
131 virtual sal_Bool SAL_CALL hasElements() override;
133 protected:
134 /** Derived classes return true, if the passed shape is supported by the instance. */
135 virtual bool implPickShape( const uno::Reference< drawing::XShape >& rxShape ) const = 0;
136 /** Derived classes create and return a new VBA implementation object for the passed shape.
138 @throws uno::RuntimeException
140 virtual ScVbaSheetObjectBase* implCreateVbaObject( const uno::Reference< drawing::XShape >& rxShape ) = 0;
141 /** Derived classes return the service name of the UNO shape. */
142 virtual OUString implGetShapeServiceName() const = 0;
144 /** Returns the shape name via 'Name' property of the UNO shape. May be overwritten.
146 @throws uno::RuntimeException
148 virtual OUString implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const;
149 /** Is called when a new UNO shape has been created but not yet inserted into the drawing page.
151 @throws uno::RuntimeException
153 virtual void implOnShapeCreated( const uno::Reference< drawing::XShape >& rxShape );
155 protected:
156 uno::Reference< XHelperInterface > mxParent;
157 uno::Reference< uno::XComponentContext > mxContext;
158 uno::Reference< frame::XModel > mxModel;
159 uno::Reference< lang::XMultiServiceFactory > mxFactory;
160 uno::Reference< drawing::XShapes > mxShapes;
162 private:
163 typedef ::std::vector< uno::Reference< drawing::XShape > > ShapeVector;
164 const uno::Type maVbaType;
165 ShapeVector maShapes;
168 ScVbaObjectContainer::ScVbaObjectContainer(
169 const uno::Reference< XHelperInterface >& rxParent,
170 const uno::Reference< uno::XComponentContext >& rxContext,
171 const uno::Reference< frame::XModel >& rxModel,
172 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
173 const uno::Type& rVbaType ) :
174 mxParent( rxParent ),
175 mxContext( rxContext ),
176 mxModel( rxModel, uno::UNO_SET_THROW ),
177 mxFactory( rxModel, uno::UNO_QUERY_THROW ),
178 maVbaType( rVbaType )
180 uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupp( rxSheet, uno::UNO_QUERY_THROW );
181 mxShapes.set( xDrawPageSupp->getDrawPage(), uno::UNO_QUERY_THROW );
184 void ScVbaObjectContainer::collectShapes()
186 maShapes.clear();
187 for( sal_Int32 nIndex = 0, nCount = mxShapes->getCount(); nIndex < nCount; ++nIndex )
189 uno::Reference< drawing::XShape > xShape( mxShapes->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
190 if( implPickShape( xShape ) )
191 maShapes.push_back( xShape );
195 uno::Reference< drawing::XShape > ScVbaObjectContainer::createShape( const awt::Point& rPos, const awt::Size& rSize )
197 uno::Reference< drawing::XShape > xShape( mxFactory->createInstance( implGetShapeServiceName() ), uno::UNO_QUERY_THROW );
198 xShape->setPosition( rPos );
199 xShape->setSize( rSize );
200 implOnShapeCreated( xShape );
201 return xShape;
204 sal_Int32 ScVbaObjectContainer::insertShape( const uno::Reference< drawing::XShape >& rxShape )
206 mxShapes->add( rxShape );
207 maShapes.push_back( rxShape );
208 return mxShapes->getCount() - 1;
211 ::rtl::Reference< ScVbaSheetObjectBase > ScVbaObjectContainer::createVbaObject(
212 const uno::Reference< drawing::XShape >& rxShape )
214 return implCreateVbaObject( rxShape );
217 uno::Any ScVbaObjectContainer::createCollectionObject( const uno::Any& rSource )
219 uno::Reference< drawing::XShape > xShape( rSource, uno::UNO_QUERY_THROW );
220 uno::Reference< excel::XSheetObject > xSheetObject( implCreateVbaObject( xShape ) );
221 return uno::Any( xSheetObject );
224 uno::Any ScVbaObjectContainer::getItemByStringIndex( const OUString& rIndex )
226 auto aIt = std::find_if(maShapes.begin(), maShapes.end(),
227 [&rIndex, this](const ShapeVector::value_type& rxShape) { return rIndex == implGetShapeName( rxShape ); });
228 if (aIt != maShapes.end())
229 return createCollectionObject( uno::Any( *aIt ) );
230 throw uno::RuntimeException();
233 // XIndexAccess
235 sal_Int32 SAL_CALL ScVbaObjectContainer::getCount()
237 return static_cast< sal_Int32 >( maShapes.size() );
240 uno::Any SAL_CALL ScVbaObjectContainer::getByIndex( sal_Int32 nIndex )
242 if( (0 <= nIndex) && (nIndex < getCount()) )
243 return uno::Any( maShapes[ static_cast< size_t >( nIndex ) ] );
244 throw lang::IndexOutOfBoundsException();
247 // XElementAccess
249 uno::Type SAL_CALL ScVbaObjectContainer::getElementType()
251 return cppu::UnoType<drawing::XShape>::get();
254 sal_Bool SAL_CALL ScVbaObjectContainer::hasElements()
256 return !maShapes.empty();
259 // private
261 OUString ScVbaObjectContainer::implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const
263 uno::Reference< beans::XPropertySet > xPropSet( rxShape, uno::UNO_QUERY_THROW );
264 return xPropSet->getPropertyValue( "Name" ).get< OUString >();
267 void ScVbaObjectContainer::implOnShapeCreated( const uno::Reference< drawing::XShape >& /*rxShape*/ )
271 namespace {
273 class ScVbaObjectEnumeration : public SimpleEnumerationBase
275 public:
276 explicit ScVbaObjectEnumeration( const ScVbaObjectContainerRef& rxContainer );
277 virtual uno::Any createCollectionObject( const uno::Any& rSource ) override;
279 private:
280 ScVbaObjectContainerRef mxContainer;
285 ScVbaObjectEnumeration::ScVbaObjectEnumeration( const ScVbaObjectContainerRef& rxContainer ) :
286 SimpleEnumerationBase( rxContainer.get() ),
287 mxContainer( rxContainer )
291 uno::Any ScVbaObjectEnumeration::createCollectionObject( const uno::Any& rSource )
293 return mxContainer->createCollectionObject( rSource );
296 ScVbaSheetObjectsBase::ScVbaSheetObjectsBase( const ScVbaObjectContainerRef& rxContainer ) :
297 ScVbaSheetObjects_BASE( rxContainer->getParent(), rxContainer->getContext(), rxContainer.get() ),
298 mxContainer( rxContainer )
300 mxContainer->collectShapes();
303 ScVbaSheetObjectsBase::~ScVbaSheetObjectsBase()
307 void ScVbaSheetObjectsBase::collectShapes()
309 mxContainer->collectShapes();
312 // XEnumerationAccess
314 uno::Reference< container::XEnumeration > SAL_CALL ScVbaSheetObjectsBase::createEnumeration()
316 return new ScVbaObjectEnumeration( mxContainer );
319 // XElementAccess
321 uno::Type SAL_CALL ScVbaSheetObjectsBase::getElementType()
323 return mxContainer->getVbaType();
326 // ScVbaCollectionBase
328 uno::Any ScVbaSheetObjectsBase::createCollectionObject( const uno::Any& rSource )
330 return mxContainer->createCollectionObject( rSource );
333 uno::Any ScVbaSheetObjectsBase::getItemByStringIndex( const OUString& rIndex )
335 return mxContainer->getItemByStringIndex( rIndex );
338 // Graphic object containers supporting ooo.vba.excel.XGraphicObject
340 ScVbaGraphicObjectsBase::ScVbaGraphicObjectsBase( const ScVbaObjectContainerRef& rxContainer ) :
341 ScVbaGraphicObjects_BASE( rxContainer )
345 // XGraphicObjects
347 uno::Any SAL_CALL ScVbaGraphicObjectsBase::Add( const uno::Any& rLeft, const uno::Any& rTop, const uno::Any& rWidth, const uno::Any& rHeight )
349 /* Extract double values from passed Anys (the lclPointsToHmm() helper
350 function will throw a RuntimeException on any error), and convert from
351 points to 1/100 mm. */
352 awt::Point aPos( static_cast<sal_Int32>(lclPointsToHmm( rLeft )), static_cast<sal_Int32>(lclPointsToHmm( rTop )) );
353 awt::Size aSize( static_cast<sal_Int32>(lclPointsToHmm( rWidth )), static_cast<sal_Int32>(lclPointsToHmm( rHeight )) );
354 // TODO: translate coordinates for RTL sheets
355 if( (aPos.X < 0) || (aPos.Y < 0) || (aSize.Width <= 0) || (aSize.Height <= 0) )
356 throw uno::RuntimeException();
358 // create the UNO shape
359 uno::Reference< drawing::XShape > xShape( mxContainer->createShape( aPos, aSize ), uno::UNO_SET_THROW );
360 sal_Int32 nIndex = mxContainer->insertShape( xShape );
362 // create and return the VBA object
363 ::rtl::Reference< ScVbaSheetObjectBase > xVbaObject = mxContainer->createVbaObject( xShape );
364 xVbaObject->setDefaultProperties( nIndex );
365 return uno::Any( uno::Reference< excel::XSheetObject >( xVbaObject.get() ) );
368 // Drawing controls
370 namespace {
372 class ScVbaControlContainer : public ScVbaObjectContainer
374 public:
375 /// @throws uno::RuntimeException
376 explicit ScVbaControlContainer(
377 const uno::Reference< XHelperInterface >& rxParent,
378 const uno::Reference< uno::XComponentContext >& rxContext,
379 const uno::Reference< frame::XModel >& rxModel,
380 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
381 const uno::Type& rVbaType,
382 const OUString& rModelServiceName,
383 sal_Int16 /* css::form::FormComponentType */ eType );
385 protected:
386 /// @throws uno::RuntimeException
387 uno::Reference< container::XIndexContainer > const & createForm();
389 virtual bool implPickShape( const uno::Reference< drawing::XShape >& rxShape ) const override;
390 virtual OUString implGetShapeServiceName() const override;
391 virtual bool implCheckProperties( const uno::Reference< beans::XPropertySet >& rxModelProps ) const;
392 virtual OUString implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const override;
393 virtual void implOnShapeCreated( const uno::Reference< drawing::XShape >& rxShape ) override;
395 protected:
396 uno::Reference< container::XIndexContainer > mxFormIC;
397 OUString maModelServiceName;
398 sal_Int16 /* css::form::FormComponentType */ meType;
403 ScVbaControlContainer::ScVbaControlContainer(
404 const uno::Reference< XHelperInterface >& rxParent,
405 const uno::Reference< uno::XComponentContext >& rxContext,
406 const uno::Reference< frame::XModel >& rxModel,
407 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
408 const uno::Type& rVbaType,
409 const OUString& rModelServiceName,
410 sal_Int16 /* css::form::FormComponentType */ eType ) :
411 ScVbaObjectContainer( rxParent, rxContext, rxModel, rxSheet, rVbaType ),
412 maModelServiceName( rModelServiceName ),
413 meType( eType )
417 uno::Reference< container::XIndexContainer > const & ScVbaControlContainer::createForm()
419 if( !mxFormIC.is() )
421 uno::Reference< form::XFormsSupplier > xFormsSupp( mxShapes, uno::UNO_QUERY_THROW );
422 uno::Reference< container::XNameContainer > xFormsNC( xFormsSupp->getForms(), uno::UNO_SET_THROW );
423 OUString aFormName = "Standard";
424 if( xFormsNC->hasByName( aFormName ) )
426 mxFormIC.set( xFormsNC->getByName( aFormName ), uno::UNO_QUERY_THROW );
428 else
430 uno::Reference< form::XForm > xForm( mxFactory->createInstance( "com.sun.star.form.component.Form" ), uno::UNO_QUERY_THROW );
431 xFormsNC->insertByName( aFormName, uno::Any( xForm ) );
432 mxFormIC.set( xForm, uno::UNO_QUERY_THROW );
435 return mxFormIC;
438 bool ScVbaControlContainer::implPickShape( const uno::Reference< drawing::XShape >& rxShape ) const
442 uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW );
443 uno::Reference< beans::XPropertySet > xModelProps( xControlShape->getControl(), uno::UNO_QUERY_THROW );
444 sal_Int16 nClassId = -1;
445 return lclGetProperty( nClassId, xModelProps, "ClassId" ) &&
446 (nClassId == meType) && implCheckProperties( xModelProps );
448 catch( uno::Exception& )
451 return false;
454 OUString ScVbaControlContainer::implGetShapeServiceName() const
456 return "com.sun.star.drawing.ControlShape";
459 bool ScVbaControlContainer::implCheckProperties( const uno::Reference< beans::XPropertySet >& /*rxModelProps*/ ) const
461 return true;
464 OUString ScVbaControlContainer::implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const
466 uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW );
467 return uno::Reference< container::XNamed >( xControlShape->getControl(), uno::UNO_QUERY_THROW )->getName();
470 void ScVbaControlContainer::implOnShapeCreated( const uno::Reference< drawing::XShape >& rxShape )
472 // passed shape must be a control shape
473 uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW );
475 // create the UNO control model
476 uno::Reference< form::XFormComponent > xFormComponent( mxFactory->createInstance( maModelServiceName ), uno::UNO_QUERY_THROW );
477 uno::Reference< awt::XControlModel > xControlModel( xFormComponent, uno::UNO_QUERY_THROW );
479 // insert the control model into the form and the shape
480 createForm();
481 mxFormIC->insertByIndex( mxFormIC->getCount(), uno::Any( xFormComponent ) );
482 xControlShape->setControl( xControlModel );
485 // Push button
487 namespace {
489 class ScVbaButtonContainer : public ScVbaControlContainer
491 bool mbOptionButtons;
492 public:
493 /// @throws uno::RuntimeException
494 explicit ScVbaButtonContainer(
495 const uno::Reference< XHelperInterface >& rxParent,
496 const uno::Reference< uno::XComponentContext >& rxContext,
497 const uno::Reference< frame::XModel >& rxModel,
498 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
499 bool bOptionButtons);
501 protected:
502 virtual ScVbaSheetObjectBase* implCreateVbaObject( const uno::Reference< drawing::XShape >& rxShape ) override;
503 virtual bool implCheckProperties( const uno::Reference< beans::XPropertySet >& rxModelProps ) const override;
508 ScVbaButtonContainer::ScVbaButtonContainer(
509 const uno::Reference< XHelperInterface >& rxParent,
510 const uno::Reference< uno::XComponentContext >& rxContext,
511 const uno::Reference< frame::XModel >& rxModel,
512 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
513 bool bOptionButtons ) :
514 ScVbaControlContainer(
515 rxParent, rxContext, rxModel, rxSheet,
516 cppu::UnoType<excel::XButton>::get(),
517 ( bOptionButtons ?
518 OUString( "com.sun.star.form.component.RadioButton" ) :
519 OUString( "com.sun.star.form.component.CommandButton" ) ),
520 ( bOptionButtons ?
521 form::FormComponentType::RADIOBUTTON :
522 form::FormComponentType::COMMANDBUTTON) ),
523 mbOptionButtons(bOptionButtons)
527 ScVbaSheetObjectBase* ScVbaButtonContainer::implCreateVbaObject( const uno::Reference< drawing::XShape >& rxShape )
529 uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW );
530 return new ScVbaButton( mxParent, mxContext, mxModel, createForm(), xControlShape );
533 bool ScVbaButtonContainer::implCheckProperties( const uno::Reference< beans::XPropertySet >& rxModelProps ) const
535 if (mbOptionButtons)
536 return true;
538 // do not insert toggle buttons into the 'Buttons' collection
539 bool bToggle = false;
540 return lclGetProperty( bToggle, rxModelProps, "Toggle" ) && !bToggle;
543 ScVbaButtons::ScVbaButtons(
544 const uno::Reference< XHelperInterface >& rxParent,
545 const uno::Reference< uno::XComponentContext >& rxContext,
546 const uno::Reference< frame::XModel >& rxModel,
547 const uno::Reference< sheet::XSpreadsheet >& rxSheet,
548 bool bOptionButtons) :
549 ScVbaGraphicObjectsBase( new ScVbaButtonContainer( rxParent, rxContext, rxModel, rxSheet, bOptionButtons ) )
553 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButtons, "ooo.vba.excel.Buttons" )
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */