1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vbaborders.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include "vbaborders.hxx"
32 #include <cppuhelper/implbase3.hxx>
33 #include <ooo/vba/excel/XlBordersIndex.hpp>
34 #include <ooo/vba/excel/XlBorderWeight.hpp>
35 #include <ooo/vba/excel/XlLineStyle.hpp>
36 #include <ooo/vba/excel/XlColorIndex.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/table/TableBorder.hpp>
39 #include <com/sun/star/table/XColumnRowRange.hpp>
41 #include "vbapalette.hxx"
43 using namespace ::com::sun::star
;
44 using namespace ::ooo::vba
;
45 using namespace ::ooo::vba::excel
;
48 typedef ::cppu::WeakImplHelper1
<container::XIndexAccess
> RangeBorders_Base
;
49 typedef InheritedHelperInterfaceImpl1
<excel::XBorder
> ScVbaBorder_Base
;
51 // #TODO sort these indexes to match the order in which Excel iterates over the
52 // borders, the enumeration will match the order in this list
53 static const sal_Int16 supportedIndexTable
[] = { XlBordersIndex::xlEdgeLeft
, XlBordersIndex::xlEdgeTop
, XlBordersIndex::xlEdgeBottom
, XlBordersIndex::xlEdgeRight
, XlBordersIndex::xlDiagonalDown
, XlBordersIndex::xlDiagonalUp
, XlBordersIndex::xlInsideVertical
, XlBordersIndex::xlInsideHorizontal
};
55 const static rtl::OUString
sTableBorder( RTL_CONSTASCII_USTRINGPARAM("TableBorder") );
57 // Equiv widths in in 1/100 mm
58 const static sal_Int32 OOLineThin
= 35;
59 const static sal_Int32 OOLineMedium
= 88;
60 const static sal_Int32 OOLineThick
= 141;
61 const static sal_Int32 OOLineHairline
= 2;
63 class ScVbaBorder
: public ScVbaBorder_Base
66 uno::Reference
< beans::XPropertySet
> m_xProps
;
68 ScVbaPalette m_Palette
;
69 bool setBorderLine( table::BorderLine
& rBorderLine
)
71 table::TableBorder aTableBorder
;
72 m_xProps
->getPropertyValue( sTableBorder
) >>= aTableBorder
;
76 case XlBordersIndex::xlEdgeLeft
:
77 aTableBorder
.IsLeftLineValid
= sal_True
;
78 aTableBorder
.LeftLine
= rBorderLine
;
80 case XlBordersIndex::xlEdgeTop
:
81 aTableBorder
.IsTopLineValid
= sal_True
;
82 aTableBorder
.TopLine
= rBorderLine
;
85 case XlBordersIndex::xlEdgeBottom
:
86 aTableBorder
.IsBottomLineValid
= sal_True
;
87 aTableBorder
.BottomLine
= rBorderLine
;
89 case XlBordersIndex::xlEdgeRight
:
90 aTableBorder
.IsRightLineValid
= sal_True
;
91 aTableBorder
.RightLine
= rBorderLine
;
93 case XlBordersIndex::xlInsideVertical
:
94 aTableBorder
.IsVerticalLineValid
= sal_True
;
95 aTableBorder
.VerticalLine
= rBorderLine
;
97 case XlBordersIndex::xlInsideHorizontal
:
98 aTableBorder
.IsHorizontalLineValid
= sal_True
;
99 aTableBorder
.HorizontalLine
= rBorderLine
;
101 case XlBordersIndex::xlDiagonalDown
:
102 case XlBordersIndex::xlDiagonalUp
:
103 // #TODO have to ignore at the momement, would be
104 // nice to investigate what we can do here
109 m_xProps
->setPropertyValue( sTableBorder
, uno::makeAny(aTableBorder
) );
113 bool getBorderLine( table::BorderLine
& rBorderLine
)
115 table::TableBorder aTableBorder
;
116 m_xProps
->getPropertyValue( sTableBorder
) >>= aTableBorder
;
117 switch ( m_LineType
)
119 case XlBordersIndex::xlEdgeLeft
:
120 if ( aTableBorder
.IsLeftLineValid
)
121 rBorderLine
= aTableBorder
.LeftLine
;
123 case XlBordersIndex::xlEdgeTop
:
124 if ( aTableBorder
.IsTopLineValid
)
125 rBorderLine
= aTableBorder
.TopLine
;
128 case XlBordersIndex::xlEdgeBottom
:
129 if ( aTableBorder
.IsBottomLineValid
)
130 rBorderLine
= aTableBorder
.BottomLine
;
132 case XlBordersIndex::xlEdgeRight
:
133 if ( aTableBorder
.IsRightLineValid
)
134 rBorderLine
= aTableBorder
.RightLine
;
136 case XlBordersIndex::xlInsideVertical
:
137 if ( aTableBorder
.IsVerticalLineValid
)
138 rBorderLine
= aTableBorder
.VerticalLine
;
140 case XlBordersIndex::xlInsideHorizontal
:
141 if ( aTableBorder
.IsHorizontalLineValid
)
142 rBorderLine
= aTableBorder
.HorizontalLine
;
145 case XlBordersIndex::xlDiagonalDown
:
146 case XlBordersIndex::xlDiagonalUp
:
147 // #TODO have to ignore at the momement, would be
148 // nice to investigate what we can do here
155 ScVbaBorder(); // no impl
157 virtual rtl::OUString
& getServiceImplName()
159 static rtl::OUString
sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaBorder") );
162 virtual css::uno::Sequence
<rtl::OUString
> getServiceNames()
164 static uno::Sequence
< rtl::OUString
> aServiceNames
;
165 if ( aServiceNames
.getLength() == 0 )
167 aServiceNames
.realloc( 1 );
168 aServiceNames
[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Border" ) );
170 return aServiceNames
;
173 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
) {}
176 uno::Any SAL_CALL
getColor() throw (uno::RuntimeException
)
178 table::BorderLine aBorderLine
;
179 if ( getBorderLine( aBorderLine
) )
180 return uno::makeAny( OORGBToXLRGB( aBorderLine
.Color
) );
181 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "No Implementation available" ) ), uno::Reference
< uno::XInterface
>() );
183 void SAL_CALL
setColor( const uno::Any
& _color
) throw (uno::RuntimeException
)
185 sal_Int32 nColor
= 0;
187 table::BorderLine aBorderLine
;
188 if ( getBorderLine( aBorderLine
) )
190 aBorderLine
.Color
= XLRGBToOORGB( nColor
);
191 setBorderLine( aBorderLine
);
194 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "No Implementation available" ) ), uno::Reference
< uno::XInterface
>() );
197 uno::Any SAL_CALL
getColorIndex() throw (uno::RuntimeException
)
199 sal_Int32 nColor
= 0;
200 XLRGBToOORGB( getColor() ) >>= nColor
;
201 uno::Reference
< container::XIndexAccess
> xIndex
= m_Palette
.getPalette();
202 sal_Int32 nElems
= xIndex
->getCount();
203 sal_Int32 nIndex
= -1;
204 for ( sal_Int32 count
=0; count
<nElems
; ++count
)
206 sal_Int32 nPaletteColor
= 0;
207 xIndex
->getByIndex( count
) >>= nPaletteColor
;
208 if ( nPaletteColor
== nColor
)
214 return uno::makeAny(nIndex
);
217 void SAL_CALL
setColorIndex( const uno::Any
& _colorindex
) throw (uno::RuntimeException
)
219 sal_Int32 nColor
= 0;
220 _colorindex
>>= nColor
;
221 if ( !nColor
|| nColor
== XlColorIndex::xlColorIndexAutomatic
)
223 setColor( OORGBToXLRGB( m_Palette
.getPalette()->getByIndex( --nColor
) ) );
225 uno::Any SAL_CALL
getWeight() throw (uno::RuntimeException
)
227 table::BorderLine aBorderLine
;
228 if ( getBorderLine( aBorderLine
) )
230 switch ( aBorderLine
.OuterLineWidth
)
232 case 0: // Thin = default OO thickness
234 return uno::makeAny( XlBorderWeight::xlThin
);
236 return uno::makeAny( XlBorderWeight::xlMedium
);
238 return uno::makeAny( XlBorderWeight::xlThick
);
240 return uno::makeAny( XlBorderWeight::xlHairline
);
245 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Method failed" ) ), uno::Reference
< uno::XInterface
>() );
247 void SAL_CALL
setWeight( const uno::Any
& _weight
) throw (uno::RuntimeException
)
249 sal_Int32 nWeight
= 0;
251 table::BorderLine aBorderLine
;
252 if ( getBorderLine( aBorderLine
) )
256 case XlBorderWeight::xlThin
:
257 aBorderLine
.OuterLineWidth
= OOLineThin
;
259 case XlBorderWeight::xlMedium
:
260 aBorderLine
.OuterLineWidth
= OOLineMedium
;
262 case XlBorderWeight::xlThick
:
263 aBorderLine
.OuterLineWidth
= OOLineThick
;
265 case XlBorderWeight::xlHairline
:
266 aBorderLine
.OuterLineWidth
= OOLineHairline
;
269 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Bad param" ) ), uno::Reference
< uno::XInterface
>() );
271 setBorderLine( aBorderLine
);
274 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Method failed" ) ), uno::Reference
< uno::XInterface
>() );
277 uno::Any SAL_CALL
getLineStyle() throw (uno::RuntimeException
)
279 // always return xlContinuous;
280 return uno::makeAny( XlLineStyle::xlContinuous
);
282 void SAL_CALL
setLineStyle( const uno::Any
& _linestyle
) throw (uno::RuntimeException
)
284 // Urk no choice but to silently ignore we don't support this attribute
285 // #TODO would be nice to support the excel line styles
286 sal_Int32 nLineStyle
= 0;
287 _linestyle
>>= nLineStyle
;
288 table::BorderLine aBorderLine
;
289 if ( getBorderLine( aBorderLine
) )
291 switch ( nLineStyle
)
293 case XlLineStyle::xlContinuous
:
294 case XlLineStyle::xlDash
:
295 case XlLineStyle::xlDashDot
:
296 case XlLineStyle::xlDashDotDot
:
297 case XlLineStyle::xlDot
:
298 case XlLineStyle::xlDouble
:
299 case XlLineStyle::xlLineStyleNone
:
300 case XlLineStyle::xlSlantDashDot
:
303 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Bad param" ) ), uno::Reference
< uno::XInterface
>() );
305 setBorderLine( aBorderLine
);
308 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Method failed" ) ), uno::Reference
< uno::XInterface
>() );
312 class RangeBorders
: public RangeBorders_Base
315 uno::Reference
< table::XCellRange
> m_xRange
;
316 uno::Reference
< uno::XComponentContext
> m_xContext
;
317 ScVbaPalette m_Palette
;
318 sal_Int32
getTableIndex( sal_Int32 nConst
)
320 // hokay return position of the index in the table
321 sal_Int32 nIndexes
= getCount();
322 sal_Int32 realIndex
= 0;
323 const sal_Int16
* pTableEntry
= supportedIndexTable
;
324 for ( ; realIndex
< nIndexes
; ++realIndex
, ++pTableEntry
)
326 if ( *pTableEntry
== nConst
)
329 return getCount(); // error condition
332 RangeBorders( const uno::Reference
< table::XCellRange
>& xRange
, const uno::Reference
< uno::XComponentContext
> & xContext
, ScVbaPalette
& rPalette
) : m_xRange( xRange
), m_xContext( xContext
), m_Palette( rPalette
)
336 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
)
338 return sizeof( supportedIndexTable
) / sizeof( supportedIndexTable
[0] );
340 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
)
343 sal_Int32 nIndex
= getTableIndex( Index
);
344 if ( nIndex
>= 0 && nIndex
< getCount() )
346 uno::Reference
< beans::XPropertySet
> xProps( m_xRange
, uno::UNO_QUERY_THROW
);
347 return uno::makeAny( uno::Reference
< excel::XBorder
>( new ScVbaBorder( xProps
, m_xContext
, supportedIndexTable
[ nIndex
], m_Palette
)) );
349 throw lang::IndexOutOfBoundsException();
351 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
)
353 return excel::XBorder::static_type(0);
355 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
)
361 uno::Reference
< container::XIndexAccess
>
362 rangeToBorderIndexAccess( const uno::Reference
< table::XCellRange
>& xRange
, const uno::Reference
< uno::XComponentContext
> & xContext
, ScVbaPalette
& rPalette
)
364 return new RangeBorders( xRange
, xContext
, rPalette
);
367 class RangeBorderEnumWrapper
: public EnumerationHelper_BASE
369 uno::Reference
<container::XIndexAccess
> m_xIndexAccess
;
372 RangeBorderEnumWrapper( const uno::Reference
< container::XIndexAccess
>& xIndexAccess
) : m_xIndexAccess( xIndexAccess
), nIndex( 0 ) {}
373 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (uno::RuntimeException
)
375 return ( nIndex
< m_xIndexAccess
->getCount() );
378 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
380 if ( nIndex
< m_xIndexAccess
->getCount() )
381 return m_xIndexAccess
->getByIndex( nIndex
++ );
382 throw container::NoSuchElementException();
386 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 )
388 uno::Reference
< table::XColumnRowRange
> xColumnRowRange(xRange
, uno::UNO_QUERY_THROW
);
389 if ( xColumnRowRange
->getRows()->getCount() == 1 && xColumnRowRange
->getColumns()->getCount() == 1 )
390 bRangeIsSingleCell
= true;
391 m_xProps
.set( xRange
, uno::UNO_QUERY_THROW
);
394 uno::Reference
< container::XEnumeration
>
395 ScVbaBorders::createEnumeration() throw (uno::RuntimeException
)
397 return new RangeBorderEnumWrapper( m_xIndexAccess
);
401 ScVbaBorders::createCollectionObject( const css::uno::Any
& aSource
)
403 return aSource
; // its already a Border object
407 ScVbaBorders::getElementType() throw (uno::RuntimeException
)
409 return excel::XBorders::static_type(0);
413 ScVbaBorders::getItemByIntIndex( const sal_Int32 nIndex
) throw (uno::RuntimeException
)
415 return createCollectionObject( m_xIndexAccess
->getByIndex( nIndex
) );
419 uno::Any SAL_CALL
ScVbaBorders::getColor() throw (uno::RuntimeException
)
421 sal_Int32 count
= getCount();
423 for( sal_Int32 i
= 0; i
< count
; i
++ )
425 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
427 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
428 if( color
.hasValue() )
430 if( color
!= xBorder
->getColor() )
431 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
434 color
= xBorder
->getColor();
439 void SAL_CALL
ScVbaBorders::setColor( const uno::Any
& _color
) throw (uno::RuntimeException
)
441 sal_Int32 count
= getCount();
442 for( sal_Int32 i
= 0; i
< count
; i
++ )
444 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
445 xBorder
->setColor( _color
);
448 uno::Any SAL_CALL
ScVbaBorders::getColorIndex() throw (uno::RuntimeException
)
450 sal_Int32 count
= getCount();
451 uno::Any nColorIndex
;
452 for( sal_Int32 i
= 0; i
< count
; i
++ )
454 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
456 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
457 if( nColorIndex
.hasValue() )
459 if( nColorIndex
!= xBorder
->getColorIndex() )
460 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
463 nColorIndex
= xBorder
->getColorIndex();
468 void SAL_CALL
ScVbaBorders::setColorIndex( const uno::Any
& _colorindex
) throw (uno::RuntimeException
)
470 sal_Int32 count
= getCount();
471 for( sal_Int32 i
= 0; i
< count
; i
++ )
473 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
474 xBorder
->setColorIndex( _colorindex
);
479 lcl_areAllLineWidthsSame( const table::TableBorder
& maTableBorder
, bool bIsCell
)
485 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
486 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
487 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
491 bRes
= ((maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.BottomLine
.OuterLineWidth
) &&
492 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.LeftLine
.OuterLineWidth
) &&
493 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.HorizontalLine
.OuterLineWidth
) &&
494 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.VerticalLine
.OuterLineWidth
) &&
495 (maTableBorder
.TopLine
.OuterLineWidth
== maTableBorder
.RightLine
.OuterLineWidth
));
500 uno::Any SAL_CALL
ScVbaBorders::getLineStyle() throw (uno::RuntimeException
)
502 table::TableBorder maTableBorder
;
503 m_xProps
->getPropertyValue( sTableBorder
) >>= maTableBorder
;
505 sal_Int32 aLinestyle
= XlLineStyle::xlLineStyleNone
;
507 if ( lcl_areAllLineWidthsSame( maTableBorder
, bRangeIsSingleCell
))
509 if (maTableBorder
.TopLine
.LineDistance
!= 0)
511 aLinestyle
= XlLineStyle::xlDouble
;
513 else if ( maTableBorder
.TopLine
.OuterLineWidth
!= 0 )
515 aLinestyle
= XlLineStyle::xlContinuous
;
518 return uno::makeAny( aLinestyle
);
520 void SAL_CALL
ScVbaBorders::setLineStyle( const uno::Any
& _linestyle
) throw (uno::RuntimeException
)
522 sal_Int32 count
= getCount();
523 for( sal_Int32 i
= 0; i
< count
; i
++ )
525 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
526 xBorder
->setLineStyle( _linestyle
);
529 uno::Any SAL_CALL
ScVbaBorders::getWeight() throw (uno::RuntimeException
)
531 sal_Int32 count
= getCount();
533 for( sal_Int32 i
= 0; i
< count
; i
++ )
535 if( XlBordersIndex::xlDiagonalDown
!= supportedIndexTable
[i
] && XlBordersIndex::xlDiagonalUp
!= supportedIndexTable
[i
] )
537 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
538 if( weight
.hasValue() )
540 if( weight
!= xBorder
->getWeight() )
541 return uno::makeAny( uno::Reference
< uno::XInterface
>() );
544 weight
= xBorder
->getWeight();
549 void SAL_CALL
ScVbaBorders::setWeight( const uno::Any
& _weight
) throw (uno::RuntimeException
)
551 sal_Int32 count
= getCount();
552 for( sal_Int32 i
= 0; i
< count
; i
++ )
554 uno::Reference
< XBorder
> xBorder( getItemByIntIndex( supportedIndexTable
[i
] ), uno::UNO_QUERY_THROW
);
555 xBorder
->setWeight( _weight
);
561 ScVbaBorders::getServiceImplName()
563 static rtl::OUString
sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaBorders") );
567 uno::Sequence
< rtl::OUString
>
568 ScVbaBorders::getServiceNames()
570 static uno::Sequence
< rtl::OUString
> aServiceNames
;
571 if ( aServiceNames
.getLength() == 0 )
573 aServiceNames
.realloc( 1 );
574 aServiceNames
[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Borders" ) );
576 return aServiceNames
;