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 #include <com/sun/star/beans/XPropertySet.hpp> 28 #include <com/sun/star/table/XCell.hpp> 29 #include <com/sun/star/table/XColumnRowRange.hpp> 30 #include <com/sun/star/beans/XIntrospection.hpp> 31 #include <com/sun/star/beans/XIntrospectionAccess.hpp> 32 #include <com/sun/star/reflection/XIdlMethod.hpp> 33 #include <com/sun/star/beans/MethodConcept.hpp> 34 #include <com/sun/star/beans/NamedValue.hpp> 35 #include <com/sun/star/xml/AttributeData.hpp> 36 37 #include <ooo/vba/excel/XlColorIndex.hpp> 38 #include <ooo/vba/excel/XlPattern.hpp> 39 40 #include <comphelper/processfactory.hxx> 41 #include <cppuhelper/queryinterface.hxx> 42 43 #include <map> 44 45 #include <svx/xtable.hxx> 46 47 #include "vbainterior.hxx" 48 #include "vbapalette.hxx" 49 #include "document.hxx" 50 51 #define STATIC_TABLE_SIZE( array ) (sizeof(array)/sizeof(*(array))) 52 #define COLORMAST 0xFFFFFF 53 const sal_uInt16 EXC_COLOR_WINDOWBACK = 65; 54 typedef std::map< sal_Int32, sal_Int32 > PatternMap; 55 typedef std::pair< sal_Int32, sal_Int32 > PatternPair; 56 using namespace ::com::sun::star; 57 using namespace ::ooo::vba; 58 using namespace ::ooo::vba::excel::XlPattern; 59 static const rtl::OUString BACKCOLOR( RTL_CONSTASCII_USTRINGPARAM( "CellBackColor" ) ); 60 static const rtl::OUString PATTERN( RTL_CONSTASCII_USTRINGPARAM( "Pattern" ) ); 61 static const rtl::OUString PATTERNCOLOR( RTL_CONSTASCII_USTRINGPARAM( "PatternColor" ) ); 62 63 PatternMap lcl_getPatternMap() 64 { 65 PatternMap aPatternMap; 66 aPatternMap.insert( PatternPair( xlPatternAutomatic, 0 ) ); 67 aPatternMap.insert( PatternPair( xlPatternChecker, 9 ) ); 68 aPatternMap.insert( PatternPair( xlPatternCrissCross, 16 ) ); 69 aPatternMap.insert( PatternPair( xlPatternDown, 7 ) ); 70 aPatternMap.insert( PatternPair( xlPatternGray16, 17 ) ); 71 aPatternMap.insert( PatternPair( xlPatternGray25, 4 ) ); 72 aPatternMap.insert( PatternPair( xlPatternGray50, 2 ) ); 73 aPatternMap.insert( PatternPair( xlPatternGray75, 3 ) ); 74 aPatternMap.insert( PatternPair( xlPatternGray8, 18 ) ); 75 aPatternMap.insert( PatternPair( xlPatternGrid, 15 ) ); 76 aPatternMap.insert( PatternPair( xlPatternHorizontal, 5 ) ); 77 aPatternMap.insert( PatternPair( xlPatternLightDown, 13 ) ); 78 aPatternMap.insert( PatternPair( xlPatternLightHorizontal, 11 ) ); 79 aPatternMap.insert( PatternPair( xlPatternLightUp, 14 ) ); 80 aPatternMap.insert( PatternPair( xlPatternLightVertical, 12 ) ); 81 aPatternMap.insert( PatternPair( xlPatternNone, 0 ) ); 82 aPatternMap.insert( PatternPair( xlPatternSemiGray75, 10 ) ); 83 aPatternMap.insert( PatternPair( xlPatternSolid, 0 ) ); 84 aPatternMap.insert( PatternPair( xlPatternUp, 8 ) ); 85 aPatternMap.insert( PatternPair( xlPatternVertical, 6 ) ); 86 return aPatternMap; 87 } 88 89 static PatternMap aPatternMap( lcl_getPatternMap() ); 90 91 ScVbaInterior::ScVbaInterior( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< beans::XPropertySet >& xProps, ScDocument* pScDoc ) throw ( lang::IllegalArgumentException) : ScVbaInterior_BASE( xParent, xContext ), m_xProps(xProps), m_pScDoc( pScDoc ) 92 { 93 // auto color 94 //m_aPattColor.SetColor( (sal_uInt32)0xFFFFFFFF ); 95 m_aPattColor.SetColor( (sal_uInt32)0x0 ); 96 m_nPattern = 0L; 97 if ( !m_xProps.is() ) 98 throw lang::IllegalArgumentException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "properties") ), uno::Reference< uno::XInterface >(), 2 ); 99 } 100 101 uno::Any 102 ScVbaInterior::getColor() throw (uno::RuntimeException) 103 { 104 Color aBackColor( GetBackColor() ); 105 return uno::makeAny( OORGBToXLRGB( aBackColor.GetColor() ) ); 106 } 107 108 void 109 ScVbaInterior::setColor( const uno::Any& _color ) throw (uno::RuntimeException) 110 { 111 sal_Int32 nColor = 0; 112 if( _color >>= nColor ) 113 { 114 SetUserDefinedAttributes( BACKCOLOR, SetAttributeData( XLRGBToOORGB( nColor ) ) ); 115 //m_xProps->setPropertyValue( BACKCOLOR , XLRGBToOORGB(_color)); 116 SetMixedColor(); 117 } 118 } 119 120 void 121 ScVbaInterior::SetMixedColor() 122 { 123 // pattern 124 uno::Any aPattern = GetUserDefinedAttributes( PATTERN ); 125 if( aPattern.hasValue() ) 126 { 127 m_nPattern = GetAttributeData( aPattern ); 128 } 129 sal_Int32 nPattern = aPatternMap[ m_nPattern ]; 130 // pattern color 131 uno::Any aPatternColor = GetUserDefinedAttributes( PATTERNCOLOR ); 132 if( aPatternColor.hasValue() ) 133 { 134 sal_uInt32 nPatternColor = GetAttributeData( aPatternColor ); 135 m_aPattColor.SetColor( nPatternColor ); 136 } 137 sal_Int32 nPatternColor = m_aPattColor.GetColor(); 138 // back color 139 Color aBackColor( GetBackColor() ); 140 // set mixed color 141 Color aMixedColor; 142 if( nPattern > 0 ) 143 aMixedColor = GetPatternColor( Color(nPatternColor), aBackColor, (sal_uInt32)nPattern ); 144 else 145 aMixedColor = GetPatternColor( aBackColor, aBackColor, (sal_uInt32)nPattern ); 146 sal_Int32 nMixedColor = aMixedColor.GetColor() & COLORMAST; 147 m_xProps->setPropertyValue( BACKCOLOR , uno::makeAny( nMixedColor ) ); 148 } 149 150 uno::Reference< container::XIndexAccess > 151 ScVbaInterior::getPalette() 152 { 153 if ( !m_pScDoc ) 154 throw uno::RuntimeException(); 155 SfxObjectShell* pShell = m_pScDoc->GetDocumentShell(); 156 ScVbaPalette aPalette( pShell ); 157 return aPalette.getPalette(); 158 } 159 160 void SAL_CALL 161 ScVbaInterior::setColorIndex( const css::uno::Any& _colorindex ) throw (css::uno::RuntimeException) 162 { 163 sal_Int32 nIndex = 0; 164 _colorindex >>= nIndex; 165 166 // hackly for excel::XlColorIndex::xlColorIndexNone 167 if( nIndex == excel::XlColorIndex::xlColorIndexNone ) 168 { 169 m_xProps->setPropertyValue( BACKCOLOR, uno::makeAny( sal_Int32( -1 ) ) ); 170 } 171 else 172 { 173 // setColor expects colors in XL RGB values 174 // #FIXME this is daft we convert OO RGB val to XL RGB val and 175 // then back again to OO RGB value 176 setColor( OORGBToXLRGB( GetIndexColor( nIndex ) ) ); 177 } 178 } 179 uno::Any 180 ScVbaInterior::GetIndexColor( const sal_Int32& nColorIndex ) 181 { 182 sal_Int32 nIndex = nColorIndex; 183 // #FIXME xlColorIndexAutomatic & xlColorIndexNone are not really 184 // handled properly here 185 if ( !nIndex || ( nIndex == excel::XlColorIndex::xlColorIndexAutomatic ) || ( nIndex == excel::XlColorIndex::xlColorIndexNone ) ) 186 nIndex = 2; // default is white ( this maybe will probably break, e.g. we may at some stage need to know what this interior is, a cell or something else and then pick a default colour based on that ) 187 --nIndex; // OOo indices are zero bases 188 uno::Reference< container::XIndexAccess > xIndex = getPalette(); 189 return xIndex->getByIndex( nIndex ); 190 } 191 192 sal_Int32 193 ScVbaInterior::GetColorIndex( const sal_Int32 nColor ) 194 { 195 uno::Reference< container::XIndexAccess > xIndex = getPalette(); 196 sal_Int32 nElems = xIndex->getCount(); 197 sal_Int32 nIndex = -1; 198 for ( sal_Int32 count=0; count<nElems; ++count ) 199 { 200 sal_Int32 nPaletteColor = 0; 201 xIndex->getByIndex( count ) >>= nPaletteColor; 202 if ( nPaletteColor == nColor ) 203 { 204 nIndex = count + 1; // 1 based 205 break; 206 } 207 } 208 return nIndex; 209 } 210 211 uno::Any SAL_CALL 212 ScVbaInterior::getColorIndex() throw ( css::uno::RuntimeException ) 213 { 214 sal_Int32 nColor = 0; 215 // hackly for excel::XlColorIndex::xlColorIndexNone 216 uno::Any aColor = m_xProps->getPropertyValue( BACKCOLOR ); 217 if( ( aColor >>= nColor ) && ( nColor == -1 ) ) 218 { 219 nColor = excel::XlColorIndex::xlColorIndexNone; 220 return uno::makeAny( nColor ); 221 } 222 223 // getColor returns Xl ColorValue, need to convert it to OO val 224 // as the palette deals with OO RGB values 225 // #FIXME this is daft in getColor we convert OO RGB val to XL RGB val 226 // and then back again to OO RGB value 227 XLRGBToOORGB( getColor() ) >>= nColor; 228 229 return uno::makeAny( GetColorIndex( nColor ) ); 230 } 231 Color 232 ScVbaInterior::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt32 nXclPattern ) 233 { 234 // 0x00 == 0% transparence (full rPattColor) 235 // 0x80 == 100% transparence (full rBackColor) 236 static const sal_uInt8 pnRatioTable[] = 237 { 238 0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07 239 0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15 240 0x50, 0x70, 0x78 // 16 - 18 241 }; 242 return ( nXclPattern < STATIC_TABLE_SIZE( pnRatioTable ) ) ? 243 GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor; 244 } 245 Color 246 ScVbaInterior::GetMixedColor( const Color& rFore, const Color& rBack, sal_uInt8 nTrans ) 247 { 248 return Color( 249 nTrans, 250 GetMixedColorComp( rFore.GetRed(), rBack.GetRed(), nTrans ), 251 GetMixedColorComp( rFore.GetGreen(), rBack.GetGreen(), nTrans ), 252 GetMixedColorComp( rFore.GetBlue(), rBack.GetBlue(), nTrans )); 253 } 254 sal_uInt8 255 ScVbaInterior::GetMixedColorComp( sal_uInt8 nFore, sal_uInt8 nBack, sal_uInt8 nTrans ) 256 { 257 sal_uInt32 nTemp = ((static_cast< sal_Int32 >( nBack ) - nFore) * nTrans) / 0x80 + nFore; 258 return static_cast< sal_uInt8 >( nTemp ); 259 } 260 uno::Reference< container::XNameContainer > 261 ScVbaInterior::GetAttributeContainer() 262 { 263 return uno::Reference < container::XNameContainer > ( m_xProps->getPropertyValue( rtl::OUString::createFromAscii( "UserDefinedAttributes" ) ), uno::UNO_QUERY_THROW ); 264 } 265 sal_Int32 266 ScVbaInterior::GetAttributeData( uno::Any aValue ) 267 { 268 xml::AttributeData aDataValue; 269 if( aValue >>= aDataValue ) 270 { 271 return aDataValue.Value.toInt32(); 272 } 273 return sal_Int32( 0 ); 274 } 275 uno::Any 276 ScVbaInterior::SetAttributeData( sal_Int32 nValue ) 277 { 278 xml::AttributeData aAttributeData; 279 //aAttributeData.Namespace = rtl::OUString::createFromAscii( "ooo.vba.excel.CellPatten"); 280 aAttributeData.Type = rtl::OUString::createFromAscii( "sal_Int32" ); 281 aAttributeData.Value = rtl::OUString::valueOf( nValue ); 282 return uno::makeAny( aAttributeData ); 283 } 284 uno::Any 285 ScVbaInterior::GetUserDefinedAttributes( const rtl::OUString& sName ) 286 { 287 uno::Reference< container::XNameContainer > xNameContainer( GetAttributeContainer(), uno::UNO_QUERY_THROW ); 288 if( xNameContainer->hasByName( sName ) ) 289 { 290 return xNameContainer->getByName( sName ); 291 } 292 return uno::Any(); 293 } 294 void 295 ScVbaInterior::SetUserDefinedAttributes( const rtl::OUString& sName, const uno::Any& aValue ) 296 { 297 if( aValue.hasValue() ) 298 { 299 uno::Reference< container::XNameContainer > xNameContainer( GetAttributeContainer(), uno::UNO_QUERY_THROW ); 300 if( xNameContainer->hasByName( sName ) ) 301 xNameContainer->removeByName( sName ); 302 xNameContainer->insertByName( sName, aValue ); 303 m_xProps->setPropertyValue( rtl::OUString::createFromAscii( "UserDefinedAttributes" ), uno::makeAny( xNameContainer ) ); 304 } 305 } 306 // OOo do not support below API 307 uno::Any SAL_CALL 308 ScVbaInterior::getPattern() throw (uno::RuntimeException) 309 { 310 // XlPattern 311 uno::Any aPattern = GetUserDefinedAttributes( PATTERN ); 312 if( aPattern.hasValue() ) 313 return uno::makeAny( GetAttributeData( aPattern ) ); 314 return uno::makeAny( excel::XlPattern::xlPatternNone ); 315 } 316 void SAL_CALL 317 ScVbaInterior::setPattern( const uno::Any& _pattern ) throw (uno::RuntimeException) 318 { 319 if( _pattern >>= m_nPattern ) 320 { 321 SetUserDefinedAttributes( PATTERN, SetAttributeData( m_nPattern ) ); 322 SetMixedColor(); 323 } 324 else 325 throw uno::RuntimeException( rtl::OUString::createFromAscii( "Invalid Pattern index" ), uno::Reference< uno::XInterface >() ); 326 } 327 Color 328 ScVbaInterior::GetBackColor() 329 { 330 sal_Int32 nColor = 0; 331 Color aBackColor; 332 uno::Any aColor = GetUserDefinedAttributes( BACKCOLOR ); 333 if( aColor.hasValue() ) 334 { 335 nColor = GetAttributeData( aColor ); 336 aBackColor.SetColor( nColor ); 337 } 338 else 339 { 340 uno::Any aAny; 341 aAny = OORGBToXLRGB( m_xProps->getPropertyValue( BACKCOLOR ) ); 342 if( aAny >>= nColor ) 343 { 344 nColor = XLRGBToOORGB( nColor ); 345 aBackColor.SetColor( nColor ); 346 SetUserDefinedAttributes( BACKCOLOR, SetAttributeData( nColor ) ); 347 } 348 } 349 return aBackColor; 350 } 351 uno::Any SAL_CALL 352 ScVbaInterior::getPatternColor() throw (uno::RuntimeException) 353 { 354 // 0 is the default color. no filled. 355 uno::Any aPatternColor = GetUserDefinedAttributes( PATTERNCOLOR ); 356 if( aPatternColor.hasValue() ) 357 { 358 sal_uInt32 nPatternColor = GetAttributeData( aPatternColor ); 359 return uno::makeAny( OORGBToXLRGB( nPatternColor ) ); 360 } 361 return uno::makeAny( sal_Int32( 0 ) ); 362 } 363 void SAL_CALL 364 ScVbaInterior::setPatternColor( const uno::Any& _patterncolor ) throw (uno::RuntimeException) 365 { 366 sal_Int32 nPattColor = 0; 367 if( _patterncolor >>= nPattColor ) 368 { 369 SetUserDefinedAttributes( PATTERNCOLOR, SetAttributeData( XLRGBToOORGB( nPattColor ) ) ); 370 SetMixedColor(); 371 } 372 else 373 throw uno::RuntimeException( rtl::OUString::createFromAscii( "Invalid Pattern Color" ), uno::Reference< uno::XInterface >() ); 374 } 375 uno::Any SAL_CALL 376 ScVbaInterior::getPatternColorIndex() throw (uno::RuntimeException) 377 { 378 sal_Int32 nColor = 0; 379 XLRGBToOORGB( getPatternColor() ) >>= nColor; 380 381 return uno::makeAny( GetIndexColor( nColor ) ); 382 } 383 void SAL_CALL 384 ScVbaInterior::setPatternColorIndex( const uno::Any& _patterncolorindex ) throw (uno::RuntimeException) 385 { 386 sal_Int32 nColorIndex = 0; 387 if( _patterncolorindex >>= nColorIndex ) 388 { 389 if( nColorIndex == 0 ) 390 return; 391 sal_Int32 nPattColor = 0; 392 GetIndexColor( nColorIndex ) >>= nPattColor; 393 setPatternColor( uno::makeAny( OORGBToXLRGB( nPattColor ) ) ); 394 } 395 else 396 throw uno::RuntimeException( rtl::OUString::createFromAscii( "Invalid Pattern Color" ), uno::Reference< uno::XInterface >() ); 397 } 398 399 rtl::OUString& 400 ScVbaInterior::getServiceImplName() 401 { 402 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaInterior") ); 403 return sImplName; 404 } 405 406 uno::Sequence< rtl::OUString > 407 ScVbaInterior::getServiceNames() 408 { 409 static uno::Sequence< rtl::OUString > aServiceNames; 410 if ( aServiceNames.getLength() == 0 ) 411 { 412 aServiceNames.realloc( 1 ); 413 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Interior" ) ); 414 } 415 return aServiceNames; 416 } 417 418