1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "vbasheetobject.hxx"
21 #include <com/sun/star/awt/TextAlign.hpp>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/container/XIndexContainer.hpp>
24 #include <com/sun/star/drawing/XControlShape.hpp>
25 #include <com/sun/star/frame/XModel.hpp>
26 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
27 #include <com/sun/star/script/XEventAttacherManager.hpp>
28 #include <com/sun/star/style/VerticalAlignment.hpp>
29 #include <comphelper/documentinfo.hxx>
30 #include <o3tl/unit_conversion.hxx>
31 #include <ooo/vba/excel/Constants.hpp>
32 #include <ooo/vba/excel/XlOrientation.hpp>
33 #include <ooo/vba/excel/XlPlacement.hpp>
34 #include <filter/msfilter/msvbahelper.hxx>
35 #include "vbafont.hxx"
37 using namespace ::com::sun::star
;
38 using namespace ::ooo::vba
;
40 constexpr OUString gaListenerType
= u
"XActionListener"_ustr
;
41 constexpr OUString gaEventMethod
= u
"actionPerformed"_ustr
;
43 static double HmmToPoints(double nHmm
)
45 return o3tl::convert(nHmm
, o3tl::Length::mm100
, o3tl::Length::pt
);
48 static sal_Int32
PointsToHmm(double fPoints
)
50 return std::round(o3tl::convert(fPoints
, o3tl::Length::pt
, o3tl::Length::mm100
));
53 ScVbaButtonCharacters::ScVbaButtonCharacters(
54 const uno::Reference
< XHelperInterface
>& rxParent
,
55 const uno::Reference
< uno::XComponentContext
>& rxContext
,
56 const uno::Reference
< beans::XPropertySet
>& rxPropSet
,
57 const ScVbaPalette
& rPalette
,
58 const uno::Any
& rStart
,
59 const uno::Any
& rLength
) :
60 ScVbaButtonCharacters_BASE( rxParent
, rxContext
),
61 maPalette( rPalette
),
62 mxPropSet( rxPropSet
, uno::UNO_SET_THROW
)
64 // extract optional start parameter (missing or invalid -> from beginning)
65 if( !(rStart
>>= mnStart
) || (mnStart
< 1) )
67 --mnStart
; // VBA is 1-based, rtl string is 0-based
69 // extract optional length parameter (missing or invalid -> to end)
70 if( !(rLength
>>= mnLength
) || (mnLength
< 1) )
71 mnLength
= SAL_MAX_INT32
;
74 ScVbaButtonCharacters::~ScVbaButtonCharacters()
78 // XCharacters attributes
80 OUString SAL_CALL
ScVbaButtonCharacters::getCaption()
82 // ignore invalid mnStart and/or mnLength members
83 OUString aString
= getFullString();
84 sal_Int32 nStart
= ::std::min( mnStart
, aString
.getLength() );
85 sal_Int32 nLength
= ::std::min( mnLength
, aString
.getLength() - nStart
);
86 return aString
.copy( nStart
, nLength
);
89 void SAL_CALL
ScVbaButtonCharacters::setCaption( const OUString
& rCaption
)
91 /* Replace the covered text with the passed text, ignore invalid mnStart
92 and/or mnLength members. This operation does not affect the mnLength
93 parameter. If the inserted text is longer than mnLength, the additional
94 characters are not covered by this object. If the inserted text is
95 shorter than mnLength, other uncovered characters from the original
96 string will be covered now, thus may be changed with subsequent
98 OUString aString
= getFullString();
99 sal_Int32 nStart
= ::std::min( mnStart
, aString
.getLength() );
100 sal_Int32 nLength
= ::std::min( mnLength
, aString
.getLength() - nStart
);
101 setFullString( aString
.replaceAt( nStart
, nLength
, rCaption
) );
104 sal_Int32 SAL_CALL
ScVbaButtonCharacters::getCount()
106 // always return the total length of the caption
107 return getFullString().getLength();
110 OUString SAL_CALL
ScVbaButtonCharacters::getText()
112 // Text attribute same as Caption attribute?
116 void SAL_CALL
ScVbaButtonCharacters::setText( const OUString
& rText
)
118 // Text attribute same as Caption attribute?
122 uno::Reference
< excel::XFont
> SAL_CALL
ScVbaButtonCharacters::getFont()
124 return new ScVbaFont( this, mxContext
, maPalette
, mxPropSet
, nullptr, true );
127 void SAL_CALL
ScVbaButtonCharacters::setFont( const uno::Reference
< excel::XFont
>& /*rxFont*/ )
132 // XCharacters methods
134 void SAL_CALL
ScVbaButtonCharacters::Insert( const OUString
& rString
)
136 /* The Insert() operation is in fact "replace covered characters", at
137 least for buttons... It seems there is no easy way to really insert a
138 substring. This operation does not affect the mnLength parameter. */
139 setCaption( rString
);
142 void SAL_CALL
ScVbaButtonCharacters::Delete()
144 /* The Delete() operation is nothing else than "replace with empty string".
145 This does not affect the mnLength parameter, multiple calls of Delete()
146 will remove characters as long as there are some more covered by this
148 setCaption( OUString() );
153 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButtonCharacters
, u
"ooo.vba.excel.Characters"_ustr
)
157 OUString
ScVbaButtonCharacters::getFullString() const
159 return mxPropSet
->getPropertyValue( u
"Label"_ustr
).get
< OUString
>();
162 void ScVbaButtonCharacters::setFullString( const OUString
& rString
)
164 mxPropSet
->setPropertyValue( u
"Label"_ustr
, uno::Any( rString
) );
167 ScVbaSheetObjectBase::ScVbaSheetObjectBase(
168 const uno::Reference
< XHelperInterface
>& rxParent
,
169 const uno::Reference
< uno::XComponentContext
>& rxContext
,
170 const uno::Reference
< frame::XModel
>& rxModel
,
171 const uno::Reference
< drawing::XShape
>& rxShape
) :
172 ScVbaSheetObject_BASE( rxParent
, rxContext
),
173 maPalette( rxModel
),
174 mxModel( rxModel
, uno::UNO_SET_THROW
),
175 mxShape( rxShape
, uno::UNO_SET_THROW
),
176 mxShapeProps( rxShape
, uno::UNO_QUERY_THROW
)
180 // XSheetObject attributes
182 double SAL_CALL
ScVbaSheetObjectBase::getLeft()
184 return HmmToPoints( mxShape
->getPosition().X
);
187 void SAL_CALL
ScVbaSheetObjectBase::setLeft( double fLeft
)
190 throw uno::RuntimeException();
191 mxShape
->setPosition( awt::Point( PointsToHmm( fLeft
), mxShape
->getPosition().Y
) );
194 double SAL_CALL
ScVbaSheetObjectBase::getTop()
196 return HmmToPoints( mxShape
->getPosition().Y
);
199 void SAL_CALL
ScVbaSheetObjectBase::setTop( double fTop
)
202 throw uno::RuntimeException();
203 mxShape
->setPosition( awt::Point( mxShape
->getPosition().X
, PointsToHmm( fTop
) ) );
206 double SAL_CALL
ScVbaSheetObjectBase::getWidth()
208 return HmmToPoints( mxShape
->getSize().Width
);
211 void SAL_CALL
ScVbaSheetObjectBase::setWidth( double fWidth
)
214 throw uno::RuntimeException();
215 mxShape
->setSize( awt::Size( PointsToHmm( fWidth
), mxShape
->getSize().Height
) );
218 double SAL_CALL
ScVbaSheetObjectBase::getHeight()
220 return HmmToPoints( mxShape
->getSize().Height
);
223 void SAL_CALL
ScVbaSheetObjectBase::setHeight( double fHeight
)
226 throw uno::RuntimeException();
227 mxShape
->setSize( awt::Size( mxShape
->getSize().Width
, PointsToHmm( fHeight
) ) );
230 OUString SAL_CALL
ScVbaSheetObjectBase::getName()
232 return mxShapeProps
->getPropertyValue( u
"Name"_ustr
).get
< OUString
>();
235 void SAL_CALL
ScVbaSheetObjectBase::setName( const OUString
& rName
)
237 mxShapeProps
->setPropertyValue( u
"Name"_ustr
, uno::Any( rName
) );
240 sal_Int32 SAL_CALL
ScVbaSheetObjectBase::getPlacement()
242 sal_Int32
const nRet
= excel::XlPlacement::xlMoveAndSize
;
243 #if 0 // TODO: not working at the moment.
244 SvxShape
* pShape
= SdrObject::getSdrObjectFromXShape( mxShape
);
247 SdrObject
* pObj
= pShape
->GetSdrObject();
250 ScAnchorType eType
= ScDrawLayer::GetAnchor(pObj
);
251 if (eType
== SCA_PAGE
)
252 nRet
= excel::XlPlacement::xlFreeFloating
;
259 void SAL_CALL
ScVbaSheetObjectBase::setPlacement( sal_Int32
/*nPlacement*/ )
261 #if 0 // TODO: not working at the moment.
262 SvxShape
* pShape
= SdrObject::getSdrObjectFromXShape( mxShape
);
265 SdrObject
* pObj
= pShape
->GetSdrObject();
268 ScAnchorType eType
= SCA_CELL
;
269 if ( nPlacement
== excel::XlPlacement::xlFreeFloating
)
272 // xlMove is not supported, treated as SCA_CELL (xlMoveAndSize)
274 ScDrawLayer::SetAnchor(pObj
, eType
);
280 sal_Bool SAL_CALL
ScVbaSheetObjectBase::getPrintObject()
286 void SAL_CALL
ScVbaSheetObjectBase::setPrintObject( sal_Bool
/*bPrintObject*/ )
293 void ScVbaSheetObjectBase::setDefaultProperties( sal_Int32 nIndex
)
295 OUString aName
= implGetBaseName() + OUStringChar(' ') + OUString::number( nIndex
+ 1 );
297 implSetDefaultProperties();
300 void ScVbaSheetObjectBase::implSetDefaultProperties()
304 ScVbaControlObjectBase::ScVbaControlObjectBase(
305 const uno::Reference
< XHelperInterface
>& rxParent
,
306 const uno::Reference
< uno::XComponentContext
>& rxContext
,
307 const uno::Reference
< frame::XModel
>& rxModel
,
308 const uno::Reference
< container::XIndexContainer
>& rxFormIC
,
309 const uno::Reference
< drawing::XControlShape
>& rxControlShape
) :
310 ScVbaControlObject_BASE( rxParent
, rxContext
, rxModel
, uno::Reference
< drawing::XShape
>( rxControlShape
, uno::UNO_QUERY_THROW
) ),
311 mxFormIC( rxFormIC
, uno::UNO_SET_THROW
),
312 mxControlProps( rxControlShape
->getControl(), uno::UNO_QUERY_THROW
),
313 mbNotifyMacroEventRead(false)
317 // XSheetObject attributes
319 OUString SAL_CALL
ScVbaControlObjectBase::getName()
321 return mxControlProps
->getPropertyValue( u
"Name"_ustr
).get
< OUString
>();
324 void SAL_CALL
ScVbaControlObjectBase::setName( const OUString
& rName
)
326 mxControlProps
->setPropertyValue( u
"Name"_ustr
, uno::Any( rName
) );
329 OUString SAL_CALL
ScVbaControlObjectBase::getOnAction()
331 uno::Reference
< script::XEventAttacherManager
> xEventMgr( mxFormIC
, uno::UNO_QUERY_THROW
);
332 sal_Int32 nIndex
= getModelIndexInForm();
333 const uno::Sequence
< script::ScriptEventDescriptor
> aEvents
= xEventMgr
->getScriptEvents( nIndex
);
334 if( aEvents
.hasElements() )
336 const script::ScriptEventDescriptor
* pEvent
= std::find_if(aEvents
.begin(), aEvents
.end(),
337 [](const script::ScriptEventDescriptor
& rEvent
) {
338 return (rEvent
.ListenerType
== gaListenerType
)
339 && (rEvent
.EventMethod
== gaEventMethod
)
340 && (rEvent
.ScriptType
== "Script");
342 if (pEvent
!= aEvents
.end())
343 return extractMacroName( pEvent
->ScriptCode
);
348 void ScVbaControlObjectBase::NotifyMacroEventRead()
350 if (mbNotifyMacroEventRead
)
352 comphelper::DocumentInfo::notifyMacroEventRead(mxModel
);
353 mbNotifyMacroEventRead
= true;
356 void SAL_CALL
ScVbaControlObjectBase::setOnAction( const OUString
& rMacroName
)
358 uno::Reference
< script::XEventAttacherManager
> xEventMgr( mxFormIC
, uno::UNO_QUERY_THROW
);
359 sal_Int32 nIndex
= getModelIndexInForm();
361 // first, remove a registered event (try/catch just in case implementation throws)
362 try { xEventMgr
->revokeScriptEvent( nIndex
, gaListenerType
, gaEventMethod
, OUString() ); } catch( uno::Exception
& ) {}
364 // if a macro name has been passed, try to attach it to the event
365 if( rMacroName
.isEmpty() )
368 MacroResolvedInfo aResolvedMacro
= resolveVBAMacro( getSfxObjShell( mxModel
), rMacroName
);
369 if( !aResolvedMacro
.mbFound
)
370 throw uno::RuntimeException();
371 script::ScriptEventDescriptor aDescriptor
;
372 aDescriptor
.ListenerType
= gaListenerType
;
373 aDescriptor
.EventMethod
= gaEventMethod
;
374 aDescriptor
.ScriptType
= "Script";
375 aDescriptor
.ScriptCode
= makeMacroURL( aResolvedMacro
.msResolvedMacro
);
376 NotifyMacroEventRead();
377 xEventMgr
->registerScriptEvent( nIndex
, aDescriptor
);
380 sal_Bool SAL_CALL
ScVbaControlObjectBase::getPrintObject()
382 return mxControlProps
->getPropertyValue( u
"Printable"_ustr
).get
<bool>();
385 void SAL_CALL
ScVbaControlObjectBase::setPrintObject( sal_Bool bPrintObject
)
387 mxControlProps
->setPropertyValue( u
"Printable"_ustr
, uno::Any( bPrintObject
) );
390 // XControlObject attributes
392 sal_Bool SAL_CALL
ScVbaControlObjectBase::getAutoSize()
398 void SAL_CALL
ScVbaControlObjectBase::setAutoSize( sal_Bool
/*bAutoSize*/ )
405 sal_Int32
ScVbaControlObjectBase::getModelIndexInForm() const
407 for( sal_Int32 nIndex
= 0, nCount
= mxFormIC
->getCount(); nIndex
< nCount
; ++nIndex
)
409 uno::Reference
< beans::XPropertySet
> xProps( mxFormIC
->getByIndex( nIndex
), uno::UNO_QUERY_THROW
);
410 if( mxControlProps
.get() == xProps
.get() )
413 throw uno::RuntimeException();
416 ScVbaButton::ScVbaButton(
417 const uno::Reference
< XHelperInterface
>& rxParent
,
418 const uno::Reference
< uno::XComponentContext
>& rxContext
,
419 const uno::Reference
< frame::XModel
>& rxModel
,
420 const uno::Reference
< container::XIndexContainer
>& rxFormIC
,
421 const uno::Reference
< drawing::XControlShape
>& rxControlShape
) :
422 ScVbaButton_BASE( rxParent
, rxContext
, rxModel
, rxFormIC
, rxControlShape
)
426 // XButton attributes
428 OUString SAL_CALL
ScVbaButton::getCaption()
430 return mxControlProps
->getPropertyValue( u
"Label"_ustr
).get
< OUString
>();
433 void SAL_CALL
ScVbaButton::setCaption( const OUString
& rCaption
)
435 mxControlProps
->setPropertyValue( u
"Label"_ustr
, uno::Any( rCaption
) );
438 uno::Reference
< excel::XFont
> SAL_CALL
ScVbaButton::getFont()
440 return new ScVbaFont( this, mxContext
, maPalette
, mxControlProps
, nullptr, true );
443 void SAL_CALL
ScVbaButton::setFont( const uno::Reference
< excel::XFont
>& /*rxFont*/ )
448 sal_Int32 SAL_CALL
ScVbaButton::getHorizontalAlignment()
450 switch( mxControlProps
->getPropertyValue( u
"Align"_ustr
).get
< sal_Int16
>() )
452 case awt::TextAlign::LEFT
: return excel::Constants::xlLeft
;
453 case awt::TextAlign::RIGHT
: return excel::Constants::xlRight
;
454 case awt::TextAlign::CENTER
: return excel::Constants::xlCenter
;
456 return excel::Constants::xlCenter
;
459 void SAL_CALL
ScVbaButton::setHorizontalAlignment( sal_Int32 nAlign
)
461 sal_Int32 nAwtAlign
= awt::TextAlign::CENTER
;
464 case excel::Constants::xlLeft
: nAwtAlign
= awt::TextAlign::LEFT
; break;
465 case excel::Constants::xlRight
: nAwtAlign
= awt::TextAlign::RIGHT
; break;
466 case excel::Constants::xlCenter
: nAwtAlign
= awt::TextAlign::CENTER
; break;
468 // form controls expect short value
469 mxControlProps
->setPropertyValue( u
"Align"_ustr
, uno::Any( static_cast< sal_Int16
>( nAwtAlign
) ) );
472 sal_Int32 SAL_CALL
ScVbaButton::getVerticalAlignment()
474 switch( mxControlProps
->getPropertyValue( u
"VerticalAlign"_ustr
).get
< style::VerticalAlignment
>() )
476 case style::VerticalAlignment_TOP
: return excel::Constants::xlTop
;
477 case style::VerticalAlignment_BOTTOM
: return excel::Constants::xlBottom
;
478 case style::VerticalAlignment_MIDDLE
: return excel::Constants::xlCenter
;
481 return excel::Constants::xlCenter
;
484 void SAL_CALL
ScVbaButton::setVerticalAlignment( sal_Int32 nAlign
)
486 style::VerticalAlignment eAwtAlign
= style::VerticalAlignment_MIDDLE
;
489 case excel::Constants::xlTop
: eAwtAlign
= style::VerticalAlignment_TOP
; break;
490 case excel::Constants::xlBottom
: eAwtAlign
= style::VerticalAlignment_BOTTOM
; break;
491 case excel::Constants::xlCenter
: eAwtAlign
= style::VerticalAlignment_MIDDLE
; break;
493 mxControlProps
->setPropertyValue( u
"VerticalAlign"_ustr
, uno::Any( eAwtAlign
) );
496 sal_Int32 SAL_CALL
ScVbaButton::getOrientation()
499 return excel::XlOrientation::xlHorizontal
;
502 void SAL_CALL
ScVbaButton::setOrientation( sal_Int32
/*nOrientation*/ )
507 uno::Any SAL_CALL
ScVbaButton::getValue()
509 return mxControlProps
->getPropertyValue( u
"State"_ustr
);
512 void SAL_CALL
ScVbaButton::setValue( const uno::Any
&nValue
)
514 return mxControlProps
->setPropertyValue( u
"State"_ustr
, nValue
);
517 OUString SAL_CALL
ScVbaButton::getText()
519 return mxControlProps
->getPropertyValue( u
"Label"_ustr
).get
< OUString
>();
522 void SAL_CALL
ScVbaButton::setText( const OUString
&aText
)
524 return mxControlProps
->setPropertyValue( u
"Label"_ustr
, uno::Any( aText
) );
529 uno::Reference
< excel::XCharacters
> SAL_CALL
ScVbaButton::Characters( const uno::Any
& rStart
, const uno::Any
& rLength
)
531 return new ScVbaButtonCharacters( this, mxContext
, mxControlProps
, maPalette
, rStart
, rLength
);
536 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButton
, u
"ooo.vba.excel.Button"_ustr
)
540 OUString
ScVbaButton::implGetBaseName() const
542 return u
"Button"_ustr
;
545 void ScVbaButton::implSetDefaultProperties()
547 setCaption( getName() );
550 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */