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 28 #include "vbaaxes.hxx" 29 #include "vbaaxis.hxx" 30 #include "vbachart.hxx" 31 #include <ooo/vba/excel/XlAxisType.hpp> 32 #include <ooo/vba/excel/XlAxisGroup.hpp> 33 #include <ooo/vba/excel/XAxis.hpp> 34 #include <map> 35 36 using namespace ::com::sun::star; 37 using namespace ::ooo::vba; 38 using namespace ::ooo::vba::excel::XlAxisType; 39 using namespace ::ooo::vba::excel::XlAxisGroup; 40 41 // each 'Item' in the Axes collection is indexed via 2 indexes, group and type. 42 // We need to 'flatten' this into a single index in order to be able to wrap 43 // iteration over the set of Axis(s) in a XIndexAccess implementation 44 // 45 typedef ::std::pair<sal_Int32, sal_Int32 > AxesCoordinate; // type and group combination 46 typedef ::std::vector< AxesCoordinate > vecAxesIndices; 47 48 typedef ::cppu::WeakImplHelper1< container::XIndexAccess > AxisIndexWrapper_BASE; 49 50 class EnumWrapper : public EnumerationHelper_BASE 51 { 52 uno::Reference<container::XIndexAccess > m_xIndexAccess; 53 sal_Int32 nIndex; 54 public: 55 EnumWrapper( const uno::Reference< container::XIndexAccess >& xIndexAccess ) : m_xIndexAccess( xIndexAccess ), nIndex( 0 ) {} 56 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException) 57 { 58 return ( nIndex < m_xIndexAccess->getCount() ); 59 } 60 61 virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 62 { 63 if ( nIndex < m_xIndexAccess->getCount() ) 64 return m_xIndexAccess->getByIndex( nIndex++ ); 65 throw container::NoSuchElementException(); 66 } 67 }; 68 69 70 uno::Reference< excel::XAxis > 71 ScVbaAxes::createAxis( const uno::Reference< excel::XChart >& xChart, const uno::Reference< uno::XComponentContext >& xContext, sal_Int32 nType, sal_Int32 nAxisGroup ) throw ( uno::RuntimeException ) 72 { 73 ScVbaChart* pChart = static_cast< ScVbaChart* >( xChart.get() ); 74 if ( !pChart ) 75 throw uno::RuntimeException( rtl::OUString::createFromAscii( "Object failure, can't access chart implementation" ), uno::Reference< uno::XInterface >() ); 76 77 uno::Reference< beans::XPropertySet > xAxisPropertySet; 78 if (((nType == xlCategory) || (nType == xlSeriesAxis) || (nType == xlValue))) 79 { 80 if ((nAxisGroup != xlPrimary) && (nAxisGroup != xlSecondary)) 81 throw script::BasicErrorException( rtl::OUString(), NULL, SbERR_METHOD_FAILED, rtl::OUString()); 82 xAxisPropertySet.set( pChart->getAxisPropertySet(nType, nAxisGroup), uno::UNO_QUERY_THROW ); 83 } 84 else 85 throw script::BasicErrorException( rtl::OUString(), NULL, SbERR_METHOD_FAILED, rtl::OUString()); 86 uno::Reference< XHelperInterface > xParent( xChart, uno::UNO_QUERY_THROW ); 87 return new ScVbaAxis( xParent, xContext, xAxisPropertySet, nType, nAxisGroup); 88 } 89 90 class AxisIndexWrapper : public AxisIndexWrapper_BASE 91 { 92 // if necessary for better performance we could change this into a map and cache the 93 // indices -> Axis, currently we create a new Axis object 94 // on each getByIndex 95 uno::Reference< uno::XComponentContext > mxContext; 96 vecAxesIndices mCoordinates; 97 uno::Reference< excel::XChart > mxChart; 98 public: 99 AxisIndexWrapper( const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< excel::XChart >& xChart ) : mxContext( xContext ), mxChart( xChart ) 100 { 101 if ( mxChart.is() ) 102 { 103 ScVbaChart* pChart = static_cast< ScVbaChart* >( mxChart.get() ); 104 // primary 105 sal_Bool bBool = false; 106 uno::Reference< beans::XPropertySet > xDiagramPropertySet( pChart->xDiagramPropertySet() ); 107 if ( ( xDiagramPropertySet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasXAxis" ) ) ) >>= bBool ) && bBool ) 108 mCoordinates.push_back( AxesCoordinate( xlPrimary, xlCategory ) ); 109 if ( ( xDiagramPropertySet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasYAxis" ) ) ) >>= bBool ) && bBool ) 110 mCoordinates.push_back( AxesCoordinate( xlPrimary, xlSeriesAxis ) ); 111 112 if ( pChart->is3D() ) 113 mCoordinates.push_back( AxesCoordinate( xlPrimary, xlValue ) ); 114 115 // secondary 116 if ( ( xDiagramPropertySet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasSecondaryXAxis" ) ) ) >>= bBool ) && bBool ) 117 mCoordinates.push_back( AxesCoordinate( xlSecondary, xlCategory ) ); 118 if ( ( xDiagramPropertySet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasSecondaryYAxis" ) ) ) >>= bBool ) && bBool ) 119 mCoordinates.push_back( AxesCoordinate( xlSecondary, xlSeriesAxis ) ); 120 } 121 122 } 123 virtual ::sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException) { return mCoordinates.size(); } 124 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, ::uno::RuntimeException) 125 { 126 AxesCoordinate dIndexes = mCoordinates[ Index ]; 127 return uno::makeAny( ScVbaAxes::createAxis( mxChart, mxContext, dIndexes.second, dIndexes.first ) ); 128 } 129 // XElementAccess 130 virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException) 131 { 132 return excel::XAxis::static_type(0); 133 } 134 virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException) 135 { 136 return ( mCoordinates.size() > 0 ); 137 } 138 }; 139 140 uno::Reference< container::XIndexAccess > createIndexWrapper( const uno::Reference< excel::XChart >& xChart, const uno::Reference< uno::XComponentContext >& xContext ) 141 { 142 return new AxisIndexWrapper( xContext, xChart ); 143 } 144 145 // #FIXME The collection semantics will never work as this object is not yet initialised correctly 146 ScVbaAxes::ScVbaAxes( const uno::Reference< XHelperInterface >& xParent,const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< excel::XChart >& xChart ) : ScVbaAxes_BASE( xParent, xContext, createIndexWrapper( xChart, xContext )), moChartParent( xChart ) 147 { 148 } 149 150 uno::Type SAL_CALL 151 ScVbaAxes::getElementType() throw (css::uno::RuntimeException) 152 { 153 return excel::XAxes::static_type(0); 154 } 155 156 uno::Reference< container::XEnumeration > SAL_CALL 157 ScVbaAxes::createEnumeration() throw (css::uno::RuntimeException) 158 { 159 return new EnumWrapper( m_xIndexAccess ); 160 } 161 162 uno::Any SAL_CALL 163 ScVbaAxes::Item( const css::uno::Any& _nType, const css::uno::Any& _oAxisGroup) throw (css::uno::RuntimeException) 164 { 165 // #TODO map the possible index combinations to a container::XIndexAccess wrapper impl 166 // using a vector of valid std::pair maybe? 167 // bodgy helperapi port bits 168 sal_Int32 nAxisGroup = xlPrimary; 169 sal_Int32 nType = -1; 170 if ( !_nType.hasValue() || ( ( _nType >>= nType ) == sal_False ) ) 171 throw uno::RuntimeException( rtl::OUString::createFromAscii( "Axes::Item Failed to extract type" ), uno::Reference< uno::XInterface >() ); 172 173 if ( _oAxisGroup.hasValue() ) 174 _oAxisGroup >>= nAxisGroup ; 175 176 return uno::makeAny( createAxis( moChartParent, mxContext, nType, nAxisGroup ) ); 177 } 178 179 uno::Any 180 ScVbaAxes::createCollectionObject(const css::uno::Any& aSource) 181 { 182 return aSource; // pass through ( it's already an XAxis object 183 } 184 185 rtl::OUString& 186 ScVbaAxes::getServiceImplName() 187 { 188 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaAxes") ); 189 return sImplName; 190 } 191 192 uno::Sequence< rtl::OUString > 193 ScVbaAxes::getServiceNames() 194 { 195 static uno::Sequence< rtl::OUString > aServiceNames; 196 if ( aServiceNames.getLength() == 0 ) 197 { 198 aServiceNames.realloc( 1 ); 199 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Axes" ) ); 200 } 201 return aServiceNames; 202 } 203 204