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