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