1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/implbase3.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::WeakImplHelper1
<container::XIndexAccess
> RangeBorders_Base
;
38 typedef InheritedHelperInterfaceImpl1
<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
55 uno::Reference
< beans::XPropertySet
> m_xProps
;
57 ScVbaPalette m_Palette
;
58 bool setBorderLine( table::BorderLine
& rBorderLine
)
60 table::TableBorder aTableBorder
;
61 m_xProps
->getPropertyValue( sTableBorder
) >>= aTableBorder
;
65 case XlBordersIndex::xlEdgeLeft
:
66 aTableBorder
.IsLeftLineValid
= sal_True
;
67 aTableBorder
.LeftLine
= rBorderLine
;
69 case XlBordersIndex::xlEdgeTop
:
70 aTableBorder
.IsTopLineValid
= sal_True
;
71 aTableBorder
.TopLine
= rBorderLine
;
74 case XlBordersIndex::xlEdgeBottom
:
75 aTableBorder
.IsBottomLineValid
= sal_True
;
76 aTableBorder
.BottomLine
= rBorderLine
;
78 case XlBordersIndex::xlEdgeRight
:
79 aTableBorder
.IsRightLineValid
= sal_True
;
80 aTableBorder
.RightLine
= rBorderLine
;
82 case XlBordersIndex::xlInsideVertical
:
83 aTableBorder
.IsVerticalLineValid
= sal_True
;
84 aTableBorder
.VerticalLine
= rBorderLine
;
86 case XlBordersIndex::xlInsideHorizontal
:
87 aTableBorder
.IsHorizontalLineValid
= sal_True
;
88 aTableBorder
.HorizontalLine
= rBorderLine
;
90 case XlBordersIndex::xlDiagonalDown
:
91 case XlBordersIndex::xlDiagonalUp
:
92 // #TODO have to ignore at the momement, would be
93 // nice to investigate what we can do here
98 m_xProps
->setPropertyValue( sTableBorder
, uno::makeAny(aTableBorder
) );
102 bool getBorderLine( table::BorderLine
& rBorderLine
)
104 table::TableBorder aTableBorder
;
105 m_xProps
->getPropertyValue( sTableBorder
) >>= aTableBorder
;
106 switch ( m_LineType
)
108 case XlBordersIndex::xlEdgeLeft
:
109 if ( aTableBorder
.IsLeftLineValid
)
110 rBorderLine
= aTableBorder
.LeftLine
;
112 case XlBordersIndex::xlEdgeTop
:
113 if ( aTableBorder
.IsTopLineValid
)
114 rBorderLine
= aTableBorder
.TopLine
;
117 case XlBordersIndex::xlEdgeBottom
:
118 if ( aTableBorder
.IsBottomLineValid
)
119 rBorderLine
= aTableBorder
.BottomLine
;
121 case XlBordersIndex::xlEdgeRight
:
122 if ( aTableBorder
.IsRightLineValid
)
123 rBorderLine
= aTableBorder
.RightLine
;
125 case XlBordersIndex::xlInsideVertical
:
126 if ( aTableBorder
.IsVerticalLineValid
)
127 rBorderLine
= aTableBorder
.VerticalLine
;
129 case XlBordersIndex::xlInsideHorizontal
:
130 if ( aTableBorder
.IsHorizontalLineValid
)
131 rBorderLine
= aTableBorder
.HorizontalLine
;
134 case XlBordersIndex::xlDiagonalDown
:
135 case XlBordersIndex::xlDiagonalUp
:
136 // #TODO have to ignore at the momement, would be
137 // nice to investigate what we can do here
146 virtual OUString
getServiceImplName() SAL_OVERRIDE
148 return OUString("ScVbaBorder");
150 virtual css::uno::Sequence
<OUString
> getServiceNames() SAL_OVERRIDE
152 static uno::Sequence
< OUString
> aServiceNames
;
153 if ( aServiceNames
.getLength() == 0 )
155 aServiceNames
.realloc( 1 );
156 aServiceNames
[ 0 ] = "ooo.vba.excel.Border";
158 return aServiceNames
;
161 ScVbaBorder( const uno::Reference
< beans::XPropertySet
> & xProps
, const uno::Reference
< uno::XComponentContext
>& xContext
, sal_Int32 lineType
, ScVbaPalette
& rPalette
) : ScVbaBorder_Base( uno::Reference
< XHelperInterface
>( xProps
, uno::UNO_QUERY
), xContext
), m_xProps( xProps
), m_LineType( lineType
), m_Palette( rPalette
) {}
164 uno::Any SAL_CALL
getColor() throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
166 table::BorderLine aBorderLine
;
167 if ( getBorderLine( aBorderLine
) )
168 return uno::makeAny( OORGBToXLRGB( aBorderLine
.Color
) );
169 throw uno::RuntimeException("No Implementation available" );
171 void SAL_CALL
setColor( const uno::Any
& _color
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
173 sal_Int32 nColor
= 0;
175 table::BorderLine aBorderLine
;
176 if ( getBorderLine( aBorderLine
) )
178 aBorderLine
.Color
= XLRGBToOORGB( nColor
);
179 setBorderLine( aBorderLine
);
182 throw uno::RuntimeException("No Implementation available" );
185 uno::Any SAL_CALL
getColorIndex() throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
187 sal_Int32 nColor
= 0;
188 XLRGBToOORGB( getColor() ) >>= nColor
;
189 uno::Reference
< container::XIndexAccess
> xIndex
= m_Palette
.getPalette();
190 sal_Int32 nElems
= xIndex
->getCount();
191 sal_Int32 nIndex
= -1;
192 for ( sal_Int32 count
=0; count
<nElems
; ++count
)
194 sal_Int32 nPaletteColor
= 0;
195 xIndex
->getByIndex( count
) >>= nPaletteColor
;
196 if ( nPaletteColor
== nColor
)
202 return uno::makeAny(nIndex
);
205 void SAL_CALL
setColorIndex( const uno::Any
& _colorindex
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
207 sal_Int32 nColor
= 0;
208 _colorindex
>>= nColor
;
209 if ( !nColor
|| nColor
== XlColorIndex::xlColorIndexAutomatic
)
211 setColor( OORGBToXLRGB( m_Palette
.getPalette()->getByIndex( --nColor
) ) );
213 uno::Any SAL_CALL
getWeight() throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
215 table::BorderLine aBorderLine
;
216 if ( getBorderLine( aBorderLine
) )
218 switch ( aBorderLine
.OuterLineWidth
)
220 case 0: // Thin = default OO thickness
222 return uno::makeAny( XlBorderWeight::xlThin
);
224 return uno::makeAny( XlBorderWeight::xlMedium
);
226 return uno::makeAny( XlBorderWeight::xlThick
);
228 return uno::makeAny( XlBorderWeight::xlHairline
);
233 throw uno::RuntimeException("Method failed" );
235 void SAL_CALL
setWeight( const uno::Any
& _weight
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
237 sal_Int32 nWeight
= 0;
239 table::BorderLine aBorderLine
;
240 if ( getBorderLine( aBorderLine
) )
244 case XlBorderWeight::xlThin
:
245 aBorderLine
.OuterLineWidth
= OOLineThin
;
247 case XlBorderWeight::xlMedium
:
248 aBorderLine
.OuterLineWidth
= OOLineMedium
;
250 case XlBorderWeight::xlThick
:
251 aBorderLine
.OuterLineWidth
= OOLineThick
;
253 case XlBorderWeight::xlHairline
:
254 aBorderLine
.OuterLineWidth
= OOLineHairline
;
257 throw uno::RuntimeException("Bad param" );
259 setBorderLine( aBorderLine
);
262 throw uno::RuntimeException("Method failed" );
265 uno::Any SAL_CALL
getLineStyle() throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
267 // always return xlContinuous;
268 return uno::makeAny( XlLineStyle::xlContinuous
);
270 void SAL_CALL
setLineStyle( const uno::Any
& _linestyle
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
272 // Urk no choice but to silently ignore we don't support this attribute
273 // #TODO would be nice to support the excel line styles
274 sal_Int32 nLineStyle
= 0;
275 _linestyle
>>= nLineStyle
;
276 table::BorderLine aBorderLine
;
277 if ( getBorderLine( aBorderLine
) )
279 switch ( nLineStyle
)
281 case XlLineStyle::xlContinuous
:
282 case XlLineStyle::xlDash
:
283 case XlLineStyle::xlDashDot
:
284 case XlLineStyle::xlDashDotDot
:
285 case XlLineStyle::xlDot
:
286 case XlLineStyle::xlDouble
:
287 case XlLineStyle::xlLineStyleNone
:
288 case XlLineStyle::xlSlantDashDot
:
291 throw uno::RuntimeException("Bad param" );
293 setBorderLine( aBorderLine
);
296 throw uno::RuntimeException("Method failed" );
300 class RangeBorders
: public RangeBorders_Base
303 uno::Reference
< table::XCellRange
> m_xRange
;
304 uno::Reference
< uno::XComponentContext
> m_xContext
;
305 ScVbaPalette m_Palette
;
306 sal_Int32
getTableIndex( sal_Int32 nConst
)
308 // hokay return position of the index in the table
309 sal_Int32 nIndexes
= getCount();
310 sal_Int32 realIndex
= 0;
311 const sal_Int16
* pTableEntry
= supportedIndexTable
;
312 for ( ; realIndex
< nIndexes
; ++realIndex
, ++pTableEntry
)
314 if ( *pTableEntry
== nConst
)
317 return getCount(); // error condition
320 RangeBorders( const uno::Reference
< table::XCellRange
>& xRange
, const uno::Reference
< uno::XComponentContext
> & xContext
, ScVbaPalette
& rPalette
) : m_xRange( xRange
), m_xContext( xContext
), m_Palette( rPalette
)
324 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
326 return sizeof( supportedIndexTable
) / sizeof( supportedIndexTable
[0] );
328 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
331 sal_Int32 nIndex
= getTableIndex( Index
);
332 if ( nIndex
>= 0 && nIndex
< getCount() )
334 uno::Reference
< beans::XPropertySet
> xProps( m_xRange
, uno::UNO_QUERY_THROW
);
335 return uno::makeAny( uno::Reference
< excel::XBorder
>( new ScVbaBorder( xProps
, m_xContext
, supportedIndexTable
[ nIndex
], m_Palette
)) );
337 throw lang::IndexOutOfBoundsException();
339 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
341 return cppu::UnoType
<excel::XBorder
>::get();
343 virtual sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
349 uno::Reference
< container::XIndexAccess
>
350 rangeToBorderIndexAccess( const uno::Reference
< table::XCellRange
>& xRange
, const uno::Reference
< uno::XComponentContext
> & xContext
, ScVbaPalette
& rPalette
)
352 return new RangeBorders( xRange
, xContext
, rPalette
);
355 class RangeBorderEnumWrapper
: public EnumerationHelper_BASE
357 uno::Reference
<container::XIndexAccess
> m_xIndexAccess
;
360 RangeBorderEnumWrapper( const uno::Reference
< container::XIndexAccess
>& xIndexAccess
) : m_xIndexAccess( xIndexAccess
), nIndex( 0 ) {}
361 virtual sal_Bool SAL_CALL
hasMoreElements( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
363 return ( nIndex
< m_xIndexAccess
->getCount() );
366 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
368 if ( nIndex
< m_xIndexAccess
->getCount() )
369 return m_xIndexAccess
->getByIndex( nIndex
++ );
370 throw container::NoSuchElementException();
374 ScVbaBorders::ScVbaBorders( const uno::Reference
< XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
> & xContext
, const uno::Reference
< table::XCellRange
>& xRange
, ScVbaPalette
& rPalette
): ScVbaBorders_BASE( xParent
, xContext
, rangeToBorderIndexAccess( xRange
,xContext
, rPalette
) ), bRangeIsSingleCell( false )
376 uno::Reference
< table::XColumnRowRange
> xColumnRowRange(xRange
, uno::UNO_QUERY_THROW
);
377 if ( xColumnRowRange
->getRows()->getCount() == 1 && xColumnRowRange
->getColumns()->getCount() == 1 )
378 bRangeIsSingleCell
= true;
379 m_xProps
.set( xRange
, uno::UNO_QUERY_THROW
);
382 uno::Reference
< container::XEnumeration
>
383 ScVbaBorders::createEnumeration() throw (uno::RuntimeException
)
385 return new RangeBorderEnumWrapper( m_xIndexAccess
);
389 ScVbaBorders::createCollectionObject( const css::uno::Any
& aSource
)
391 return aSource
; // its already a Border object
395 ScVbaBorders::getElementType() throw (uno::RuntimeException
)
397 return cppu::UnoType
<excel::XBorders
>::get();
401 ScVbaBorders::getItemByIntIndex( const sal_Int32 nIndex
) throw (uno::RuntimeException
)
403 return createCollectionObject( m_xIndexAccess
->getByIndex( nIndex
) );
406 uno::Any SAL_CALL
ScVbaBorders::getColor() throw (uno::RuntimeException
, std::exception
)
408 sal_Int32 count
= getCount();
410 for( sal_Int32 i
= 0; i
< count
; i
++ )
412 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
414 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
415 if( color
.hasValue() )
417 if( color
!= xBorder
->getColor() )
418 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
421 color
= xBorder
->getColor();
426 void SAL_CALL
ScVbaBorders::setColor( const uno::Any
& _color
) throw (uno::RuntimeException
, std::exception
)
428 sal_Int32 count
= getCount();
429 for( sal_Int32 i
= 0; i
< count
; i
++ )
431 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
432 xBorder
->setColor( _color
);
435 uno::Any SAL_CALL
ScVbaBorders::getColorIndex() throw (uno::RuntimeException
, std::exception
)
437 sal_Int32 count
= getCount();
438 uno::Any nColorIndex
;
439 for( sal_Int32 i
= 0; i
< count
; i
++ )
441 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
443 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
444 if( nColorIndex
.hasValue() )
446 if( nColorIndex
!= xBorder
->getColorIndex() )
447 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
450 nColorIndex
= xBorder
->getColorIndex();
455 void SAL_CALL
ScVbaBorders::setColorIndex( const uno::Any
& _colorindex
) throw (uno::RuntimeException
, std::exception
)
457 sal_Int32 count
= getCount();
458 for( sal_Int32 i
= 0; i
< count
; i
++ )
460 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
461 xBorder
->setColorIndex( _colorindex
);
466 lcl_areAllLineWidthsSame( const table::TableBorder
& maTableBorder
, bool bIsCell
)
472 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
473 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
474 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
478 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
479 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
480 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.HorizontalLine
.OuterLineWidth
) &&
481 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.VerticalLine
.OuterLineWidth
) &&
482 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
487 uno::Any SAL_CALL
ScVbaBorders::getLineStyle() throw (uno::RuntimeException
, std::exception
)
489 table::TableBorder maTableBorder
;
490 m_xProps
->getPropertyValue( sTableBorder
) >>= maTableBorder
;
492 sal_Int32 aLinestyle
= XlLineStyle::xlLineStyleNone
;
494 if ( lcl_areAllLineWidthsSame( maTableBorder
, bRangeIsSingleCell
))
496 if (maTableBorder
.TopLine
.LineDistance
!= 0)
498 aLinestyle
= XlLineStyle::xlDouble
;
500 else if ( maTableBorder
.TopLine
.OuterLineWidth
!= 0 )
502 aLinestyle
= XlLineStyle::xlContinuous
;
505 return uno::makeAny( aLinestyle
);
507 void SAL_CALL
ScVbaBorders::setLineStyle( const uno::Any
& _linestyle
) throw (uno::RuntimeException
, std::exception
)
509 sal_Int32 count
= getCount();
510 for( sal_Int32 i
= 0; i
< count
; i
++ )
512 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
513 xBorder
->setLineStyle( _linestyle
);
516 uno::Any SAL_CALL
ScVbaBorders::getWeight() throw (uno::RuntimeException
, std::exception
)
518 sal_Int32 count
= getCount();
520 for( sal_Int32 i
= 0; i
< count
; i
++ )
522 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
524 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
525 if( weight
.hasValue() )
527 if( weight
!= xBorder
->getWeight() )
528 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
531 weight
= xBorder
->getWeight();
536 void SAL_CALL
ScVbaBorders::setWeight( const uno::Any
& _weight
) throw (uno::RuntimeException
, std::exception
)
538 sal_Int32 count
= getCount();
539 for( sal_Int32 i
= 0; i
< count
; i
++ )
541 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
542 xBorder
->setWeight( _weight
);
547 ScVbaBorders::getServiceImplName()
549 return OUString("ScVbaBorders");
552 uno::Sequence
< OUString
>
553 ScVbaBorders::getServiceNames()
555 static uno::Sequence
< OUString
> aServiceNames
;
556 if ( aServiceNames
.getLength() == 0 )
558 aServiceNames
.realloc( 1 );
559 aServiceNames
[ 0 ] = "ooo.vba.excel.Borders";
561 return aServiceNames
;
564 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */