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