xref: /AOO41X/main/sc/source/ui/vba/vbasheetobject.cxx (revision e9cbe144f2ea8c6fdc1a6527ef692f8296608908)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "vbasheetobject.hxx"
25 #include <com/sun/star/awt/TextAlign.hpp>
26 #include <com/sun/star/container/XIndexContainer.hpp>
27 #include <com/sun/star/drawing/XControlShape.hpp>
28 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
29 #include <com/sun/star/script/XEventAttacherManager.hpp>
30 #include <com/sun/star/style/VerticalAlignment.hpp>
31 #include <ooo/vba/excel/Constants.hpp>
32 #include <ooo/vba/excel/XlOrientation.hpp>
33 #include <ooo/vba/excel/XlPlacement.hpp>
34 #include <rtl/ustrbuf.hxx>
35 #include <filter/msfilter/msvbahelper.hxx>
36 #include <oox/helper/helper.hxx>
37 #include <svx/unoshape.hxx>
38 #include "vbafont.hxx"
39 #include "drwlayer.hxx"
40 
41 using ::rtl::OUString;
42 using namespace ::com::sun::star;
43 using namespace ::ooo::vba;
44 
45 // ============================================================================
46 
47 ScVbaButtonCharacters::ScVbaButtonCharacters(
48         const uno::Reference< XHelperInterface >& rxParent,
49         const uno::Reference< uno::XComponentContext >& rxContext,
50         const uno::Reference< beans::XPropertySet >& rxPropSet,
51         const ScVbaPalette& rPalette,
52         const uno::Any& rStart,
53         const uno::Any& rLength ) throw (uno::RuntimeException) :
54     ScVbaButtonCharacters_BASE( rxParent, rxContext ),
55     maPalette( rPalette ),
56     mxPropSet( rxPropSet, uno::UNO_SET_THROW )
57 {
58     // extract optional start parameter (missing or invalid -> from beginning)
59     if( !(rStart >>= mnStart) || (mnStart < 1) )
60         mnStart = 1;
61     --mnStart;  // VBA is 1-based, rtl string is 0-based
62 
63     // extract optional length parameter (missing or invalid -> to end)
64     if( !(rLength >>= mnLength) || (mnLength < 1) )
65         mnLength = SAL_MAX_INT32;
66 }
67 
68 ScVbaButtonCharacters::~ScVbaButtonCharacters()
69 {
70 }
71 
72 // XCharacters attributes
73 
74 OUString SAL_CALL ScVbaButtonCharacters::getCaption() throw (uno::RuntimeException)
75 {
76     // ignore invalid mnStart and/or mnLength members
77     OUString aString = getFullString();
78     sal_Int32 nStart = ::std::min( mnStart, aString.getLength() );
79     sal_Int32 nLength = ::std::min( mnLength, aString.getLength() - nStart );
80     return aString.copy( nStart, nLength );
81 }
82 
83 void SAL_CALL ScVbaButtonCharacters::setCaption( const OUString& rCaption ) throw (uno::RuntimeException)
84 {
85     /*  Replace the covered text with the passed text, ignore invalid mnStart
86         and/or mnLength members. This operation does not affect the mnLength
87         parameter. If the inserted text is longer than mnLength, the additional
88         characters are not covered by this object. If the inserted text is
89         shorter than mnLength, other uncovered characters from the original
90         string will be covered now, thus may be changed with subsequent
91         operations. */
92     OUString aString = getFullString();
93     sal_Int32 nStart = ::std::min( mnStart, aString.getLength() );
94     sal_Int32 nLength = ::std::min( mnLength, aString.getLength() - nStart );
95     setFullString( aString.replaceAt( nStart, nLength, rCaption ) );
96 }
97 
98 sal_Int32 SAL_CALL ScVbaButtonCharacters::getCount() throw (uno::RuntimeException)
99 {
100     // always return the total length of the caption
101     return getFullString().getLength();
102 }
103 
104 OUString SAL_CALL ScVbaButtonCharacters::getText() throw (uno::RuntimeException)
105 {
106     // Text attribute same as Caption attribute?
107     return getCaption();
108 }
109 
110 void SAL_CALL ScVbaButtonCharacters::setText( const OUString& rText ) throw (uno::RuntimeException)
111 {
112     // Text attribute same as Caption attribute?
113     setCaption( rText );
114 }
115 
116 uno::Reference< excel::XFont > SAL_CALL ScVbaButtonCharacters::getFont() throw (uno::RuntimeException)
117 {
118     return new ScVbaFont( this, mxContext, maPalette, mxPropSet, 0, true );
119 }
120 
121 void SAL_CALL ScVbaButtonCharacters::setFont( const uno::Reference< excel::XFont >& /*rxFont*/ ) throw (uno::RuntimeException)
122 {
123     // TODO
124 }
125 
126 // XCharacters methods
127 
128 void SAL_CALL ScVbaButtonCharacters::Insert( const OUString& rString ) throw (uno::RuntimeException)
129 {
130     /*  The Insert() operation is in fact "replace covered characters", at
131         least for buttons... It seems there is no easy way to really insert a
132         substring. This operation does not affect the mnLength parameter. */
133     setCaption( rString );
134 }
135 
136 void SAL_CALL ScVbaButtonCharacters::Delete() throw (uno::RuntimeException)
137 {
138     /*  The Delete() operation is nothing else than "replace with empty string".
139         This does not affect the mnLength parameter, multiple calls of Delete()
140         will remove characters as long as there are some more covered by this
141         object. */
142     setCaption( OUString() );
143 }
144 
145 // XHelperInterface
146 
147 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButtonCharacters, "ooo.vba.excel.Characters" )
148 
149 // private
150 
151 OUString ScVbaButtonCharacters::getFullString() const throw (uno::RuntimeException)
152 {
153     return mxPropSet->getPropertyValue( CREATE_OUSTRING( "Label" ) ).get< OUString >();
154 }
155 
156 void ScVbaButtonCharacters::setFullString( const OUString& rString ) throw (uno::RuntimeException)
157 {
158     mxPropSet->setPropertyValue( CREATE_OUSTRING( "Label" ), uno::Any( rString ) );
159 }
160 
161 // ============================================================================
162 
163 ScVbaSheetObjectBase::ScVbaSheetObjectBase(
164         const uno::Reference< XHelperInterface >& rxParent,
165         const uno::Reference< uno::XComponentContext >& rxContext,
166         const uno::Reference< frame::XModel >& rxModel,
167         const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) :
168     ScVbaSheetObject_BASE( rxParent, rxContext ),
169     maPalette( rxModel ),
170     mxModel( rxModel, uno::UNO_SET_THROW ),
171     mxShape( rxShape, uno::UNO_SET_THROW ),
172     mxShapeProps( rxShape, uno::UNO_QUERY_THROW )
173 {
174 }
175 
176 // XSheetObject attributes
177 
178 double SAL_CALL ScVbaSheetObjectBase::getLeft() throw (uno::RuntimeException)
179 {
180     return HmmToPoints( mxShape->getPosition().X );
181 }
182 
183 void SAL_CALL ScVbaSheetObjectBase::setLeft( double fLeft ) throw (uno::RuntimeException)
184 {
185     if( fLeft < 0.0 )
186         throw uno::RuntimeException();
187     mxShape->setPosition( awt::Point( PointsToHmm( fLeft ), mxShape->getPosition().Y ) );
188 }
189 
190 double SAL_CALL ScVbaSheetObjectBase::getTop() throw (uno::RuntimeException)
191 {
192     return HmmToPoints( mxShape->getPosition().Y );
193 }
194 
195 void SAL_CALL ScVbaSheetObjectBase::setTop( double fTop ) throw (uno::RuntimeException)
196 {
197     if( fTop < 0.0 )
198         throw uno::RuntimeException();
199     mxShape->setPosition( awt::Point( mxShape->getPosition().X, PointsToHmm( fTop ) ) );
200 }
201 
202 double SAL_CALL ScVbaSheetObjectBase::getWidth() throw (uno::RuntimeException)
203 {
204     return HmmToPoints( mxShape->getSize().Width );
205 }
206 
207 void SAL_CALL ScVbaSheetObjectBase::setWidth( double fWidth ) throw (uno::RuntimeException)
208 {
209     if( fWidth <= 0.0 )
210         throw uno::RuntimeException();
211     mxShape->setSize( awt::Size( PointsToHmm( fWidth ), mxShape->getSize().Height ) );
212 }
213 
214 double SAL_CALL ScVbaSheetObjectBase::getHeight() throw (uno::RuntimeException)
215 {
216     return HmmToPoints( mxShape->getSize().Height );
217 }
218 
219 void SAL_CALL ScVbaSheetObjectBase::setHeight( double fHeight ) throw (uno::RuntimeException)
220 {
221     if( fHeight <= 0.0 )
222         throw uno::RuntimeException();
223     mxShape->setSize( awt::Size( mxShape->getSize().Width, PointsToHmm( fHeight ) ) );
224 }
225 
226 OUString SAL_CALL ScVbaSheetObjectBase::getName() throw (uno::RuntimeException)
227 {
228     return mxShapeProps->getPropertyValue( CREATE_OUSTRING( "Name" ) ).get< OUString >();
229 }
230 
231 void SAL_CALL ScVbaSheetObjectBase::setName( const OUString& rName ) throw (uno::RuntimeException)
232 {
233     mxShapeProps->setPropertyValue( CREATE_OUSTRING( "Name" ), uno::Any( rName ) );
234 }
235 
236 sal_Int32 SAL_CALL ScVbaSheetObjectBase::getPlacement() throw (uno::RuntimeException)
237 {
238     sal_Int32 nRet = excel::XlPlacement::xlMoveAndSize;
239     SvxShape* pShape = SvxShape::getImplementation( mxShape );
240     if(pShape)
241     {
242         SdrObject* pObj = pShape->GetSdrObject();
243         if (pObj)
244         {
245             ScAnchorType eType = ScDrawLayer::GetAnchor(pObj);
246             if (eType == SCA_PAGE)
247                 nRet = excel::XlPlacement::xlFreeFloating;
248         }
249     }
250     return nRet;
251 }
252 
253 void SAL_CALL ScVbaSheetObjectBase::setPlacement( sal_Int32 nPlacement ) throw (uno::RuntimeException)
254 {
255     SvxShape* pShape = SvxShape::getImplementation( mxShape );
256     if(pShape)
257     {
258         SdrObject* pObj = pShape->GetSdrObject();
259         if (pObj)
260         {
261             ScAnchorType eType = SCA_CELL;
262             if ( nPlacement == excel::XlPlacement::xlFreeFloating )
263                 eType = SCA_PAGE;
264 
265             // xlMove is not supported, treated as SCA_CELL (xlMoveAndSize)
266 
267             ScDrawLayer::SetAnchor(pObj, eType);
268         }
269     }
270 }
271 
272 sal_Bool SAL_CALL ScVbaSheetObjectBase::getPrintObject() throw (uno::RuntimeException)
273 {
274     // not supported
275     return sal_True;
276 }
277 
278 void SAL_CALL ScVbaSheetObjectBase::setPrintObject( sal_Bool /*bPrintObject*/ ) throw (uno::RuntimeException)
279 {
280     // not supported
281 }
282 
283 // private
284 
285 void ScVbaSheetObjectBase::setDefaultProperties( sal_Int32 nIndex ) throw (uno::RuntimeException)
286 {
287     OUString aName = ::rtl::OUStringBuffer( implGetBaseName() ).append( sal_Unicode( ' ' ) ).append( nIndex + 1 ).makeStringAndClear();
288     setName( aName );
289     implSetDefaultProperties();
290 }
291 
292 void ScVbaSheetObjectBase::implSetDefaultProperties() throw (uno::RuntimeException)
293 {
294 }
295 
296 // ============================================================================
297 
298 ScVbaControlObjectBase::ScVbaControlObjectBase(
299         const uno::Reference< XHelperInterface >& rxParent,
300         const uno::Reference< uno::XComponentContext >& rxContext,
301         const uno::Reference< frame::XModel >& rxModel,
302         const uno::Reference< container::XIndexContainer >& rxFormIC,
303         const uno::Reference< drawing::XControlShape >& rxControlShape,
304         ListenerType eListenerType ) throw (uno::RuntimeException) :
305     ScVbaControlObject_BASE( rxParent, rxContext, rxModel, uno::Reference< drawing::XShape >( rxControlShape, uno::UNO_QUERY_THROW ) ),
306     mxFormIC( rxFormIC, uno::UNO_SET_THROW ),
307     mxControlProps( rxControlShape->getControl(), uno::UNO_QUERY_THROW )
308 {
309     // set listener and event name to be used for OnAction attribute
310     switch( eListenerType )
311     {
312         case LISTENER_ACTION:
313             maListenerType = CREATE_OUSTRING( "XActionListener" );
314             maEventMethod = CREATE_OUSTRING( "actionPerformed" );
315         break;
316         case LISTENER_MOUSE:
317             maListenerType = CREATE_OUSTRING( "XMouseListener" );
318             maEventMethod = CREATE_OUSTRING( "mouseReleased" );
319         break;
320         case LISTENER_TEXT:
321             maListenerType = CREATE_OUSTRING( "XTextListener" );
322             maEventMethod = CREATE_OUSTRING( "textChanged" );
323         break;
324         case LISTENER_VALUE:
325             maListenerType = CREATE_OUSTRING( "XAdjustmentListener" );
326             maEventMethod = CREATE_OUSTRING( "adjustmentValueChanged" );
327         break;
328         case LISTENER_CHANGE:
329             maListenerType = CREATE_OUSTRING( "XChangeListener" );
330             maEventMethod = CREATE_OUSTRING( "changed" );
331         break;
332         // no default, to let the compiler complain about missing case
333     }
334 }
335 
336 // XSheetObject attributes
337 
338 OUString SAL_CALL ScVbaControlObjectBase::getName() throw (uno::RuntimeException)
339 {
340     return mxControlProps->getPropertyValue( CREATE_OUSTRING( "Name" ) ).get< OUString >();
341 }
342 
343 void SAL_CALL ScVbaControlObjectBase::setName( const OUString& rName ) throw (uno::RuntimeException)
344 {
345     mxControlProps->setPropertyValue( CREATE_OUSTRING( "Name" ), uno::Any( rName ) );
346 }
347 
348 OUString SAL_CALL ScVbaControlObjectBase::getOnAction() throw (uno::RuntimeException)
349 {
350     uno::Reference< script::XEventAttacherManager > xEventMgr( mxFormIC, uno::UNO_QUERY_THROW );
351     sal_Int32 nIndex = getModelIndexInForm();
352     uno::Sequence< script::ScriptEventDescriptor > aEvents = xEventMgr->getScriptEvents( nIndex );
353     if( aEvents.hasElements() )
354     {
355         const script::ScriptEventDescriptor* pEvent = aEvents.getConstArray();
356         const script::ScriptEventDescriptor* pEventEnd = pEvent + aEvents.getLength();
357         const OUString aScriptType = CREATE_OUSTRING( "Script" );
358         for( ; pEvent < pEventEnd; ++pEvent )
359             if( (pEvent->ListenerType == maListenerType) && (pEvent->EventMethod == maEventMethod) && (pEvent->ScriptType == aScriptType) )
360                 return extractMacroName( pEvent->ScriptCode );
361     }
362     return OUString();
363 }
364 
365 void SAL_CALL ScVbaControlObjectBase::setOnAction( const OUString& rMacroName ) throw (uno::RuntimeException)
366 {
367     uno::Reference< script::XEventAttacherManager > xEventMgr( mxFormIC, uno::UNO_QUERY_THROW );
368     sal_Int32 nIndex = getModelIndexInForm();
369 
370     // first, remove a registered event (try/catch just in case implementation throws)
371     try { xEventMgr->revokeScriptEvent( nIndex, maListenerType, maEventMethod, OUString() ); } catch( uno::Exception& ) {}
372 
373     // if a macro name has been passed, try to attach it to the event
374     if( rMacroName.getLength() > 0 )
375     {
376         MacroResolvedInfo aResolvedMacro = resolveVBAMacro( getSfxObjShell( mxModel ), rMacroName );
377         if( !aResolvedMacro.mbFound )
378             throw uno::RuntimeException();
379         script::ScriptEventDescriptor aDescriptor;
380         aDescriptor.ListenerType = maListenerType;
381         aDescriptor.EventMethod = maEventMethod;
382         aDescriptor.ScriptType = CREATE_OUSTRING( "Script" );
383         aDescriptor.ScriptCode = makeMacroURL( aResolvedMacro.msResolvedMacro );
384         xEventMgr->registerScriptEvent( nIndex, aDescriptor );
385     }
386 }
387 
388 sal_Bool SAL_CALL ScVbaControlObjectBase::getPrintObject() throw (uno::RuntimeException)
389 {
390     return mxControlProps->getPropertyValue( CREATE_OUSTRING( "Printable" ) ).get< sal_Bool >();
391 }
392 
393 void SAL_CALL ScVbaControlObjectBase::setPrintObject( sal_Bool bPrintObject ) throw (uno::RuntimeException)
394 {
395     mxControlProps->setPropertyValue( CREATE_OUSTRING( "Printable" ), uno::Any( bPrintObject ) );
396 }
397 
398 // XControlObject attributes
399 
400 sal_Bool SAL_CALL ScVbaControlObjectBase::getAutoSize() throw (uno::RuntimeException)
401 {
402     // not supported
403     return sal_False;
404 }
405 
406 void SAL_CALL ScVbaControlObjectBase::setAutoSize( sal_Bool /*bAutoSize*/ ) throw (uno::RuntimeException)
407 {
408     // not supported
409 }
410 
411 // private
412 
413 sal_Int32 ScVbaControlObjectBase::getModelIndexInForm() const throw (uno::RuntimeException)
414 {
415     for( sal_Int32 nIndex = 0, nCount = mxFormIC->getCount(); nIndex < nCount; ++nIndex )
416     {
417         uno::Reference< beans::XPropertySet > xProps( mxFormIC->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
418         if( mxControlProps.get() == xProps.get() )
419             return nIndex;
420     }
421     throw uno::RuntimeException();
422 }
423 
424 // ============================================================================
425 
426 ScVbaButton::ScVbaButton(
427         const uno::Reference< XHelperInterface >& rxParent,
428         const uno::Reference< uno::XComponentContext >& rxContext,
429         const uno::Reference< frame::XModel >& rxModel,
430         const uno::Reference< container::XIndexContainer >& rxFormIC,
431         const uno::Reference< drawing::XControlShape >& rxControlShape ) throw (uno::RuntimeException) :
432     ScVbaButton_BASE( rxParent, rxContext, rxModel, rxFormIC, rxControlShape, LISTENER_ACTION )
433 {
434 }
435 
436 // XButton attributes
437 
438 OUString SAL_CALL ScVbaButton::getCaption() throw (uno::RuntimeException)
439 {
440     return mxControlProps->getPropertyValue( CREATE_OUSTRING( "Label" ) ).get< OUString >();
441 }
442 
443 void SAL_CALL ScVbaButton::setCaption( const OUString& rCaption ) throw (uno::RuntimeException)
444 {
445     mxControlProps->setPropertyValue( CREATE_OUSTRING( "Label" ), uno::Any( rCaption ) );
446 }
447 
448 uno::Reference< excel::XFont > SAL_CALL ScVbaButton::getFont() throw (uno::RuntimeException)
449 {
450     return new ScVbaFont( this, mxContext, maPalette, mxControlProps, 0, true );
451 }
452 
453 void SAL_CALL ScVbaButton::setFont( const uno::Reference< excel::XFont >& /*rxFont*/ ) throw (uno::RuntimeException)
454 {
455     // TODO
456 }
457 
458 sal_Int32 SAL_CALL ScVbaButton::getHorizontalAlignment() throw (uno::RuntimeException)
459 {
460     switch( mxControlProps->getPropertyValue( CREATE_OUSTRING( "Align" ) ).get< sal_Int16 >() )
461     {
462         case awt::TextAlign::LEFT:      return excel::Constants::xlLeft;
463         case awt::TextAlign::RIGHT:     return excel::Constants::xlRight;
464         case awt::TextAlign::CENTER:    return excel::Constants::xlCenter;
465     }
466     return excel::Constants::xlCenter;
467 }
468 
469 void SAL_CALL ScVbaButton::setHorizontalAlignment( sal_Int32 nAlign ) throw (uno::RuntimeException)
470 {
471     sal_Int32 nAwtAlign = awt::TextAlign::CENTER;
472     switch( nAlign )
473     {
474         case excel::Constants::xlLeft:      nAwtAlign = awt::TextAlign::LEFT;   break;
475         case excel::Constants::xlRight:     nAwtAlign = awt::TextAlign::RIGHT;  break;
476         case excel::Constants::xlCenter:    nAwtAlign = awt::TextAlign::CENTER; break;
477     }
478     // form controls expect short value
479     mxControlProps->setPropertyValue( CREATE_OUSTRING( "Align" ), uno::Any( static_cast< sal_Int16 >( nAwtAlign ) ) );
480 }
481 
482 sal_Int32 SAL_CALL ScVbaButton::getVerticalAlignment() throw (uno::RuntimeException)
483 {
484     switch( mxControlProps->getPropertyValue( CREATE_OUSTRING( "VerticalAlign" ) ).get< style::VerticalAlignment >() )
485     {
486         case style::VerticalAlignment_TOP:      return excel::Constants::xlTop;
487         case style::VerticalAlignment_BOTTOM:   return excel::Constants::xlBottom;
488         case style::VerticalAlignment_MIDDLE:   return excel::Constants::xlCenter;
489         default:;
490     }
491     return excel::Constants::xlCenter;
492 }
493 
494 void SAL_CALL ScVbaButton::setVerticalAlignment( sal_Int32 nAlign ) throw (uno::RuntimeException)
495 {
496     style::VerticalAlignment eAwtAlign = style::VerticalAlignment_MIDDLE;
497     switch( nAlign )
498     {
499         case excel::Constants::xlTop:       eAwtAlign = style::VerticalAlignment_TOP;       break;
500         case excel::Constants::xlBottom:    eAwtAlign = style::VerticalAlignment_BOTTOM;    break;
501         case excel::Constants::xlCenter:    eAwtAlign = style::VerticalAlignment_MIDDLE;    break;
502     }
503     mxControlProps->setPropertyValue( CREATE_OUSTRING( "VerticalAlign" ), uno::Any( eAwtAlign ) );
504 }
505 
506 sal_Int32 SAL_CALL ScVbaButton::getOrientation() throw (uno::RuntimeException)
507 {
508     // not supported
509     return excel::XlOrientation::xlHorizontal;
510 }
511 
512 void SAL_CALL ScVbaButton::setOrientation( sal_Int32 /*nOrientation*/ ) throw (uno::RuntimeException)
513 {
514     // not supported
515 }
516 
517 // XButton methods
518 
519 uno::Reference< excel::XCharacters > SAL_CALL ScVbaButton::Characters( const uno::Any& rStart, const uno::Any& rLength ) throw (uno::RuntimeException)
520 {
521     return new ScVbaButtonCharacters( this, mxContext, mxControlProps, maPalette, rStart, rLength );
522 }
523 
524 // XHelperInterface
525 
526 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButton, "ooo.vba.excel.Button" )
527 
528 // private
529 
530 OUString ScVbaButton::implGetBaseName() const
531 {
532     return CREATE_OUSTRING( "Button" );
533 }
534 
535 void ScVbaButton::implSetDefaultProperties() throw (uno::RuntimeException)
536 {
537     setCaption( getName() );
538 }
539 
540 // ============================================================================
541