1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include "vbaborders.hxx" 28 #include <ooo/vba/word/XBorder.hpp> 29 #include <ooo/vba/word/WdBorderType.hpp> 30 #include <ooo/vba/word/WdLineStyle.hpp> 31 #include <cppuhelper/implbase3.hxx> 32 #include <com/sun/star/beans/XPropertySet.hpp> 33 #include <com/sun/star/table/TableBorder.hpp> 34 #include <com/sun/star/table/ShadowFormat.hpp> 35 #include <com/sun/star/table/ShadowLocation.hpp> 36 #include "vbapalette.hxx" 37 38 using namespace ::com::sun::star; 39 using namespace ::ooo::vba; 40 41 42 typedef ::cppu::WeakImplHelper1<container::XIndexAccess > RangeBorders_Base; 43 typedef InheritedHelperInterfaceImpl1<word::XBorder > SwVbaBorder_Base; 44 45 // #TODO sort these indexes to match the order in which Word iterates over the 46 // borders, the enumeration will match the order in this list 47 static const sal_Int16 supportedIndexTable[] = { word::WdBorderType::wdBorderBottom, word::WdBorderType::wdBorderDiagonalDown, word::WdBorderType::wdBorderDiagonalUp, word::WdBorderType::wdBorderHorizontal, word::WdBorderType::wdBorderLeft, word::WdBorderType::wdBorderRight, word::WdBorderType::wdBorderTop, word::WdBorderType::wdBorderVertical }; 48 49 const static rtl::OUString sTableBorder( RTL_CONSTASCII_USTRINGPARAM("TableBorder") ); 50 51 // Equiv widths in in 1/100 mm 52 const static sal_Int32 OOLineThin = 35; 53 const static sal_Int32 OOLineMedium = 88; 54 const static sal_Int32 OOLineThick = 141; 55 const static sal_Int32 OOLineHairline = 2; 56 57 class SwVbaBorder : public SwVbaBorder_Base 58 { 59 private: 60 uno::Reference< beans::XPropertySet > m_xProps; 61 sal_Int32 m_LineType; 62 VbaPalette m_Palette; 63 bool setBorderLine( table::BorderLine& rBorderLine ) 64 { 65 table::TableBorder aTableBorder; 66 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder; 67 68 switch ( m_LineType ) 69 { 70 case word::WdBorderType::wdBorderLeft: 71 aTableBorder.IsLeftLineValid = sal_True; 72 aTableBorder.LeftLine= rBorderLine; 73 break; 74 case word::WdBorderType::wdBorderTop: 75 aTableBorder.IsTopLineValid = sal_True; 76 aTableBorder.TopLine = rBorderLine; 77 break; 78 79 case word::WdBorderType::wdBorderBottom: 80 aTableBorder.IsBottomLineValid = sal_True; 81 aTableBorder.BottomLine = rBorderLine; 82 break; 83 case word::WdBorderType::wdBorderRight: 84 aTableBorder.IsRightLineValid = sal_True; 85 aTableBorder.RightLine = rBorderLine; 86 break; 87 case word::WdBorderType::wdBorderVertical: 88 aTableBorder.IsVerticalLineValid = sal_True; 89 aTableBorder.VerticalLine = rBorderLine; 90 break; 91 case word::WdBorderType::wdBorderHorizontal: 92 aTableBorder.IsHorizontalLineValid = sal_True; 93 aTableBorder.HorizontalLine = rBorderLine; 94 break; 95 case word::WdBorderType::wdBorderDiagonalDown: 96 case word::WdBorderType::wdBorderDiagonalUp: 97 // #TODO have to ignore at the momement, would be 98 // nice to investigate what we can do here 99 break; 100 default: 101 return false; 102 } 103 m_xProps->setPropertyValue( sTableBorder, uno::makeAny(aTableBorder) ); 104 return true; 105 } 106 107 bool getBorderLine( table::BorderLine& rBorderLine ) 108 { 109 table::TableBorder aTableBorder; 110 m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder; 111 switch ( m_LineType ) 112 { 113 case word::WdBorderType::wdBorderLeft: 114 if ( aTableBorder.IsLeftLineValid ) 115 rBorderLine = aTableBorder.LeftLine; 116 break; 117 case word::WdBorderType::wdBorderTop: 118 if ( aTableBorder.IsTopLineValid ) 119 rBorderLine = aTableBorder.TopLine; 120 break; 121 case word::WdBorderType::wdBorderBottom: 122 if ( aTableBorder.IsBottomLineValid ) 123 rBorderLine = aTableBorder.BottomLine; 124 break; 125 case word::WdBorderType::wdBorderRight: 126 if ( aTableBorder.IsRightLineValid ) 127 rBorderLine = aTableBorder.RightLine; 128 break; 129 case word::WdBorderType::wdBorderVertical: 130 if ( aTableBorder.IsVerticalLineValid ) 131 rBorderLine = aTableBorder.VerticalLine; 132 break; 133 case word::WdBorderType::wdBorderHorizontal: 134 if ( aTableBorder.IsHorizontalLineValid ) 135 rBorderLine = aTableBorder.HorizontalLine; 136 break; 137 138 case word::WdBorderType::wdBorderDiagonalDown: 139 case word::WdBorderType::wdBorderDiagonalUp: 140 // #TODO have to ignore at the momement, would be 141 // nice to investigate what we can do here 142 break; 143 default: 144 return false; 145 } 146 return true; 147 } 148 SwVbaBorder(); // no impl 149 protected: 150 virtual rtl::OUString& getServiceImplName() 151 { 152 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaBorder") ); 153 return sImplName; 154 } 155 virtual css::uno::Sequence<rtl::OUString> getServiceNames() 156 { 157 static uno::Sequence< rtl::OUString > aServiceNames; 158 if ( aServiceNames.getLength() == 0 ) 159 { 160 aServiceNames.realloc( 1 ); 161 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Border" ) ); 162 } 163 return aServiceNames; 164 } 165 public: 166 SwVbaBorder( const uno::Reference< beans::XPropertySet > & xProps, const uno::Reference< uno::XComponentContext >& xContext, sal_Int32 lineType, VbaPalette& rPalette) : SwVbaBorder_Base( uno::Reference< XHelperInterface >( xProps, uno::UNO_QUERY ), xContext ), m_xProps( xProps ), m_LineType( lineType ), m_Palette( rPalette ) {} 167 168 uno::Any SAL_CALL getLineStyle() throw (uno::RuntimeException) 169 { 170 sal_Int32 nLineStyle = word::WdLineStyle::wdLineStyleNone; 171 table::BorderLine aBorderLine; 172 if ( getBorderLine( aBorderLine ) ) 173 { 174 if( aBorderLine.InnerLineWidth !=0 && aBorderLine.OuterLineWidth !=0 ) 175 { 176 nLineStyle = word::WdLineStyle::wdLineStyleDouble; 177 } 178 else if( aBorderLine.InnerLineWidth !=0 || aBorderLine.OuterLineWidth !=0 ) 179 { 180 nLineStyle = word::WdLineStyle::wdLineStyleSingle; 181 } 182 else 183 { 184 nLineStyle = word::WdLineStyle::wdLineStyleNone; 185 } 186 } 187 return uno::makeAny( nLineStyle ); 188 } 189 void SAL_CALL setLineStyle( const uno::Any& _linestyle ) throw (uno::RuntimeException) 190 { 191 // Urk no choice but to silently ignore we don't support this attribute 192 // #TODO would be nice to support the word line styles 193 sal_Int32 nLineStyle = 0; 194 _linestyle >>= nLineStyle; 195 table::BorderLine aBorderLine; 196 if ( getBorderLine( aBorderLine ) ) 197 { 198 switch ( nLineStyle ) 199 { 200 case word::WdLineStyle::wdLineStyleNone: 201 { 202 aBorderLine.InnerLineWidth = 0; 203 aBorderLine.OuterLineWidth = 0; 204 break; 205 } 206 case word::WdLineStyle::wdLineStyleDashDot: 207 case word::WdLineStyle::wdLineStyleDashDotDot: 208 case word::WdLineStyle::wdLineStyleDashDotStroked: 209 case word::WdLineStyle::wdLineStyleDashLargeGap: 210 case word::WdLineStyle::wdLineStyleDashSmallGap: 211 case word::WdLineStyle::wdLineStyleDot: 212 case word::WdLineStyle::wdLineStyleDouble: 213 case word::WdLineStyle::wdLineStyleDoubleWavy: 214 case word::WdLineStyle::wdLineStyleEmboss3D: 215 case word::WdLineStyle::wdLineStyleEngrave3D: 216 case word::WdLineStyle::wdLineStyleInset: 217 case word::WdLineStyle::wdLineStyleOutset: 218 case word::WdLineStyle::wdLineStyleSingle: 219 case word::WdLineStyle::wdLineStyleSingleWavy: 220 case word::WdLineStyle::wdLineStyleThickThinLargeGap: 221 case word::WdLineStyle::wdLineStyleThickThinMedGap: 222 case word::WdLineStyle::wdLineStyleThickThinSmallGap: 223 case word::WdLineStyle::wdLineStyleThinThickLargeGap: 224 case word::WdLineStyle::wdLineStyleThinThickMedGap: 225 case word::WdLineStyle::wdLineStyleThinThickSmallGap: 226 case word::WdLineStyle::wdLineStyleThinThickThinLargeGap: 227 case word::WdLineStyle::wdLineStyleThinThickThinMedGap: 228 case word::WdLineStyle::wdLineStyleThinThickThinSmallGap: 229 case word::WdLineStyle::wdLineStyleTriple: 230 { 231 aBorderLine.InnerLineWidth = 0; 232 aBorderLine.OuterLineWidth = OOLineHairline; 233 break; 234 } 235 default: 236 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Bad param" ) ), uno::Reference< uno::XInterface >() ); 237 } 238 setBorderLine( aBorderLine ); 239 } 240 else 241 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Method failed" ) ), uno::Reference< uno::XInterface >() ); 242 } 243 }; 244 245 class RangeBorders : public RangeBorders_Base 246 { 247 private: 248 uno::Reference< table::XCellRange > m_xRange; 249 uno::Reference< uno::XComponentContext > m_xContext; 250 VbaPalette m_Palette; 251 sal_Int32 getTableIndex( sal_Int32 nConst ) 252 { 253 // hokay return position of the index in the table 254 sal_Int32 nIndexes = getCount(); 255 sal_Int32 realIndex = 0; 256 const sal_Int16* pTableEntry = supportedIndexTable; 257 for ( ; realIndex < nIndexes; ++realIndex, ++pTableEntry ) 258 { 259 if ( *pTableEntry == nConst ) 260 return realIndex; 261 } 262 return getCount(); // error condition 263 } 264 public: 265 RangeBorders( const uno::Reference< table::XCellRange >& xRange, const uno::Reference< uno::XComponentContext > & xContext, VbaPalette& rPalette ) : m_xRange( xRange ), m_xContext( xContext ), m_Palette( rPalette ) 266 { 267 } 268 // XIndexAccess 269 virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException) 270 { 271 return sizeof( supportedIndexTable ) / sizeof( supportedIndexTable[0] ); 272 } 273 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException) 274 { 275 276 sal_Int32 nIndex = getTableIndex( Index ); 277 if ( nIndex >= 0 && nIndex < getCount() ) 278 { 279 uno::Reference< beans::XPropertySet > xProps( m_xRange, uno::UNO_QUERY_THROW ); 280 return uno::makeAny( uno::Reference< word::XBorder >( new SwVbaBorder( xProps, m_xContext, supportedIndexTable[ nIndex ], m_Palette )) ); 281 } 282 throw lang::IndexOutOfBoundsException(); 283 } 284 virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException) 285 { 286 return word::XBorder::static_type(0); 287 } 288 virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException) 289 { 290 return sal_True; 291 } 292 }; 293 294 uno::Reference< container::XIndexAccess > 295 rangeToBorderIndexAccess( const uno::Reference< table::XCellRange >& xRange, const uno::Reference< uno::XComponentContext > & xContext, VbaPalette& rPalette ) 296 { 297 return new RangeBorders( xRange, xContext, rPalette ); 298 } 299 300 class RangeBorderEnumWrapper : public EnumerationHelper_BASE 301 { 302 uno::Reference<container::XIndexAccess > m_xIndexAccess; 303 sal_Int32 nIndex; 304 public: 305 RangeBorderEnumWrapper( const uno::Reference< container::XIndexAccess >& xIndexAccess ) : m_xIndexAccess( xIndexAccess ), nIndex( 0 ) {} 306 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException) 307 { 308 return ( nIndex < m_xIndexAccess->getCount() ); 309 } 310 311 virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 312 { 313 if ( nIndex < m_xIndexAccess->getCount() ) 314 return m_xIndexAccess->getByIndex( nIndex++ ); 315 throw container::NoSuchElementException(); 316 } 317 }; 318 319 // for Table borders 320 SwVbaBorders::SwVbaBorders( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< table::XCellRange >& xRange, VbaPalette& rPalette ): SwVbaBorders_BASE( xParent, xContext, rangeToBorderIndexAccess( xRange ,xContext, rPalette ) ) 321 { 322 m_xProps.set( xRange, uno::UNO_QUERY_THROW ); 323 } 324 325 uno::Reference< container::XEnumeration > 326 SwVbaBorders::createEnumeration() throw (uno::RuntimeException) 327 { 328 return new RangeBorderEnumWrapper( m_xIndexAccess ); 329 } 330 331 uno::Any 332 SwVbaBorders::createCollectionObject( const css::uno::Any& aSource ) 333 { 334 return aSource; // its already a Border object 335 } 336 337 uno::Type 338 SwVbaBorders::getElementType() throw (uno::RuntimeException) 339 { 340 return word::XBorders::static_type(0); 341 } 342 343 uno::Any 344 SwVbaBorders::getItemByIntIndex( const sal_Int32 nIndex ) throw (uno::RuntimeException) 345 { 346 return createCollectionObject( m_xIndexAccess->getByIndex( nIndex ) ); 347 } 348 349 sal_Bool SAL_CALL SwVbaBorders::getShadow() throw (uno::RuntimeException) 350 { 351 table::ShadowFormat aShadowFormat; 352 m_xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShadowFormat") ) ) >>= aShadowFormat; 353 return ( aShadowFormat.Location != table::ShadowLocation_NONE ); 354 } 355 356 void SAL_CALL SwVbaBorders::setShadow( sal_Bool /*_shadow*/ ) throw (uno::RuntimeException) 357 { 358 throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() ); 359 } 360 361 rtl::OUString& 362 SwVbaBorders::getServiceImplName() 363 { 364 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaBorders") ); 365 return sImplName; 366 } 367 368 uno::Sequence< rtl::OUString > 369 SwVbaBorders::getServiceNames() 370 { 371 static uno::Sequence< rtl::OUString > aServiceNames; 372 if ( aServiceNames.getLength() == 0 ) 373 { 374 aServiceNames.realloc( 1 ); 375 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Borders" ) ); 376 } 377 return aServiceNames; 378 } 379