1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #include "oox/drawingml/chart/plotareaconverter.hxx" 29*cdf0e10cSrcweir 30*cdf0e10cSrcweir #include <com/sun/star/chart/XChartDocument.hpp> 31*cdf0e10cSrcweir #include <com/sun/star/chart/XDiagramPositioning.hpp> 32*cdf0e10cSrcweir #include <com/sun/star/chart2/XChartDocument.hpp> 33*cdf0e10cSrcweir #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> 34*cdf0e10cSrcweir #include <com/sun/star/chart2/XDiagram.hpp> 35*cdf0e10cSrcweir #include <com/sun/star/drawing/Direction3D.hpp> 36*cdf0e10cSrcweir #include <com/sun/star/drawing/ProjectionMode.hpp> 37*cdf0e10cSrcweir #include <com/sun/star/drawing/ShadeMode.hpp> 38*cdf0e10cSrcweir #include "oox/drawingml/chart/axisconverter.hxx" 39*cdf0e10cSrcweir #include "oox/drawingml/chart/plotareamodel.hxx" 40*cdf0e10cSrcweir #include "oox/drawingml/chart/typegroupconverter.hxx" 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir namespace oox { 43*cdf0e10cSrcweir namespace drawingml { 44*cdf0e10cSrcweir namespace chart { 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir // ============================================================================ 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir using namespace ::com::sun::star::awt; 49*cdf0e10cSrcweir using namespace ::com::sun::star::chart2; 50*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir using ::rtl::OUString; 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir // ============================================================================ 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir namespace { 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir /** Axes set model. This is a helper for the plot area converter collecting all 59*cdf0e10cSrcweir type groups and axes of the primary or secondary axes set. */ 60*cdf0e10cSrcweir struct AxesSetModel 61*cdf0e10cSrcweir { 62*cdf0e10cSrcweir typedef ModelVector< TypeGroupModel > TypeGroupVector; 63*cdf0e10cSrcweir typedef ModelMap< sal_Int32, AxisModel > AxisMap; 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir TypeGroupVector maTypeGroups; /// All type groups containing data series. 66*cdf0e10cSrcweir AxisMap maAxes; /// All axes mapped by API axis type. 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir inline explicit AxesSetModel() {} 69*cdf0e10cSrcweir inline ~AxesSetModel() {} 70*cdf0e10cSrcweir }; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir // ============================================================================ 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir /** Axes set converter. This is a helper class for the plot area converter. */ 75*cdf0e10cSrcweir class AxesSetConverter : public ConverterBase< AxesSetModel > 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir public: 78*cdf0e10cSrcweir explicit AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel ); 79*cdf0e10cSrcweir virtual ~AxesSetConverter(); 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir /** Converts the axes set model to a chart2 diagram. Returns an automatic 82*cdf0e10cSrcweir chart title from a single series title, if possible. */ 83*cdf0e10cSrcweir void convertFromModel( 84*cdf0e10cSrcweir const Reference< XDiagram >& rxDiagram, 85*cdf0e10cSrcweir View3DModel& rView3DModel, 86*cdf0e10cSrcweir sal_Int32 nAxesSetIdx, 87*cdf0e10cSrcweir bool bSupportsVaryColorsByPoint ); 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir /** Returns the automatic chart title if the axes set contains only one series. */ 90*cdf0e10cSrcweir inline const ::rtl::OUString& getAutomaticTitle() const { return maAutoTitle; } 91*cdf0e10cSrcweir /** Returns true, if the chart is three-dimensional. */ 92*cdf0e10cSrcweir inline bool is3dChart() const { return mb3dChart; } 93*cdf0e10cSrcweir /** Returns true, if chart type supports wall and floor format in 3D mode. */ 94*cdf0e10cSrcweir inline bool isWall3dChart() const { return mbWall3dChart; } 95*cdf0e10cSrcweir /** Returns true, if chart is a pie chart or doughnut chart. */ 96*cdf0e10cSrcweir inline bool isPieChart() const { return mbPieChart; } 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir private: 99*cdf0e10cSrcweir ::rtl::OUString maAutoTitle; 100*cdf0e10cSrcweir bool mb3dChart; 101*cdf0e10cSrcweir bool mbWall3dChart; 102*cdf0e10cSrcweir bool mbPieChart; 103*cdf0e10cSrcweir }; 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 106*cdf0e10cSrcweir 107*cdf0e10cSrcweir AxesSetConverter::AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel ) : 108*cdf0e10cSrcweir ConverterBase< AxesSetModel >( rParent, rModel ), 109*cdf0e10cSrcweir mb3dChart( false ), 110*cdf0e10cSrcweir mbWall3dChart( false ), 111*cdf0e10cSrcweir mbPieChart( false ) 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir AxesSetConverter::~AxesSetConverter() 116*cdf0e10cSrcweir { 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir ModelRef< AxisModel > lclGetOrCreateAxis( const AxesSetModel::AxisMap& rFromAxes, sal_Int32 nAxisIdx, sal_Int32 nDefTypeId ) 120*cdf0e10cSrcweir { 121*cdf0e10cSrcweir ModelRef< AxisModel > xAxis = rFromAxes.get( nAxisIdx ); 122*cdf0e10cSrcweir if( !xAxis ) 123*cdf0e10cSrcweir xAxis.create( nDefTypeId ).mbDeleted = true; // missing axis is invisible 124*cdf0e10cSrcweir return xAxis; 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir void AxesSetConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, 128*cdf0e10cSrcweir View3DModel& rView3DModel, sal_Int32 nAxesSetIdx, bool bSupportsVaryColorsByPoint ) 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir // create type group converter objects for all type groups 131*cdf0e10cSrcweir typedef RefVector< TypeGroupConverter > TypeGroupConvVector; 132*cdf0e10cSrcweir TypeGroupConvVector aTypeGroups; 133*cdf0e10cSrcweir for( AxesSetModel::TypeGroupVector::iterator aIt = mrModel.maTypeGroups.begin(), aEnd = mrModel.maTypeGroups.end(); aIt != aEnd; ++aIt ) 134*cdf0e10cSrcweir aTypeGroups.push_back( TypeGroupConvVector::value_type( new TypeGroupConverter( *this, **aIt ) ) ); 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir OSL_ENSURE( !aTypeGroups.empty(), "AxesSetConverter::convertFromModel - no type groups in axes set" ); 137*cdf0e10cSrcweir if( !aTypeGroups.empty() ) try 138*cdf0e10cSrcweir { 139*cdf0e10cSrcweir // first type group needed for coordinate system and axis conversion 140*cdf0e10cSrcweir TypeGroupConverter& rFirstTypeGroup = *aTypeGroups.front(); 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir // get automatic chart title, if there is only one type group 143*cdf0e10cSrcweir if( aTypeGroups.size() == 1 ) 144*cdf0e10cSrcweir maAutoTitle = rFirstTypeGroup.getSingleSeriesTitle(); 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir /* Create a coordinate system. For now, all type groups from all axes sets 147*cdf0e10cSrcweir have to be inserted into one coordinate system. Later, chart2 should 148*cdf0e10cSrcweir support using one coordinate system for each axes set. */ 149*cdf0e10cSrcweir Reference< XCoordinateSystem > xCoordSystem; 150*cdf0e10cSrcweir Reference< XCoordinateSystemContainer > xCoordSystemCont( rxDiagram, UNO_QUERY_THROW ); 151*cdf0e10cSrcweir Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems(); 152*cdf0e10cSrcweir if( aCoordSystems.hasElements() ) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir OSL_ENSURE( aCoordSystems.getLength() == 1, "AxesSetConverter::convertFromModel - too many coordinate systems" ); 155*cdf0e10cSrcweir xCoordSystem = aCoordSystems[ 0 ]; 156*cdf0e10cSrcweir OSL_ENSURE( xCoordSystem.is(), "AxesSetConverter::convertFromModel - invalid coordinate system" ); 157*cdf0e10cSrcweir } 158*cdf0e10cSrcweir else 159*cdf0e10cSrcweir { 160*cdf0e10cSrcweir xCoordSystem = rFirstTypeGroup.createCoordinateSystem(); 161*cdf0e10cSrcweir if( xCoordSystem.is() ) 162*cdf0e10cSrcweir xCoordSystemCont->addCoordinateSystem( xCoordSystem ); 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir // 3D view settings 166*cdf0e10cSrcweir mb3dChart = rFirstTypeGroup.is3dChart(); 167*cdf0e10cSrcweir mbWall3dChart = rFirstTypeGroup.isWall3dChart(); 168*cdf0e10cSrcweir mbPieChart = rFirstTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE; 169*cdf0e10cSrcweir if( mb3dChart ) 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir View3DConverter aView3DConv( *this, rView3DModel ); 172*cdf0e10cSrcweir aView3DConv.convertFromModel( rxDiagram, rFirstTypeGroup ); 173*cdf0e10cSrcweir } 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir /* Convert all chart type groups. Each type group will add its series 176*cdf0e10cSrcweir to the data provider attached to the chart document. */ 177*cdf0e10cSrcweir if( xCoordSystem.is() ) 178*cdf0e10cSrcweir { 179*cdf0e10cSrcweir // convert all axes (create missing axis models) 180*cdf0e10cSrcweir ModelRef< AxisModel > xXAxis = lclGetOrCreateAxis( mrModel.maAxes, API_X_AXIS, rFirstTypeGroup.getTypeInfo().mbCategoryAxis ? C_TOKEN( catAx ) : C_TOKEN( valAx ) ); 181*cdf0e10cSrcweir ModelRef< AxisModel > xYAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Y_AXIS, C_TOKEN( valAx ) ); 182*cdf0e10cSrcweir 183*cdf0e10cSrcweir AxisConverter aXAxisConv( *this, *xXAxis ); 184*cdf0e10cSrcweir aXAxisConv.convertFromModel( xCoordSystem, rFirstTypeGroup, xYAxis.get(), nAxesSetIdx, API_X_AXIS ); 185*cdf0e10cSrcweir AxisConverter aYAxisConv( *this, *xYAxis ); 186*cdf0e10cSrcweir aYAxisConv.convertFromModel( xCoordSystem, rFirstTypeGroup, xXAxis.get(), nAxesSetIdx, API_Y_AXIS ); 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir if( rFirstTypeGroup.isDeep3dChart() ) 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir ModelRef< AxisModel > xZAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Z_AXIS, C_TOKEN( serAx ) ); 191*cdf0e10cSrcweir AxisConverter aZAxisConv( *this, *xZAxis ); 192*cdf0e10cSrcweir aZAxisConv.convertFromModel( xCoordSystem, rFirstTypeGroup, 0, nAxesSetIdx, API_Z_AXIS ); 193*cdf0e10cSrcweir } 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir // convert all chart type groups, this converts all series data and formatting 196*cdf0e10cSrcweir for( TypeGroupConvVector::iterator aTIt = aTypeGroups.begin(), aTEnd = aTypeGroups.end(); aTIt != aTEnd; ++aTIt ) 197*cdf0e10cSrcweir (*aTIt)->convertFromModel( rxDiagram, xCoordSystem, nAxesSetIdx, bSupportsVaryColorsByPoint ); 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir catch( Exception& ) 201*cdf0e10cSrcweir { 202*cdf0e10cSrcweir } 203*cdf0e10cSrcweir } 204*cdf0e10cSrcweir 205*cdf0e10cSrcweir } // namespace 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir // ============================================================================ 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir View3DConverter::View3DConverter( const ConverterRoot& rParent, View3DModel& rModel ) : 210*cdf0e10cSrcweir ConverterBase< View3DModel >( rParent, rModel ) 211*cdf0e10cSrcweir { 212*cdf0e10cSrcweir } 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir View3DConverter::~View3DConverter() 215*cdf0e10cSrcweir { 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir void View3DConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, TypeGroupConverter& rTypeGroup ) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir namespace cssd = ::com::sun::star::drawing; 221*cdf0e10cSrcweir PropertySet aPropSet( rxDiagram ); 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir sal_Int32 nRotationY = 0; 224*cdf0e10cSrcweir sal_Int32 nRotationX = 0; 225*cdf0e10cSrcweir bool bRightAngled = false; 226*cdf0e10cSrcweir sal_Int32 nAmbientColor = 0; 227*cdf0e10cSrcweir sal_Int32 nLightColor = 0; 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir if( rTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE ) 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir // Y rotation used as 'first pie slice angle' in 3D pie charts 232*cdf0e10cSrcweir rTypeGroup.convertPieRotation( aPropSet, mrModel.monRotationY.get( 0 ) ); 233*cdf0e10cSrcweir // X rotation a.k.a. elevation (map OOXML [0..90] to Chart2 [-90,0]) 234*cdf0e10cSrcweir nRotationX = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.monRotationX.get( 15 ), 0, 90 ) - 90; 235*cdf0e10cSrcweir // no right-angled axes in pie charts 236*cdf0e10cSrcweir bRightAngled = false; 237*cdf0e10cSrcweir // ambient color (Gray 30%) 238*cdf0e10cSrcweir nAmbientColor = 0xB3B3B3; 239*cdf0e10cSrcweir // light color (Gray 70%) 240*cdf0e10cSrcweir nLightColor = 0x4C4C4C; 241*cdf0e10cSrcweir } 242*cdf0e10cSrcweir else // 3D bar/area/line charts 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir // Y rotation (OOXML [0..359], Chart2 [-179,180]) 245*cdf0e10cSrcweir nRotationY = mrModel.monRotationY.get( 20 ); 246*cdf0e10cSrcweir // X rotation a.k.a. elevation (OOXML [-90..90], Chart2 [-179,180]) 247*cdf0e10cSrcweir nRotationX = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.monRotationX.get( 15 ), -90, 90 ); 248*cdf0e10cSrcweir // right-angled axes 249*cdf0e10cSrcweir bRightAngled = mrModel.mbRightAngled; 250*cdf0e10cSrcweir // ambient color (Gray 20%) 251*cdf0e10cSrcweir nAmbientColor = 0xCCCCCC; 252*cdf0e10cSrcweir // light color (Gray 60%) 253*cdf0e10cSrcweir nLightColor = 0x666666; 254*cdf0e10cSrcweir } 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir // Y rotation (map OOXML [0..359] to Chart2 [-179,180]) 257*cdf0e10cSrcweir nRotationY %= 360; 258*cdf0e10cSrcweir if( nRotationY > 180 ) nRotationY -= 360; 259*cdf0e10cSrcweir /* Perspective (map OOXML [0..200] to Chart2 [0,100]). Seems that MSO 2007 is 260*cdf0e10cSrcweir buggy here, the XML plugin of MSO 2003 writes the correct perspective in 261*cdf0e10cSrcweir the range from 0 to 100. We will emulate the wrong behaviour of MSO 2007. */ 262*cdf0e10cSrcweir sal_Int32 nPerspective = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.mnPerspective / 2, 0, 100 ); 263*cdf0e10cSrcweir // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%) 264*cdf0e10cSrcweir bool bParallel = bRightAngled || (nPerspective == 0); 265*cdf0e10cSrcweir cssd::ProjectionMode eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE; 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir // set rotation properties 268*cdf0e10cSrcweir aPropSet.setProperty( PROP_RotationVertical, nRotationY ); 269*cdf0e10cSrcweir aPropSet.setProperty( PROP_RotationHorizontal, nRotationX ); 270*cdf0e10cSrcweir aPropSet.setProperty( PROP_Perspective, nPerspective ); 271*cdf0e10cSrcweir aPropSet.setProperty( PROP_RightAngledAxes, bRightAngled ); 272*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DScenePerspective, eProjMode ); 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir // set light settings 275*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DSceneShadeMode, cssd::ShadeMode_FLAT ); 276*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DSceneAmbientColor, nAmbientColor ); 277*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DSceneLightOn1, false ); 278*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DSceneLightOn2, true ); 279*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DSceneLightColor2, nLightColor ); 280*cdf0e10cSrcweir aPropSet.setProperty( PROP_D3DSceneLightDirection2, cssd::Direction3D( 0.2, 0.4, 1.0 ) ); 281*cdf0e10cSrcweir } 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir // ============================================================================ 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir WallFloorConverter::WallFloorConverter( const ConverterRoot& rParent, WallFloorModel& rModel ) : 286*cdf0e10cSrcweir ConverterBase< WallFloorModel >( rParent, rModel ) 287*cdf0e10cSrcweir { 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir WallFloorConverter::~WallFloorConverter() 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir void WallFloorConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, ObjectType eObjType ) 295*cdf0e10cSrcweir { 296*cdf0e10cSrcweir if( rxDiagram.is() ) 297*cdf0e10cSrcweir { 298*cdf0e10cSrcweir PropertySet aPropSet; 299*cdf0e10cSrcweir switch( eObjType ) 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir case OBJECTTYPE_FLOOR: aPropSet.set( rxDiagram->getFloor() ); break; 302*cdf0e10cSrcweir case OBJECTTYPE_WALL: aPropSet.set( rxDiagram->getWall() ); break; 303*cdf0e10cSrcweir default: OSL_ENSURE( false, "WallFloorConverter::convertFromModel - invalid object type" ); 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir if( aPropSet.is() ) 306*cdf0e10cSrcweir getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType ); 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir // ============================================================================ 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir PlotAreaConverter::PlotAreaConverter( const ConverterRoot& rParent, PlotAreaModel& rModel ) : 313*cdf0e10cSrcweir ConverterBase< PlotAreaModel >( rParent, rModel ), 314*cdf0e10cSrcweir mb3dChart( false ), 315*cdf0e10cSrcweir mbWall3dChart( false ), 316*cdf0e10cSrcweir mbPieChart( false ) 317*cdf0e10cSrcweir { 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir PlotAreaConverter::~PlotAreaConverter() 321*cdf0e10cSrcweir { 322*cdf0e10cSrcweir } 323*cdf0e10cSrcweir 324*cdf0e10cSrcweir void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel ) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir /* Create the diagram object and attach it to the chart document. One 327*cdf0e10cSrcweir diagram is used to carry all coordinate systems and data series. */ 328*cdf0e10cSrcweir Reference< XDiagram > xDiagram; 329*cdf0e10cSrcweir try 330*cdf0e10cSrcweir { 331*cdf0e10cSrcweir xDiagram.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Diagram" ) ), UNO_QUERY_THROW ); 332*cdf0e10cSrcweir getChartDocument()->setFirstDiagram( xDiagram ); 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir catch( Exception& ) 335*cdf0e10cSrcweir { 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir // store all axis models in a map, keyed by axis identifier 339*cdf0e10cSrcweir typedef ModelMap< sal_Int32, AxisModel > AxisMap; 340*cdf0e10cSrcweir AxisMap aAxisMap; 341*cdf0e10cSrcweir for( PlotAreaModel::AxisVector::iterator aAIt = mrModel.maAxes.begin(), aAEnd = mrModel.maAxes.end(); aAIt != aAEnd; ++aAIt ) 342*cdf0e10cSrcweir { 343*cdf0e10cSrcweir PlotAreaModel::AxisVector::value_type xAxis = *aAIt; 344*cdf0e10cSrcweir OSL_ENSURE( xAxis->mnAxisId >= 0, "PlotAreaConverter::convertFromModel - invalid axis identifier" ); 345*cdf0e10cSrcweir OSL_ENSURE( !aAxisMap.has( xAxis->mnAxisId ), "PlotAreaConverter::convertFromModel - axis identifiers not unique" ); 346*cdf0e10cSrcweir if( xAxis->mnAxisId >= 0 ) 347*cdf0e10cSrcweir aAxisMap[ xAxis->mnAxisId ] = xAxis; 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir // group the type group models into different axes sets 351*cdf0e10cSrcweir typedef ModelVector< AxesSetModel > AxesSetVector; 352*cdf0e10cSrcweir AxesSetVector aAxesSets; 353*cdf0e10cSrcweir sal_Int32 nMaxSeriesIdx = -1; 354*cdf0e10cSrcweir for( PlotAreaModel::TypeGroupVector::iterator aTIt = mrModel.maTypeGroups.begin(), aTEnd = mrModel.maTypeGroups.end(); aTIt != aTEnd; ++aTIt ) 355*cdf0e10cSrcweir { 356*cdf0e10cSrcweir PlotAreaModel::TypeGroupVector::value_type xTypeGroup = *aTIt; 357*cdf0e10cSrcweir if( !xTypeGroup->maSeries.empty() ) 358*cdf0e10cSrcweir { 359*cdf0e10cSrcweir // try to find a compatible axes set for the type group 360*cdf0e10cSrcweir AxesSetModel* pAxesSet = 0; 361*cdf0e10cSrcweir for( AxesSetVector::iterator aASIt = aAxesSets.begin(), aASEnd = aAxesSets.end(); !pAxesSet && (aASIt != aASEnd); ++aASIt ) 362*cdf0e10cSrcweir if( (*aASIt)->maTypeGroups.front()->maAxisIds == xTypeGroup->maAxisIds ) 363*cdf0e10cSrcweir pAxesSet = aASIt->get(); 364*cdf0e10cSrcweir 365*cdf0e10cSrcweir // not possible to insert into an existing axes set -> start a new axes set 366*cdf0e10cSrcweir if( !pAxesSet ) 367*cdf0e10cSrcweir { 368*cdf0e10cSrcweir pAxesSet = &aAxesSets.create(); 369*cdf0e10cSrcweir // find axis models used by the type group 370*cdf0e10cSrcweir const TypeGroupModel::AxisIdVector& rAxisIds = xTypeGroup->maAxisIds; 371*cdf0e10cSrcweir if( rAxisIds.size() >= 1 ) 372*cdf0e10cSrcweir pAxesSet->maAxes[ API_X_AXIS ] = aAxisMap.get( rAxisIds[ 0 ] ); 373*cdf0e10cSrcweir if( rAxisIds.size() >= 2 ) 374*cdf0e10cSrcweir pAxesSet->maAxes[ API_Y_AXIS ] = aAxisMap.get( rAxisIds[ 1 ] ); 375*cdf0e10cSrcweir if( rAxisIds.size() >= 3 ) 376*cdf0e10cSrcweir pAxesSet->maAxes[ API_Z_AXIS ] = aAxisMap.get( rAxisIds[ 2 ] ); 377*cdf0e10cSrcweir } 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir // insert the type group model 380*cdf0e10cSrcweir pAxesSet->maTypeGroups.push_back( xTypeGroup ); 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir // collect the maximum series index for automatic series formatting 383*cdf0e10cSrcweir for( TypeGroupModel::SeriesVector::iterator aSIt = xTypeGroup->maSeries.begin(), aSEnd = xTypeGroup->maSeries.end(); aSIt != aSEnd; ++aSIt ) 384*cdf0e10cSrcweir nMaxSeriesIdx = ::std::max( nMaxSeriesIdx, (*aSIt)->mnIndex ); 385*cdf0e10cSrcweir } 386*cdf0e10cSrcweir } 387*cdf0e10cSrcweir getFormatter().setMaxSeriesIndex( nMaxSeriesIdx ); 388*cdf0e10cSrcweir 389*cdf0e10cSrcweir // varying point colors only for single series in single chart type 390*cdf0e10cSrcweir bool bSupportsVaryColorsByPoint = mrModel.maTypeGroups.size() == 1; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir // convert all axes sets 393*cdf0e10cSrcweir for( AxesSetVector::iterator aASBeg = aAxesSets.begin(), aASIt = aASBeg, aASEnd = aAxesSets.end(); aASIt != aASEnd; ++aASIt ) 394*cdf0e10cSrcweir { 395*cdf0e10cSrcweir AxesSetConverter aAxesSetConv( *this, **aASIt ); 396*cdf0e10cSrcweir sal_Int32 nAxesSetIdx = static_cast< sal_Int32 >( aASIt - aASBeg ); 397*cdf0e10cSrcweir aAxesSetConv.convertFromModel( xDiagram, rView3DModel, nAxesSetIdx, bSupportsVaryColorsByPoint ); 398*cdf0e10cSrcweir if( nAxesSetIdx == 0 ) 399*cdf0e10cSrcweir { 400*cdf0e10cSrcweir maAutoTitle = aAxesSetConv.getAutomaticTitle(); 401*cdf0e10cSrcweir mb3dChart = aAxesSetConv.is3dChart(); 402*cdf0e10cSrcweir mbWall3dChart = aAxesSetConv.isWall3dChart(); 403*cdf0e10cSrcweir mbPieChart = aAxesSetConv.isPieChart(); 404*cdf0e10cSrcweir } 405*cdf0e10cSrcweir else 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir maAutoTitle = OUString(); 408*cdf0e10cSrcweir } 409*cdf0e10cSrcweir } 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir // plot area formatting 412*cdf0e10cSrcweir if( xDiagram.is() && !mb3dChart ) 413*cdf0e10cSrcweir { 414*cdf0e10cSrcweir PropertySet aPropSet( xDiagram->getWall() ); 415*cdf0e10cSrcweir getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_PLOTAREA2D ); 416*cdf0e10cSrcweir } 417*cdf0e10cSrcweir } 418*cdf0e10cSrcweir 419*cdf0e10cSrcweir void PlotAreaConverter::convertPositionFromModel() 420*cdf0e10cSrcweir { 421*cdf0e10cSrcweir LayoutModel& rLayout = mrModel.mxLayout.getOrCreate(); 422*cdf0e10cSrcweir LayoutConverter aLayoutConv( *this, rLayout ); 423*cdf0e10cSrcweir Rectangle aDiagramRect; 424*cdf0e10cSrcweir if( aLayoutConv.calcAbsRectangle( aDiagramRect ) ) try 425*cdf0e10cSrcweir { 426*cdf0e10cSrcweir namespace cssc = ::com::sun::star::chart; 427*cdf0e10cSrcweir Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY_THROW ); 428*cdf0e10cSrcweir Reference< cssc::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW ); 429*cdf0e10cSrcweir // for pie charts, always set inner plot area size to exclude the data labels as Excel does 430*cdf0e10cSrcweir sal_Int32 nTarget = (mbPieChart && (rLayout.mnTarget == XML_outer)) ? XML_inner : rLayout.mnTarget; 431*cdf0e10cSrcweir switch( nTarget ) 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir case XML_inner: 434*cdf0e10cSrcweir xPositioning->setDiagramPositionExcludingAxes( aDiagramRect ); 435*cdf0e10cSrcweir break; 436*cdf0e10cSrcweir case XML_outer: 437*cdf0e10cSrcweir xPositioning->setDiagramPositionIncludingAxes( aDiagramRect ); 438*cdf0e10cSrcweir break; 439*cdf0e10cSrcweir default: 440*cdf0e10cSrcweir OSL_ENSURE( false, "PlotAreaConverter::convertPositionFromModel - unknown positioning target" ); 441*cdf0e10cSrcweir } 442*cdf0e10cSrcweir } 443*cdf0e10cSrcweir catch( Exception& ) 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir } 446*cdf0e10cSrcweir } 447*cdf0e10cSrcweir 448*cdf0e10cSrcweir // ============================================================================ 449*cdf0e10cSrcweir 450*cdf0e10cSrcweir } // namespace chart 451*cdf0e10cSrcweir } // namespace drawingml 452*cdf0e10cSrcweir } // namespace oox 453