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/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
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
;
65 case XlBordersIndex::xlEdgeLeft
:
66 aTableBorder
.IsLeftLineValid
= true;
67 aTableBorder
.LeftLine
= rBorderLine
;
69 case XlBordersIndex::xlEdgeTop
:
70 aTableBorder
.IsTopLineValid
= true;
71 aTableBorder
.TopLine
= rBorderLine
;
74 case XlBordersIndex::xlEdgeBottom
:
75 aTableBorder
.IsBottomLineValid
= true;
76 aTableBorder
.BottomLine
= rBorderLine
;
78 case XlBordersIndex::xlEdgeRight
:
79 aTableBorder
.IsRightLineValid
= true;
80 aTableBorder
.RightLine
= rBorderLine
;
82 case XlBordersIndex::xlInsideVertical
:
83 aTableBorder
.IsVerticalLineValid
= true;
84 aTableBorder
.VerticalLine
= rBorderLine
;
86 case XlBordersIndex::xlInsideHorizontal
:
87 aTableBorder
.IsHorizontalLineValid
= true;
88 aTableBorder
.HorizontalLine
= rBorderLine
;
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
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
;
111 case XlBordersIndex::xlEdgeTop
:
112 if ( aTableBorder
.IsTopLineValid
)
113 rBorderLine
= aTableBorder
.TopLine
;
116 case XlBordersIndex::xlEdgeBottom
:
117 if ( aTableBorder
.IsBottomLineValid
)
118 rBorderLine
= aTableBorder
.BottomLine
;
120 case XlBordersIndex::xlEdgeRight
:
121 if ( aTableBorder
.IsRightLineValid
)
122 rBorderLine
= aTableBorder
.RightLine
;
124 case XlBordersIndex::xlInsideVertical
:
125 if ( aTableBorder
.IsVerticalLineValid
)
126 rBorderLine
= aTableBorder
.VerticalLine
;
128 case XlBordersIndex::xlInsideHorizontal
:
129 if ( aTableBorder
.IsHorizontalLineValid
)
130 rBorderLine
= aTableBorder
.HorizontalLine
;
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
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
;
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
) {}
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;
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
)
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
)
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
218 return uno::makeAny( XlBorderWeight::xlThin
);
220 return uno::makeAny( XlBorderWeight::xlMedium
);
222 return uno::makeAny( XlBorderWeight::xlThick
);
224 return uno::makeAny( XlBorderWeight::xlHairline
);
229 throw uno::RuntimeException("Method failed" );
231 void SAL_CALL
setWeight( const uno::Any
& _weight
) override
233 sal_Int32 nWeight
= 0;
235 table::BorderLine aBorderLine
;
236 if ( !getBorderLine( aBorderLine
) )
237 throw uno::RuntimeException("Method failed" );
241 case XlBorderWeight::xlThin
:
242 aBorderLine
.OuterLineWidth
= OOLineThin
;
244 case XlBorderWeight::xlMedium
:
245 aBorderLine
.OuterLineWidth
= OOLineMedium
;
247 case XlBorderWeight::xlThick
:
248 aBorderLine
.OuterLineWidth
= OOLineThick
;
250 case XlBorderWeight::xlHairline
:
251 aBorderLine
.OuterLineWidth
= OOLineHairline
;
254 throw uno::RuntimeException("Bad param" );
256 setBorderLine( aBorderLine
);
260 void SAL_CALL
setTintAndShade( const uno::Any
& /*rAny*/ ) override
264 uno::Any SAL_CALL
getTintAndShade() override
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
:
297 throw uno::RuntimeException("Bad param" );
299 setBorderLine( aBorderLine
);
304 class RangeBorders
: public RangeBorders_Base
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
)
321 return getCount(); // error condition
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
)
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
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
;
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
);
397 ScVbaBorders::createCollectionObject( const css::uno::Any
& aSource
)
399 return aSource
; // it's already a Border object
403 ScVbaBorders::getElementType()
405 return cppu::UnoType
<excel::XBorders
>::get();
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();
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
>() );
429 color
= xBorder
->getColor();
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
>() );
458 nColorIndex
= xBorder
->getColorIndex();
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
);
474 lcl_areAllLineWidthsSame( const table::TableBorder
& maTableBorder
, bool bIsCell
)
480 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
481 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
482 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
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
));
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();
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
>() );
539 weight
= xBorder
->getWeight();
545 uno::Any SAL_CALL
ScVbaBorders::getTintAndShade()
548 return uno::makeAny(static_cast<double>(0));
551 void SAL_CALL
ScVbaBorders::setTintAndShade(const uno::Any
& /*rAny*/)
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
);
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: */