Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / ui / vba / vbaborders.cxx
blob815f007676fa9ffbafe0f085fb25a4a9c1fd924a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include "vbaborders.hxx"
21 #include <sal/macros.h>
22 #include <cppuhelper/implbase.hxx>
23 #include <ooo/vba/excel/XlBordersIndex.hpp>
24 #include <ooo/vba/excel/XlBorderWeight.hpp>
25 #include <ooo/vba/excel/XlLineStyle.hpp>
26 #include <ooo/vba/excel/XlColorIndex.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/table/TableBorder.hpp>
29 #include <com/sun/star/table/XColumnRowRange.hpp>
31 #include "vbapalette.hxx"
33 using namespace ::com::sun::star;
34 using namespace ::ooo::vba;
35 using namespace ::ooo::vba::excel;
37 typedef ::cppu::WeakImplHelper<container::XIndexAccess > RangeBorders_Base;
38 typedef InheritedHelperInterfaceWeakImpl<excel::XBorder > ScVbaBorder_Base;
40 // #TODO sort these indexes to match the order in which Excel iterates over the
41 // borders, the enumeration will match the order in this list
42 static const sal_Int16 supportedIndexTable[] = { XlBordersIndex::xlEdgeLeft, XlBordersIndex::xlEdgeTop, XlBordersIndex::xlEdgeBottom, XlBordersIndex::xlEdgeRight, XlBordersIndex::xlDiagonalDown, XlBordersIndex::xlDiagonalUp, XlBordersIndex::xlInsideVertical, XlBordersIndex::xlInsideHorizontal };
44 static const char sTableBorder[] = "TableBorder";
46 // Equiv widths in 1/100 mm
47 const static sal_Int32 OOLineThin = 35;
48 const static sal_Int32 OOLineMedium = 88;
49 const static sal_Int32 OOLineThick = 141;
50 const static sal_Int32 OOLineHairline = 2;
52 class ScVbaBorder : public ScVbaBorder_Base
54 private:
55 uno::Reference< beans::XPropertySet > m_xProps;
56 sal_Int32 const m_LineType;
57 ScVbaPalette m_Palette;
58 void setBorderLine( const table::BorderLine& rBorderLine )
60 table::TableBorder aTableBorder;
61 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
63 switch ( m_LineType )
65 case XlBordersIndex::xlEdgeLeft:
66 aTableBorder.IsLeftLineValid = true;
67 aTableBorder.LeftLine= rBorderLine;
68 break;
69 case XlBordersIndex::xlEdgeTop:
70 aTableBorder.IsTopLineValid = true;
71 aTableBorder.TopLine = rBorderLine;
72 break;
74 case XlBordersIndex::xlEdgeBottom:
75 aTableBorder.IsBottomLineValid = true;
76 aTableBorder.BottomLine = rBorderLine;
77 break;
78 case XlBordersIndex::xlEdgeRight:
79 aTableBorder.IsRightLineValid = true;
80 aTableBorder.RightLine = rBorderLine;
81 break;
82 case XlBordersIndex::xlInsideVertical:
83 aTableBorder.IsVerticalLineValid = true;
84 aTableBorder.VerticalLine = rBorderLine;
85 break;
86 case XlBordersIndex::xlInsideHorizontal:
87 aTableBorder.IsHorizontalLineValid = true;
88 aTableBorder.HorizontalLine = rBorderLine;
89 break;
90 case XlBordersIndex::xlDiagonalDown:
91 case XlBordersIndex::xlDiagonalUp:
92 // #TODO have to ignore at the moment, would be
93 // nice to investigate what we can do here
94 break;
95 default:
96 return;
98 m_xProps->setPropertyValue( sTableBorder, uno::makeAny(aTableBorder) );
101 bool getBorderLine( table::BorderLine& rBorderLine )
103 table::TableBorder aTableBorder;
104 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
105 switch ( m_LineType )
107 case XlBordersIndex::xlEdgeLeft:
108 if ( aTableBorder.IsLeftLineValid )
109 rBorderLine = aTableBorder.LeftLine;
110 break;
111 case XlBordersIndex::xlEdgeTop:
112 if ( aTableBorder.IsTopLineValid )
113 rBorderLine = aTableBorder.TopLine;
114 break;
116 case XlBordersIndex::xlEdgeBottom:
117 if ( aTableBorder.IsBottomLineValid )
118 rBorderLine = aTableBorder.BottomLine;
119 break;
120 case XlBordersIndex::xlEdgeRight:
121 if ( aTableBorder.IsRightLineValid )
122 rBorderLine = aTableBorder.RightLine;
123 break;
124 case XlBordersIndex::xlInsideVertical:
125 if ( aTableBorder.IsVerticalLineValid )
126 rBorderLine = aTableBorder.VerticalLine;
127 break;
128 case XlBordersIndex::xlInsideHorizontal:
129 if ( aTableBorder.IsHorizontalLineValid )
130 rBorderLine = aTableBorder.HorizontalLine;
131 break;
133 case XlBordersIndex::xlDiagonalDown:
134 case XlBordersIndex::xlDiagonalUp:
135 // #TODO have to ignore at the moment, would be
136 // nice to investigate what we can do here
137 break;
138 default:
139 return false;
141 return true;
144 protected:
145 virtual OUString getServiceImplName() override
147 return "ScVbaBorder";
149 virtual css::uno::Sequence<OUString> getServiceNames() override
151 static uno::Sequence< OUString > const aServiceNames
153 "ooo.vba.excel.Border"
155 return aServiceNames;
157 public:
158 ScVbaBorder( const uno::Reference< beans::XPropertySet > & xProps, const uno::Reference< uno::XComponentContext >& xContext, sal_Int32 lineType, const ScVbaPalette& rPalette) : ScVbaBorder_Base( uno::Reference< XHelperInterface >( xProps, uno::UNO_QUERY ), xContext ), m_xProps( xProps ), m_LineType( lineType ), m_Palette( rPalette ) {}
160 // XBorder
161 uno::Any SAL_CALL getColor() override
163 table::BorderLine aBorderLine;
164 if ( getBorderLine( aBorderLine ) )
165 return uno::makeAny( OORGBToXLRGB( Color(aBorderLine.Color) ) );
166 throw uno::RuntimeException("No Implementation available" );
168 void SAL_CALL setColor( const uno::Any& _color ) override
170 sal_Int32 nColor = 0;
171 _color >>= nColor;
172 table::BorderLine aBorderLine;
173 if ( !getBorderLine( aBorderLine ) )
174 throw uno::RuntimeException("No Implementation available" );
176 aBorderLine.Color = XLRGBToOORGB( nColor );
177 setBorderLine( aBorderLine );
181 uno::Any SAL_CALL getColorIndex() override
183 sal_Int32 nColor = 0;
184 XLRGBToOORGB( getColor() ) >>= nColor;
185 uno::Reference< container::XIndexAccess > xIndex = m_Palette.getPalette();
186 sal_Int32 nElems = xIndex->getCount();
187 sal_Int32 nIndex = -1;
188 for ( sal_Int32 count=0; count<nElems; ++count )
190 sal_Int32 nPaletteColor = 0;
191 xIndex->getByIndex( count ) >>= nPaletteColor;
192 if ( nPaletteColor == nColor )
194 nIndex = count + 1;
195 break;
198 return uno::makeAny(nIndex);
201 void SAL_CALL setColorIndex( const uno::Any& _colorindex ) override
203 sal_Int32 nColor = 0;
204 _colorindex >>= nColor;
205 if ( !nColor || nColor == XlColorIndex::xlColorIndexAutomatic )
206 nColor = 1;
207 setColor( OORGBToXLRGB( m_Palette.getPalette()->getByIndex( --nColor ) ) );
209 uno::Any SAL_CALL getWeight() override
211 table::BorderLine aBorderLine;
212 if ( getBorderLine( aBorderLine ) )
214 switch ( aBorderLine.OuterLineWidth )
216 case 0: // Thin = default OO thickness
217 case OOLineThin:
218 return uno::makeAny( XlBorderWeight::xlThin );
219 case OOLineMedium:
220 return uno::makeAny( XlBorderWeight::xlMedium );
221 case OOLineThick:
222 return uno::makeAny( XlBorderWeight::xlThick );
223 case OOLineHairline:
224 return uno::makeAny( XlBorderWeight::xlHairline );
225 default:
226 break;
229 throw uno::RuntimeException("Method failed" );
231 void SAL_CALL setWeight( const uno::Any& _weight ) override
233 sal_Int32 nWeight = 0;
234 _weight >>= nWeight;
235 table::BorderLine aBorderLine;
236 if ( !getBorderLine( aBorderLine ) )
237 throw uno::RuntimeException("Method failed" );
239 switch ( nWeight )
241 case XlBorderWeight::xlThin:
242 aBorderLine.OuterLineWidth = OOLineThin;
243 break;
244 case XlBorderWeight::xlMedium:
245 aBorderLine.OuterLineWidth = OOLineMedium;
246 break;
247 case XlBorderWeight::xlThick:
248 aBorderLine.OuterLineWidth = OOLineThick;
249 break;
250 case XlBorderWeight::xlHairline:
251 aBorderLine.OuterLineWidth = OOLineHairline;
252 break;
253 default:
254 throw uno::RuntimeException("Bad param" );
256 setBorderLine( aBorderLine );
260 void SAL_CALL setTintAndShade( const uno::Any& /*rAny*/ ) override
262 // TODO implement
264 uno::Any SAL_CALL getTintAndShade() override
266 // TODO implement
267 return uno::makeAny(static_cast<double>(0));
270 uno::Any SAL_CALL getLineStyle() override
272 // always return xlContinuous;
273 return uno::makeAny( XlLineStyle::xlContinuous );
275 void SAL_CALL setLineStyle( const uno::Any& _linestyle ) override
277 // Urk no choice but to silently ignore we don't support this attribute
278 // #TODO would be nice to support the excel line styles
279 sal_Int32 nLineStyle = 0;
280 _linestyle >>= nLineStyle;
281 table::BorderLine aBorderLine;
282 if ( !getBorderLine( aBorderLine ) )
283 throw uno::RuntimeException("Method failed" );
285 switch ( nLineStyle )
287 case XlLineStyle::xlContinuous:
288 case XlLineStyle::xlDash:
289 case XlLineStyle::xlDashDot:
290 case XlLineStyle::xlDashDotDot:
291 case XlLineStyle::xlDot:
292 case XlLineStyle::xlDouble:
293 case XlLineStyle::xlLineStyleNone:
294 case XlLineStyle::xlSlantDashDot:
295 break;
296 default:
297 throw uno::RuntimeException("Bad param" );
299 setBorderLine( aBorderLine );
304 class RangeBorders : public RangeBorders_Base
306 private:
307 uno::Reference< table::XCellRange > m_xRange;
308 uno::Reference< uno::XComponentContext > m_xContext;
309 ScVbaPalette m_Palette;
310 sal_Int32 getTableIndex( sal_Int32 nConst )
312 // okay return position of the index in the table
313 sal_Int32 nIndexes = getCount();
314 sal_Int32 realIndex = 0;
315 const sal_Int16* pTableEntry = supportedIndexTable;
316 for ( ; realIndex < nIndexes; ++realIndex, ++pTableEntry )
318 if ( *pTableEntry == nConst )
319 return realIndex;
321 return getCount(); // error condition
323 public:
324 RangeBorders( const uno::Reference< table::XCellRange >& xRange, const uno::Reference< uno::XComponentContext > & xContext, const ScVbaPalette& rPalette ) : m_xRange( xRange ), m_xContext( xContext ), m_Palette( rPalette )
327 // XIndexAccess
328 virtual ::sal_Int32 SAL_CALL getCount( ) override
330 return SAL_N_ELEMENTS( supportedIndexTable );
332 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
335 sal_Int32 nIndex = getTableIndex( Index );
336 if ( nIndex >= 0 && nIndex < getCount() )
338 uno::Reference< beans::XPropertySet > xProps( m_xRange, uno::UNO_QUERY_THROW );
339 return uno::makeAny( uno::Reference< excel::XBorder >( new ScVbaBorder( xProps, m_xContext, supportedIndexTable[ nIndex ], m_Palette )) );
341 throw lang::IndexOutOfBoundsException();
343 virtual uno::Type SAL_CALL getElementType( ) override
345 return cppu::UnoType<excel::XBorder>::get();
347 virtual sal_Bool SAL_CALL hasElements( ) override
349 return true;
353 static uno::Reference< container::XIndexAccess >
354 rangeToBorderIndexAccess( const uno::Reference< table::XCellRange >& xRange, const uno::Reference< uno::XComponentContext > & xContext, const ScVbaPalette& rPalette )
356 return new RangeBorders( xRange, xContext, rPalette );
359 class RangeBorderEnumWrapper : public EnumerationHelper_BASE
361 uno::Reference<container::XIndexAccess > m_xIndexAccess;
362 sal_Int32 nIndex;
363 public:
364 explicit RangeBorderEnumWrapper( const uno::Reference< container::XIndexAccess >& xIndexAccess ) : m_xIndexAccess( xIndexAccess ), nIndex( 0 ) {}
365 virtual sal_Bool SAL_CALL hasMoreElements( ) override
367 return ( nIndex < m_xIndexAccess->getCount() );
370 virtual uno::Any SAL_CALL nextElement( ) override
372 if ( nIndex < m_xIndexAccess->getCount() )
373 return m_xIndexAccess->getByIndex( nIndex++ );
374 throw container::NoSuchElementException();
378 ScVbaBorders::ScVbaBorders( const uno::Reference< XHelperInterface >& xParent,
379 const uno::Reference< uno::XComponentContext > & xContext,
380 const uno::Reference< table::XCellRange >& xRange,
381 const ScVbaPalette& rPalette )
382 : ScVbaBorders_BASE( xParent, xContext, rangeToBorderIndexAccess( xRange ,xContext, rPalette ) ), bRangeIsSingleCell( false )
384 uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, uno::UNO_QUERY_THROW );
385 if ( xColumnRowRange->getRows()->getCount() == 1 && xColumnRowRange->getColumns()->getCount() == 1 )
386 bRangeIsSingleCell = true;
387 m_xProps.set( xRange, uno::UNO_QUERY_THROW );
390 uno::Reference< container::XEnumeration >
391 ScVbaBorders::createEnumeration()
393 return new RangeBorderEnumWrapper( m_xIndexAccess );
396 uno::Any
397 ScVbaBorders::createCollectionObject( const css::uno::Any& aSource )
399 return aSource; // it's already a Border object
402 uno::Type
403 ScVbaBorders::getElementType()
405 return cppu::UnoType<excel::XBorders>::get();
408 uno::Any
409 ScVbaBorders::getItemByIntIndex( const sal_Int32 nIndex )
411 return createCollectionObject( m_xIndexAccess->getByIndex( nIndex ) );
414 uno::Any SAL_CALL ScVbaBorders::getColor()
416 sal_Int32 count = getCount();
417 uno::Any color;
418 for( sal_Int32 i = 0; i < count ; i++ )
420 if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
422 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
423 if( color.hasValue() )
425 if( color != xBorder->getColor() )
426 return uno::makeAny( uno::Reference< uno::XInterface >() );
428 else
429 color = xBorder->getColor();
432 return color;
434 void SAL_CALL ScVbaBorders::setColor( const uno::Any& _color )
436 sal_Int32 count = getCount();
437 for( sal_Int32 i = 0; i < count ; i++ )
439 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
440 xBorder->setColor( _color );
443 uno::Any SAL_CALL ScVbaBorders::getColorIndex()
445 sal_Int32 count = getCount();
446 uno::Any nColorIndex;
447 for( sal_Int32 i = 0; i < count ; i++ )
449 if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
451 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
452 if( nColorIndex.hasValue() )
454 if( nColorIndex != xBorder->getColorIndex() )
455 return uno::makeAny( uno::Reference< uno::XInterface >() );
457 else
458 nColorIndex = xBorder->getColorIndex();
461 return nColorIndex;
463 void SAL_CALL ScVbaBorders::setColorIndex( const uno::Any& _colorindex )
465 sal_Int32 count = getCount();
466 for( sal_Int32 i = 0; i < count ; i++ )
468 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
469 xBorder->setColorIndex( _colorindex );
473 static bool
474 lcl_areAllLineWidthsSame( const table::TableBorder& maTableBorder, bool bIsCell )
477 bool bRes = false;
478 if (bIsCell)
480 bRes = ((maTableBorder.TopLine.OuterLineWidth == maTableBorder.BottomLine.OuterLineWidth) &&
481 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.LeftLine.OuterLineWidth) &&
482 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.RightLine.OuterLineWidth));
484 else
486 bRes = ((maTableBorder.TopLine.OuterLineWidth == maTableBorder.BottomLine.OuterLineWidth) &&
487 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.LeftLine.OuterLineWidth) &&
488 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.HorizontalLine.OuterLineWidth) &&
489 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.VerticalLine.OuterLineWidth) &&
490 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.RightLine.OuterLineWidth));
492 return bRes;
495 uno::Any SAL_CALL ScVbaBorders::getLineStyle()
497 table::TableBorder aTableBorder;
498 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
500 sal_Int32 aLinestyle = XlLineStyle::xlLineStyleNone;
502 if ( lcl_areAllLineWidthsSame( aTableBorder, bRangeIsSingleCell ))
504 if (aTableBorder.TopLine.LineDistance != 0)
506 aLinestyle = XlLineStyle::xlDouble;
508 else if ( aTableBorder.TopLine.OuterLineWidth != 0 )
510 aLinestyle = XlLineStyle::xlContinuous;
513 return uno::makeAny( aLinestyle );
515 void SAL_CALL ScVbaBorders::setLineStyle( const uno::Any& _linestyle )
517 sal_Int32 count = getCount();
518 for( sal_Int32 i = 0; i < count ; i++ )
520 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
521 xBorder->setLineStyle( _linestyle );
524 uno::Any SAL_CALL ScVbaBorders::getWeight()
526 sal_Int32 count = getCount();
527 uno::Any weight;
528 for( sal_Int32 i = 0; i < count ; i++ )
530 if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
532 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
533 if( weight.hasValue() )
535 if( weight != xBorder->getWeight() )
536 return uno::makeAny( uno::Reference< uno::XInterface >() );
538 else
539 weight = xBorder->getWeight();
542 return weight;
545 uno::Any SAL_CALL ScVbaBorders::getTintAndShade()
547 // TODO implement
548 return uno::makeAny(static_cast<double>(0));
551 void SAL_CALL ScVbaBorders::setTintAndShade(const uno::Any& /*rAny*/)
553 // TODO implement
556 void SAL_CALL ScVbaBorders::setWeight( const uno::Any& _weight )
558 sal_Int32 count = getCount();
559 for( sal_Int32 i = 0; i < count ; i++ )
561 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
562 xBorder->setWeight( _weight );
566 OUString
567 ScVbaBorders::getServiceImplName()
569 return "ScVbaBorders";
572 uno::Sequence< OUString >
573 ScVbaBorders::getServiceNames()
575 static uno::Sequence< OUString > const aServiceNames
577 "ooo.vba.excel.Borders"
579 return aServiceNames;
582 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */