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
;
38 typedef ::cppu::WeakImplHelper1
<container::XIndexAccess
> RangeBorders_Base
;
39 typedef InheritedHelperInterfaceImpl1
<excel::XBorder
> ScVbaBorder_Base
;
41 // #TODO sort these indexes to match the order in which Excel iterates over the
42 // borders, the enumeration will match the order in this list
43 static const sal_Int16 supportedIndexTable
[] = { XlBordersIndex::xlEdgeLeft
, XlBordersIndex::xlEdgeTop
, XlBordersIndex::xlEdgeBottom
, XlBordersIndex::xlEdgeRight
, XlBordersIndex::xlDiagonalDown
, XlBordersIndex::xlDiagonalUp
, XlBordersIndex::xlInsideVertical
, XlBordersIndex::xlInsideHorizontal
};
45 const static OUString
sTableBorder("TableBorder");
47 // Equiv widths in in 1/100 mm
48 const static sal_Int32 OOLineThin
= 35;
49 const static sal_Int32 OOLineMedium
= 88;
50 const static sal_Int32 OOLineThick
= 141;
51 const static sal_Int32 OOLineHairline
= 2;
53 class ScVbaBorder
: public ScVbaBorder_Base
56 uno::Reference
< beans::XPropertySet
> m_xProps
;
58 ScVbaPalette m_Palette
;
59 bool setBorderLine( table::BorderLine
& rBorderLine
)
61 table::TableBorder aTableBorder
;
62 m_xProps
->getPropertyValue( sTableBorder
) >>= aTableBorder
;
66 case XlBordersIndex::xlEdgeLeft
:
67 aTableBorder
.IsLeftLineValid
= sal_True
;
68 aTableBorder
.LeftLine
= rBorderLine
;
70 case XlBordersIndex::xlEdgeTop
:
71 aTableBorder
.IsTopLineValid
= sal_True
;
72 aTableBorder
.TopLine
= rBorderLine
;
75 case XlBordersIndex::xlEdgeBottom
:
76 aTableBorder
.IsBottomLineValid
= sal_True
;
77 aTableBorder
.BottomLine
= rBorderLine
;
79 case XlBordersIndex::xlEdgeRight
:
80 aTableBorder
.IsRightLineValid
= sal_True
;
81 aTableBorder
.RightLine
= rBorderLine
;
83 case XlBordersIndex::xlInsideVertical
:
84 aTableBorder
.IsVerticalLineValid
= sal_True
;
85 aTableBorder
.VerticalLine
= rBorderLine
;
87 case XlBordersIndex::xlInsideHorizontal
:
88 aTableBorder
.IsHorizontalLineValid
= sal_True
;
89 aTableBorder
.HorizontalLine
= rBorderLine
;
91 case XlBordersIndex::xlDiagonalDown
:
92 case XlBordersIndex::xlDiagonalUp
:
93 // #TODO have to ignore at the momement, would be
94 // nice to investigate what we can do here
99 m_xProps
->setPropertyValue( sTableBorder
, uno::makeAny(aTableBorder
) );
103 bool getBorderLine( table::BorderLine
& rBorderLine
)
105 table::TableBorder aTableBorder
;
106 m_xProps
->getPropertyValue( sTableBorder
) >>= aTableBorder
;
107 switch ( m_LineType
)
109 case XlBordersIndex::xlEdgeLeft
:
110 if ( aTableBorder
.IsLeftLineValid
)
111 rBorderLine
= aTableBorder
.LeftLine
;
113 case XlBordersIndex::xlEdgeTop
:
114 if ( aTableBorder
.IsTopLineValid
)
115 rBorderLine
= aTableBorder
.TopLine
;
118 case XlBordersIndex::xlEdgeBottom
:
119 if ( aTableBorder
.IsBottomLineValid
)
120 rBorderLine
= aTableBorder
.BottomLine
;
122 case XlBordersIndex::xlEdgeRight
:
123 if ( aTableBorder
.IsRightLineValid
)
124 rBorderLine
= aTableBorder
.RightLine
;
126 case XlBordersIndex::xlInsideVertical
:
127 if ( aTableBorder
.IsVerticalLineValid
)
128 rBorderLine
= aTableBorder
.VerticalLine
;
130 case XlBordersIndex::xlInsideHorizontal
:
131 if ( aTableBorder
.IsHorizontalLineValid
)
132 rBorderLine
= aTableBorder
.HorizontalLine
;
135 case XlBordersIndex::xlDiagonalDown
:
136 case XlBordersIndex::xlDiagonalUp
:
137 // #TODO have to ignore at the momement, would be
138 // nice to investigate what we can do here
145 ScVbaBorder(); // no impl
147 virtual OUString
getServiceImplName()
149 return OUString("ScVbaBorder");
151 virtual css::uno::Sequence
<OUString
> getServiceNames()
153 static uno::Sequence
< OUString
> aServiceNames
;
154 if ( aServiceNames
.getLength() == 0 )
156 aServiceNames
.realloc( 1 );
157 aServiceNames
[ 0 ] = "ooo.vba.excel.Border";
159 return aServiceNames
;
162 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
) {}
165 uno::Any SAL_CALL
getColor() throw (uno::RuntimeException
)
167 table::BorderLine aBorderLine
;
168 if ( getBorderLine( aBorderLine
) )
169 return uno::makeAny( OORGBToXLRGB( aBorderLine
.Color
) );
170 throw uno::RuntimeException("No Implementation available", uno::Reference
< uno::XInterface
>() );
172 void SAL_CALL
setColor( const uno::Any
& _color
) throw (uno::RuntimeException
)
174 sal_Int32 nColor
= 0;
176 table::BorderLine aBorderLine
;
177 if ( getBorderLine( aBorderLine
) )
179 aBorderLine
.Color
= XLRGBToOORGB( nColor
);
180 setBorderLine( aBorderLine
);
183 throw uno::RuntimeException("No Implementation available", uno::Reference
< uno::XInterface
>() );
186 uno::Any SAL_CALL
getColorIndex() throw (uno::RuntimeException
)
188 sal_Int32 nColor
= 0;
189 XLRGBToOORGB( getColor() ) >>= nColor
;
190 uno::Reference
< container::XIndexAccess
> xIndex
= m_Palette
.getPalette();
191 sal_Int32 nElems
= xIndex
->getCount();
192 sal_Int32 nIndex
= -1;
193 for ( sal_Int32 count
=0; count
<nElems
; ++count
)
195 sal_Int32 nPaletteColor
= 0;
196 xIndex
->getByIndex( count
) >>= nPaletteColor
;
197 if ( nPaletteColor
== nColor
)
203 return uno::makeAny(nIndex
);
206 void SAL_CALL
setColorIndex( const uno::Any
& _colorindex
) throw (uno::RuntimeException
)
208 sal_Int32 nColor
= 0;
209 _colorindex
>>= nColor
;
210 if ( !nColor
|| nColor
== XlColorIndex::xlColorIndexAutomatic
)
212 setColor( OORGBToXLRGB( m_Palette
.getPalette()->getByIndex( --nColor
) ) );
214 uno::Any SAL_CALL
getWeight() throw (uno::RuntimeException
)
216 table::BorderLine aBorderLine
;
217 if ( getBorderLine( aBorderLine
) )
219 switch ( aBorderLine
.OuterLineWidth
)
221 case 0: // Thin = default OO thickness
223 return uno::makeAny( XlBorderWeight::xlThin
);
225 return uno::makeAny( XlBorderWeight::xlMedium
);
227 return uno::makeAny( XlBorderWeight::xlThick
);
229 return uno::makeAny( XlBorderWeight::xlHairline
);
234 throw uno::RuntimeException("Method failed", uno::Reference
< uno::XInterface
>() );
236 void SAL_CALL
setWeight( const uno::Any
& _weight
) throw (uno::RuntimeException
)
238 sal_Int32 nWeight
= 0;
240 table::BorderLine aBorderLine
;
241 if ( getBorderLine( aBorderLine
) )
245 case XlBorderWeight::xlThin
:
246 aBorderLine
.OuterLineWidth
= OOLineThin
;
248 case XlBorderWeight::xlMedium
:
249 aBorderLine
.OuterLineWidth
= OOLineMedium
;
251 case XlBorderWeight::xlThick
:
252 aBorderLine
.OuterLineWidth
= OOLineThick
;
254 case XlBorderWeight::xlHairline
:
255 aBorderLine
.OuterLineWidth
= OOLineHairline
;
258 throw uno::RuntimeException("Bad param", uno::Reference
< uno::XInterface
>() );
260 setBorderLine( aBorderLine
);
263 throw uno::RuntimeException("Method failed", uno::Reference
< uno::XInterface
>() );
266 uno::Any SAL_CALL
getLineStyle() throw (uno::RuntimeException
)
268 // always return xlContinuous;
269 return uno::makeAny( XlLineStyle::xlContinuous
);
271 void SAL_CALL
setLineStyle( const uno::Any
& _linestyle
) throw (uno::RuntimeException
)
273 // Urk no choice but to silently ignore we don't support this attribute
274 // #TODO would be nice to support the excel line styles
275 sal_Int32 nLineStyle
= 0;
276 _linestyle
>>= nLineStyle
;
277 table::BorderLine aBorderLine
;
278 if ( getBorderLine( aBorderLine
) )
280 switch ( nLineStyle
)
282 case XlLineStyle::xlContinuous
:
283 case XlLineStyle::xlDash
:
284 case XlLineStyle::xlDashDot
:
285 case XlLineStyle::xlDashDotDot
:
286 case XlLineStyle::xlDot
:
287 case XlLineStyle::xlDouble
:
288 case XlLineStyle::xlLineStyleNone
:
289 case XlLineStyle::xlSlantDashDot
:
292 throw uno::RuntimeException("Bad param", uno::Reference
< uno::XInterface
>() );
294 setBorderLine( aBorderLine
);
297 throw uno::RuntimeException("Method failed", uno::Reference
< uno::XInterface
>() );
301 class RangeBorders
: public RangeBorders_Base
304 uno::Reference
< table::XCellRange
> m_xRange
;
305 uno::Reference
< uno::XComponentContext
> m_xContext
;
306 ScVbaPalette m_Palette
;
307 sal_Int32
getTableIndex( sal_Int32 nConst
)
309 // hokay return position of the index in the table
310 sal_Int32 nIndexes
= getCount();
311 sal_Int32 realIndex
= 0;
312 const sal_Int16
* pTableEntry
= supportedIndexTable
;
313 for ( ; realIndex
< nIndexes
; ++realIndex
, ++pTableEntry
)
315 if ( *pTableEntry
== nConst
)
318 return getCount(); // error condition
321 RangeBorders( const uno::Reference
< table::XCellRange
>& xRange
, const uno::Reference
< uno::XComponentContext
> & xContext
, ScVbaPalette
& rPalette
) : m_xRange( xRange
), m_xContext( xContext
), m_Palette( rPalette
)
325 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
)
327 return sizeof( supportedIndexTable
) / sizeof( supportedIndexTable
[0] );
329 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
)
332 sal_Int32 nIndex
= getTableIndex( Index
);
333 if ( nIndex
>= 0 && nIndex
< getCount() )
335 uno::Reference
< beans::XPropertySet
> xProps( m_xRange
, uno::UNO_QUERY_THROW
);
336 return uno::makeAny( uno::Reference
< excel::XBorder
>( new ScVbaBorder( xProps
, m_xContext
, supportedIndexTable
[ nIndex
], m_Palette
)) );
338 throw lang::IndexOutOfBoundsException();
340 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
)
342 return excel::XBorder::static_type(0);
344 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
)
350 uno::Reference
< container::XIndexAccess
>
351 rangeToBorderIndexAccess( const uno::Reference
< table::XCellRange
>& xRange
, const uno::Reference
< uno::XComponentContext
> & xContext
, ScVbaPalette
& rPalette
)
353 return new RangeBorders( xRange
, xContext
, rPalette
);
356 class RangeBorderEnumWrapper
: public EnumerationHelper_BASE
358 uno::Reference
<container::XIndexAccess
> m_xIndexAccess
;
361 RangeBorderEnumWrapper( const uno::Reference
< container::XIndexAccess
>& xIndexAccess
) : m_xIndexAccess( xIndexAccess
), nIndex( 0 ) {}
362 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (uno::RuntimeException
)
364 return ( nIndex
< m_xIndexAccess
->getCount() );
367 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
369 if ( nIndex
< m_xIndexAccess
->getCount() )
370 return m_xIndexAccess
->getByIndex( nIndex
++ );
371 throw container::NoSuchElementException();
375 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 )
377 uno::Reference
< table::XColumnRowRange
> xColumnRowRange(xRange
, uno::UNO_QUERY_THROW
);
378 if ( xColumnRowRange
->getRows()->getCount() == 1 && xColumnRowRange
->getColumns()->getCount() == 1 )
379 bRangeIsSingleCell
= true;
380 m_xProps
.set( xRange
, uno::UNO_QUERY_THROW
);
383 uno::Reference
< container::XEnumeration
>
384 ScVbaBorders::createEnumeration() throw (uno::RuntimeException
)
386 return new RangeBorderEnumWrapper( m_xIndexAccess
);
390 ScVbaBorders::createCollectionObject( const css::uno::Any
& aSource
)
392 return aSource
; // its already a Border object
396 ScVbaBorders::getElementType() throw (uno::RuntimeException
)
398 return excel::XBorders::static_type(0);
402 ScVbaBorders::getItemByIntIndex( const sal_Int32 nIndex
) throw (uno::RuntimeException
)
404 return createCollectionObject( m_xIndexAccess
->getByIndex( nIndex
) );
408 uno::Any SAL_CALL
ScVbaBorders::getColor() throw (uno::RuntimeException
)
410 sal_Int32 count
= getCount();
412 for( sal_Int32 i
= 0; i
< count
; i
++ )
414 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
416 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
417 if( color
.hasValue() )
419 if( color
!= xBorder
->getColor() )
420 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
423 color
= xBorder
->getColor();
428 void SAL_CALL
ScVbaBorders::setColor( const uno::Any
& _color
) throw (uno::RuntimeException
)
430 sal_Int32 count
= getCount();
431 for( sal_Int32 i
= 0; i
< count
; i
++ )
433 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
434 xBorder
->setColor( _color
);
437 uno::Any SAL_CALL
ScVbaBorders::getColorIndex() throw (uno::RuntimeException
)
439 sal_Int32 count
= getCount();
440 uno::Any nColorIndex
;
441 for( sal_Int32 i
= 0; i
< count
; i
++ )
443 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
445 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
446 if( nColorIndex
.hasValue() )
448 if( nColorIndex
!= xBorder
->getColorIndex() )
449 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
452 nColorIndex
= xBorder
->getColorIndex();
457 void SAL_CALL
ScVbaBorders::setColorIndex( const uno::Any
& _colorindex
) throw (uno::RuntimeException
)
459 sal_Int32 count
= getCount();
460 for( sal_Int32 i
= 0; i
< count
; i
++ )
462 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
463 xBorder
->setColorIndex( _colorindex
);
468 lcl_areAllLineWidthsSame( const table::TableBorder
& maTableBorder
, bool bIsCell
)
474 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
475 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
476 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
480 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
481 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
482 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.HorizontalLine
.OuterLineWidth
) &&
483 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.VerticalLine
.OuterLineWidth
) &&
484 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
489 uno::Any SAL_CALL
ScVbaBorders::getLineStyle() throw (uno::RuntimeException
)
491 table::TableBorder maTableBorder
;
492 m_xProps
->getPropertyValue( sTableBorder
) >>= maTableBorder
;
494 sal_Int32 aLinestyle
= XlLineStyle::xlLineStyleNone
;
496 if ( lcl_areAllLineWidthsSame( maTableBorder
, bRangeIsSingleCell
))
498 if (maTableBorder
.TopLine
.LineDistance
!= 0)
500 aLinestyle
= XlLineStyle::xlDouble
;
502 else if ( maTableBorder
.TopLine
.OuterLineWidth
!= 0 )
504 aLinestyle
= XlLineStyle::xlContinuous
;
507 return uno::makeAny( aLinestyle
);
509 void SAL_CALL
ScVbaBorders::setLineStyle( const uno::Any
& _linestyle
) throw (uno::RuntimeException
)
511 sal_Int32 count
= getCount();
512 for( sal_Int32 i
= 0; i
< count
; i
++ )
514 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
515 xBorder
->setLineStyle( _linestyle
);
518 uno::Any SAL_CALL
ScVbaBorders::getWeight() throw (uno::RuntimeException
)
520 sal_Int32 count
= getCount();
522 for( sal_Int32 i
= 0; i
< count
; i
++ )
524 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
526 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
527 if( weight
.hasValue() )
529 if( weight
!= xBorder
->getWeight() )
530 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
533 weight
= xBorder
->getWeight();
538 void SAL_CALL
ScVbaBorders::setWeight( const uno::Any
& _weight
) throw (uno::RuntimeException
)
540 sal_Int32 count
= getCount();
541 for( sal_Int32 i
= 0; i
< count
; i
++ )
543 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
544 xBorder
->setWeight( _weight
);
550 ScVbaBorders::getServiceImplName()
552 return OUString("ScVbaBorders");
555 uno::Sequence
< OUString
>
556 ScVbaBorders::getServiceNames()
558 static uno::Sequence
< OUString
> aServiceNames
;
559 if ( aServiceNames
.getLength() == 0 )
561 aServiceNames
.realloc( 1 );
562 aServiceNames
[ 0 ] = "ooo.vba.excel.Borders";
564 return aServiceNames
;
567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */