tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / vba / vbaborders.cxx
blobb57c2abd35c0f8ba483fdf34da3eeab90f5cb4f0
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/XCellRange.hpp>
30 #include <com/sun/star/table/XColumnRowRange.hpp>
31 #include <utility>
33 #include "vbapalette.hxx"
35 using namespace ::com::sun::star;
36 using namespace ::ooo::vba;
37 using namespace ::ooo::vba::excel;
39 typedef ::cppu::WeakImplHelper<container::XIndexAccess > RangeBorders_Base;
40 typedef InheritedHelperInterfaceWeakImpl<excel::XBorder > ScVbaBorder_Base;
42 // #TODO sort these indexes to match the order in which Excel iterates over the
43 // borders, the enumeration will match the order in this list
44 const sal_Int16 supportedIndexTable[] = { XlBordersIndex::xlEdgeLeft, XlBordersIndex::xlEdgeTop, XlBordersIndex::xlEdgeBottom, XlBordersIndex::xlEdgeRight, XlBordersIndex::xlDiagonalDown, XlBordersIndex::xlDiagonalUp, XlBordersIndex::xlInsideVertical, XlBordersIndex::xlInsideHorizontal };
46 constexpr OUString sTableBorder = u"TableBorder"_ustr;
48 // Equiv widths in 1/100 mm
49 const sal_Int32 OOLineThin = 26;
50 const sal_Int32 OOLineMedium = 88;
51 const sal_Int32 OOLineThick = 141;
52 const sal_Int32 OOLineHairline = 2;
54 namespace {
56 class ScVbaBorder : public ScVbaBorder_Base
58 private:
59 uno::Reference< beans::XPropertySet > m_xProps;
60 sal_Int32 m_LineType;
61 ScVbaPalette m_Palette;
62 void setBorderLine( const table::BorderLine& rBorderLine )
64 table::TableBorder aTableBorder;
65 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
67 switch ( m_LineType )
69 case XlBordersIndex::xlEdgeLeft:
70 aTableBorder.IsLeftLineValid = true;
71 aTableBorder.LeftLine= rBorderLine;
72 break;
73 case XlBordersIndex::xlEdgeTop:
74 aTableBorder.IsTopLineValid = true;
75 aTableBorder.TopLine = rBorderLine;
76 break;
78 case XlBordersIndex::xlEdgeBottom:
79 aTableBorder.IsBottomLineValid = true;
80 aTableBorder.BottomLine = rBorderLine;
81 break;
82 case XlBordersIndex::xlEdgeRight:
83 aTableBorder.IsRightLineValid = true;
84 aTableBorder.RightLine = rBorderLine;
85 break;
86 case XlBordersIndex::xlInsideVertical:
87 aTableBorder.IsVerticalLineValid = true;
88 aTableBorder.VerticalLine = rBorderLine;
89 break;
90 case XlBordersIndex::xlInsideHorizontal:
91 aTableBorder.IsHorizontalLineValid = true;
92 aTableBorder.HorizontalLine = rBorderLine;
93 break;
94 case XlBordersIndex::xlDiagonalDown:
95 case XlBordersIndex::xlDiagonalUp:
96 // #TODO have to ignore at the moment, would be
97 // nice to investigate what we can do here
98 break;
99 default:
100 return;
102 m_xProps->setPropertyValue( sTableBorder, uno::Any(aTableBorder) );
105 bool getBorderLine( table::BorderLine& rBorderLine )
107 table::TableBorder aTableBorder;
108 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
109 switch ( m_LineType )
111 case XlBordersIndex::xlEdgeLeft:
112 if ( aTableBorder.IsLeftLineValid )
113 rBorderLine = aTableBorder.LeftLine;
114 break;
115 case XlBordersIndex::xlEdgeTop:
116 if ( aTableBorder.IsTopLineValid )
117 rBorderLine = aTableBorder.TopLine;
118 break;
120 case XlBordersIndex::xlEdgeBottom:
121 if ( aTableBorder.IsBottomLineValid )
122 rBorderLine = aTableBorder.BottomLine;
123 break;
124 case XlBordersIndex::xlEdgeRight:
125 if ( aTableBorder.IsRightLineValid )
126 rBorderLine = aTableBorder.RightLine;
127 break;
128 case XlBordersIndex::xlInsideVertical:
129 if ( aTableBorder.IsVerticalLineValid )
130 rBorderLine = aTableBorder.VerticalLine;
131 break;
132 case XlBordersIndex::xlInsideHorizontal:
133 if ( aTableBorder.IsHorizontalLineValid )
134 rBorderLine = aTableBorder.HorizontalLine;
135 break;
137 case XlBordersIndex::xlDiagonalDown:
138 case XlBordersIndex::xlDiagonalUp:
139 // #TODO have to ignore at the moment, would be
140 // nice to investigate what we can do here
141 break;
142 default:
143 return false;
145 return true;
148 protected:
149 virtual OUString getServiceImplName() override
151 return u"ScVbaBorder"_ustr;
153 virtual css::uno::Sequence<OUString> getServiceNames() override
155 static uno::Sequence< OUString > const aServiceNames
157 u"ooo.vba.excel.Border"_ustr
159 return aServiceNames;
161 public:
162 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 ) {}
164 // XBorder
165 uno::Any SAL_CALL getColor() override
167 table::BorderLine aBorderLine;
168 if ( getBorderLine( aBorderLine ) )
169 return uno::Any( OORGBToXLRGB( Color(ColorTransparency, aBorderLine.Color) ) );
170 throw uno::RuntimeException(u"No Implementation available"_ustr );
172 void SAL_CALL setColor( const uno::Any& _color ) override
174 sal_Int32 nColor = 0;
175 _color >>= nColor;
176 table::BorderLine aBorderLine;
177 if ( !getBorderLine( aBorderLine ) )
178 throw uno::RuntimeException(u"No Implementation available"_ustr );
180 aBorderLine.Color = XLRGBToOORGB( nColor );
181 setBorderLine( aBorderLine );
185 uno::Any SAL_CALL getColorIndex() 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 )
198 nIndex = count + 1;
199 break;
202 return uno::Any(nIndex);
205 void SAL_CALL setColorIndex( const uno::Any& _colorindex ) override
207 sal_Int32 nColor = 0;
208 _colorindex >>= nColor;
209 if ( !nColor || nColor == XlColorIndex::xlColorIndexAutomatic )
210 nColor = 1;
211 setColor( OORGBToXLRGB( m_Palette.getPalette()->getByIndex( --nColor ) ) );
213 uno::Any SAL_CALL getWeight() override
215 table::BorderLine aBorderLine;
216 if ( getBorderLine( aBorderLine ) )
218 switch ( aBorderLine.OuterLineWidth )
220 case 0: // Thin = default OO thickness
221 case OOLineThin:
222 return uno::Any( XlBorderWeight::xlThin );
223 case OOLineMedium:
224 return uno::Any( XlBorderWeight::xlMedium );
225 case OOLineThick:
226 return uno::Any( XlBorderWeight::xlThick );
227 case OOLineHairline:
228 return uno::Any( XlBorderWeight::xlHairline );
229 default:
230 break;
233 throw uno::RuntimeException(u"Method failed"_ustr );
235 void SAL_CALL setWeight( const uno::Any& _weight ) override
237 sal_Int32 nWeight = 0;
238 _weight >>= nWeight;
239 table::BorderLine aBorderLine;
240 if ( !getBorderLine( aBorderLine ) )
241 throw uno::RuntimeException(u"Method failed"_ustr );
243 switch ( nWeight )
245 case XlBorderWeight::xlThin:
246 aBorderLine.OuterLineWidth = OOLineThin;
247 break;
248 case XlBorderWeight::xlMedium:
249 aBorderLine.OuterLineWidth = OOLineMedium;
250 break;
251 case XlBorderWeight::xlThick:
252 aBorderLine.OuterLineWidth = OOLineThick;
253 break;
254 case XlBorderWeight::xlHairline:
255 aBorderLine.OuterLineWidth = OOLineHairline;
256 break;
257 default:
258 throw uno::RuntimeException(u"Bad param"_ustr );
260 setBorderLine( aBorderLine );
264 void SAL_CALL setTintAndShade( const uno::Any& /*rAny*/ ) override
266 // TODO implement
268 uno::Any SAL_CALL getTintAndShade() override
270 // TODO implement
271 return uno::Any(static_cast<double>(0));
274 uno::Any SAL_CALL getLineStyle() override
276 // always return xlContinuous;
277 return uno::Any( XlLineStyle::xlContinuous );
279 void SAL_CALL setLineStyle( const uno::Any& _linestyle ) override
281 // Urk no choice but to silently ignore we don't support this attribute
282 // #TODO would be nice to support the excel line styles
283 sal_Int32 nLineStyle = 0;
284 _linestyle >>= nLineStyle;
285 table::BorderLine aBorderLine;
286 if ( !getBorderLine( aBorderLine ) )
287 throw uno::RuntimeException(u"Method failed"_ustr );
289 switch ( nLineStyle )
291 case XlLineStyle::xlContinuous:
292 case XlLineStyle::xlDash:
293 case XlLineStyle::xlDashDot:
294 case XlLineStyle::xlDashDotDot:
295 case XlLineStyle::xlDot:
296 case XlLineStyle::xlDouble:
297 case XlLineStyle::xlLineStyleNone:
298 case XlLineStyle::xlSlantDashDot:
299 break;
300 default:
301 throw uno::RuntimeException(u"Bad param"_ustr );
303 setBorderLine( aBorderLine );
308 class RangeBorders : public RangeBorders_Base
310 private:
311 uno::Reference< table::XCellRange > m_xRange;
312 uno::Reference< uno::XComponentContext > m_xContext;
313 ScVbaPalette m_Palette;
314 sal_Int32 getTableIndex( sal_Int32 nConst )
316 // okay return position of the index in the table
317 sal_Int32 nIndexes = getCount();
318 sal_Int32 realIndex = 0;
319 const sal_Int16* pTableEntry = supportedIndexTable;
320 for ( ; realIndex < nIndexes; ++realIndex, ++pTableEntry )
322 if ( *pTableEntry == nConst )
323 return realIndex;
325 return getCount(); // error condition
327 public:
328 RangeBorders( uno::Reference< table::XCellRange > xRange, uno::Reference< uno::XComponentContext > xContext, const ScVbaPalette& rPalette ) : m_xRange(std::move( xRange )), m_xContext(std::move( xContext )), m_Palette( rPalette )
331 // XIndexAccess
332 virtual ::sal_Int32 SAL_CALL getCount( ) override
334 return SAL_N_ELEMENTS( supportedIndexTable );
336 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
339 sal_Int32 nIndex = getTableIndex( Index );
340 if ( nIndex >= 0 && nIndex < getCount() )
342 uno::Reference< beans::XPropertySet > xProps( m_xRange, uno::UNO_QUERY_THROW );
343 return uno::Any( uno::Reference< excel::XBorder >( new ScVbaBorder( xProps, m_xContext, supportedIndexTable[ nIndex ], m_Palette )) );
345 throw lang::IndexOutOfBoundsException();
347 virtual uno::Type SAL_CALL getElementType( ) override
349 return cppu::UnoType<excel::XBorder>::get();
351 virtual sal_Bool SAL_CALL hasElements( ) override
353 return true;
359 static uno::Reference< container::XIndexAccess >
360 rangeToBorderIndexAccess( const uno::Reference< table::XCellRange >& xRange, const uno::Reference< uno::XComponentContext > & xContext, const ScVbaPalette& rPalette )
362 return new RangeBorders( xRange, xContext, rPalette );
365 namespace {
367 class RangeBorderEnumWrapper : public EnumerationHelper_BASE
369 uno::Reference<container::XIndexAccess > m_xIndexAccess;
370 sal_Int32 m_nIndex;
371 public:
372 explicit RangeBorderEnumWrapper( uno::Reference< container::XIndexAccess > xIndexAccess ) : m_xIndexAccess(std::move( xIndexAccess )), m_nIndex( 0 ) {}
373 virtual sal_Bool SAL_CALL hasMoreElements( ) override
375 return ( m_nIndex < m_xIndexAccess->getCount() );
378 virtual uno::Any SAL_CALL nextElement( ) override
380 if ( m_nIndex < m_xIndexAccess->getCount() )
381 return m_xIndexAccess->getByIndex( m_nIndex++ );
382 throw container::NoSuchElementException();
388 ScVbaBorders::ScVbaBorders( const uno::Reference< XHelperInterface >& xParent,
389 const uno::Reference< uno::XComponentContext > & xContext,
390 const uno::Reference< table::XCellRange >& xRange,
391 const ScVbaPalette& rPalette )
392 : ScVbaBorders_BASE( xParent, xContext, rangeToBorderIndexAccess( xRange ,xContext, rPalette ) ), bRangeIsSingleCell( false )
394 uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, uno::UNO_QUERY_THROW );
395 if ( xColumnRowRange->getRows()->getCount() == 1 && xColumnRowRange->getColumns()->getCount() == 1 )
396 bRangeIsSingleCell = true;
397 m_xProps.set( xRange, uno::UNO_QUERY_THROW );
400 uno::Reference< container::XEnumeration >
401 ScVbaBorders::createEnumeration()
403 return new RangeBorderEnumWrapper( m_xIndexAccess );
406 uno::Any
407 ScVbaBorders::createCollectionObject( const css::uno::Any& aSource )
409 return aSource; // it's already a Border object
412 uno::Type
413 ScVbaBorders::getElementType()
415 return cppu::UnoType<excel::XBorders>::get();
418 uno::Any
419 ScVbaBorders::getItemByIntIndex( const sal_Int32 nIndex )
421 return createCollectionObject( m_xIndexAccess->getByIndex( nIndex ) );
424 uno::Any SAL_CALL ScVbaBorders::getColor()
426 sal_Int32 count = getCount();
427 uno::Any color;
428 for( sal_Int32 i = 0; i < count ; i++ )
430 if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
432 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
433 if( color.hasValue() )
435 if( color != xBorder->getColor() )
436 return uno::Any( uno::Reference< uno::XInterface >() );
438 else
439 color = xBorder->getColor();
442 return color;
444 void SAL_CALL ScVbaBorders::setColor( const uno::Any& _color )
446 sal_Int32 count = getCount();
447 for( sal_Int32 i = 0; i < count ; i++ )
449 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
450 xBorder->setColor( _color );
453 uno::Any SAL_CALL ScVbaBorders::getColorIndex()
455 sal_Int32 count = getCount();
456 uno::Any nColorIndex;
457 for( sal_Int32 i = 0; i < count ; i++ )
459 if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
461 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
462 if( nColorIndex.hasValue() )
464 if( nColorIndex != xBorder->getColorIndex() )
465 return uno::Any( uno::Reference< uno::XInterface >() );
467 else
468 nColorIndex = xBorder->getColorIndex();
471 return nColorIndex;
473 void SAL_CALL ScVbaBorders::setColorIndex( const uno::Any& _colorindex )
475 sal_Int32 count = getCount();
476 for( sal_Int32 i = 0; i < count ; i++ )
478 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
479 xBorder->setColorIndex( _colorindex );
483 static bool
484 lcl_areAllLineWidthsSame( const table::TableBorder& maTableBorder, bool bIsCell )
487 bool bRes = false;
488 if (bIsCell)
490 bRes = ((maTableBorder.TopLine.OuterLineWidth == maTableBorder.BottomLine.OuterLineWidth) &&
491 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.LeftLine.OuterLineWidth) &&
492 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.RightLine.OuterLineWidth));
494 else
496 bRes = ((maTableBorder.TopLine.OuterLineWidth == maTableBorder.BottomLine.OuterLineWidth) &&
497 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.LeftLine.OuterLineWidth) &&
498 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.HorizontalLine.OuterLineWidth) &&
499 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.VerticalLine.OuterLineWidth) &&
500 (maTableBorder.TopLine.OuterLineWidth == maTableBorder.RightLine.OuterLineWidth));
502 return bRes;
505 uno::Any SAL_CALL ScVbaBorders::getLineStyle()
507 table::TableBorder aTableBorder;
508 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
510 sal_Int32 aLinestyle = XlLineStyle::xlLineStyleNone;
512 if ( lcl_areAllLineWidthsSame( aTableBorder, bRangeIsSingleCell ))
514 if (aTableBorder.TopLine.LineDistance != 0)
516 aLinestyle = XlLineStyle::xlDouble;
518 else if ( aTableBorder.TopLine.OuterLineWidth != 0 )
520 aLinestyle = XlLineStyle::xlContinuous;
523 return uno::Any( aLinestyle );
525 void SAL_CALL ScVbaBorders::setLineStyle( const uno::Any& _linestyle )
527 sal_Int32 count = getCount();
528 for( sal_Int32 i = 0; i < count ; i++ )
530 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
531 xBorder->setLineStyle( _linestyle );
534 uno::Any SAL_CALL ScVbaBorders::getWeight()
536 sal_Int32 count = getCount();
537 uno::Any weight;
538 for( sal_Int32 i = 0; i < count ; i++ )
540 if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
542 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
543 if( weight.hasValue() )
545 if( weight != xBorder->getWeight() )
546 return uno::Any( uno::Reference< uno::XInterface >() );
548 else
549 weight = xBorder->getWeight();
552 return weight;
555 uno::Any SAL_CALL ScVbaBorders::getTintAndShade()
557 // TODO implement
558 return uno::Any(static_cast<double>(0));
561 void SAL_CALL ScVbaBorders::setTintAndShade(const uno::Any& /*rAny*/)
563 // TODO implement
566 void SAL_CALL ScVbaBorders::setWeight( const uno::Any& _weight )
568 sal_Int32 count = getCount();
569 for( sal_Int32 i = 0; i < count ; i++ )
571 uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
572 xBorder->setWeight( _weight );
576 OUString
577 ScVbaBorders::getServiceImplName()
579 return u"ScVbaBorders"_ustr;
582 uno::Sequence< OUString >
583 ScVbaBorders::getServiceNames()
585 static uno::Sequence< OUString > const aServiceNames
587 u"ooo.vba.excel.Borders"_ustr
589 return aServiceNames;
592 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */