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