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