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