1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #include "oox/drawingml/chart/axisconverter.hxx"
25*b1cdbd2cSJim Jagielski 
26*b1cdbd2cSJim Jagielski #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
27*b1cdbd2cSJim Jagielski #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
28*b1cdbd2cSJim Jagielski #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/chart/ChartAxisPosition.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/chart/TimeInterval.hpp>
31*b1cdbd2cSJim Jagielski #include <com/sun/star/chart/TimeUnit.hpp>
32*b1cdbd2cSJim Jagielski #include <com/sun/star/chart2/AxisType.hpp>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/chart2/TickmarkStyle.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/chart2/XAxis.hpp>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/chart2/XCoordinateSystem.hpp>
36*b1cdbd2cSJim Jagielski #include <com/sun/star/chart2/XTitled.hpp>
37*b1cdbd2cSJim Jagielski #include "oox/drawingml/chart/axismodel.hxx"
38*b1cdbd2cSJim Jagielski #include "oox/drawingml/chart/titleconverter.hxx"
39*b1cdbd2cSJim Jagielski #include "oox/drawingml/chart/typegroupconverter.hxx"
40*b1cdbd2cSJim Jagielski #include "oox/drawingml/lineproperties.hxx"
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski namespace oox {
43*b1cdbd2cSJim Jagielski namespace drawingml {
44*b1cdbd2cSJim Jagielski namespace chart {
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski // ============================================================================
47*b1cdbd2cSJim Jagielski 
48*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::beans;
49*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::chart2;
50*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::uno;
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski using ::rtl::OUString;
53*b1cdbd2cSJim Jagielski 
54*b1cdbd2cSJim Jagielski // ============================================================================
55*b1cdbd2cSJim Jagielski 
56*b1cdbd2cSJim Jagielski namespace {
57*b1cdbd2cSJim Jagielski 
lclSetValueOrClearAny(Any & orAny,const OptValue<double> & rofValue)58*b1cdbd2cSJim Jagielski inline void lclSetValueOrClearAny( Any& orAny, const OptValue< double >& rofValue )
59*b1cdbd2cSJim Jagielski {
60*b1cdbd2cSJim Jagielski     if( rofValue.has() ) orAny <<= rofValue.get(); else orAny.clear();
61*b1cdbd2cSJim Jagielski }
62*b1cdbd2cSJim Jagielski 
lclIsLogarithmicScale(const AxisModel & rAxisModel)63*b1cdbd2cSJim Jagielski bool lclIsLogarithmicScale( const AxisModel& rAxisModel )
64*b1cdbd2cSJim Jagielski {
65*b1cdbd2cSJim Jagielski     return rAxisModel.mofLogBase.has() && (2.0 <= rAxisModel.mofLogBase.get()) && (rAxisModel.mofLogBase.get() <= 1000.0);
66*b1cdbd2cSJim Jagielski }
67*b1cdbd2cSJim Jagielski 
lclGetApiTimeUnit(sal_Int32 nTimeUnit)68*b1cdbd2cSJim Jagielski sal_Int32 lclGetApiTimeUnit( sal_Int32 nTimeUnit )
69*b1cdbd2cSJim Jagielski {
70*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::chart;
71*b1cdbd2cSJim Jagielski     switch( nTimeUnit )
72*b1cdbd2cSJim Jagielski     {
73*b1cdbd2cSJim Jagielski         case XML_days:      return TimeUnit::DAY;
74*b1cdbd2cSJim Jagielski         case XML_months:    return TimeUnit::MONTH;
75*b1cdbd2cSJim Jagielski         case XML_years:     return TimeUnit::YEAR;
76*b1cdbd2cSJim Jagielski         default:            OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" );
77*b1cdbd2cSJim Jagielski     }
78*b1cdbd2cSJim Jagielski     return TimeUnit::DAY;
79*b1cdbd2cSJim Jagielski }
80*b1cdbd2cSJim Jagielski 
lclConvertTimeInterval(Any & orInterval,const OptValue<double> & rofUnit,sal_Int32 nTimeUnit)81*b1cdbd2cSJim Jagielski void lclConvertTimeInterval( Any& orInterval, const OptValue< double >& rofUnit, sal_Int32 nTimeUnit )
82*b1cdbd2cSJim Jagielski {
83*b1cdbd2cSJim Jagielski     if( rofUnit.has() && (1.0 <= rofUnit.get()) && (rofUnit.get() <= SAL_MAX_INT32) )
84*b1cdbd2cSJim Jagielski         orInterval <<= ::com::sun::star::chart::TimeInterval( static_cast< sal_Int32 >( rofUnit.get() ), lclGetApiTimeUnit( nTimeUnit ) );
85*b1cdbd2cSJim Jagielski     else
86*b1cdbd2cSJim Jagielski         orInterval.clear();
87*b1cdbd2cSJim Jagielski }
88*b1cdbd2cSJim Jagielski 
lclGetLabelPosition(sal_Int32 nToken)89*b1cdbd2cSJim Jagielski ::com::sun::star::chart::ChartAxisLabelPosition lclGetLabelPosition( sal_Int32 nToken )
90*b1cdbd2cSJim Jagielski {
91*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::chart;
92*b1cdbd2cSJim Jagielski     switch( nToken )
93*b1cdbd2cSJim Jagielski     {
94*b1cdbd2cSJim Jagielski         case XML_high:      return ChartAxisLabelPosition_OUTSIDE_END;
95*b1cdbd2cSJim Jagielski         case XML_low:       return ChartAxisLabelPosition_OUTSIDE_START;
96*b1cdbd2cSJim Jagielski         case XML_nextTo:    return ChartAxisLabelPosition_NEAR_AXIS;
97*b1cdbd2cSJim Jagielski     }
98*b1cdbd2cSJim Jagielski     return ChartAxisLabelPosition_NEAR_AXIS;
99*b1cdbd2cSJim Jagielski }
100*b1cdbd2cSJim Jagielski 
lclGetTickMark(sal_Int32 nToken)101*b1cdbd2cSJim Jagielski sal_Int32 lclGetTickMark( sal_Int32 nToken )
102*b1cdbd2cSJim Jagielski {
103*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::chart2::TickmarkStyle;
104*b1cdbd2cSJim Jagielski     switch( nToken )
105*b1cdbd2cSJim Jagielski     {
106*b1cdbd2cSJim Jagielski         case XML_in:    return INNER;
107*b1cdbd2cSJim Jagielski         case XML_out:   return OUTER;
108*b1cdbd2cSJim Jagielski         case XML_cross: return INNER | OUTER;
109*b1cdbd2cSJim Jagielski     }
110*b1cdbd2cSJim Jagielski     return NONE;
111*b1cdbd2cSJim Jagielski }
112*b1cdbd2cSJim Jagielski 
113*b1cdbd2cSJim Jagielski } // namespace
114*b1cdbd2cSJim Jagielski 
115*b1cdbd2cSJim Jagielski // ============================================================================
116*b1cdbd2cSJim Jagielski 
AxisConverter(const ConverterRoot & rParent,AxisModel & rModel)117*b1cdbd2cSJim Jagielski AxisConverter::AxisConverter( const ConverterRoot& rParent, AxisModel& rModel ) :
118*b1cdbd2cSJim Jagielski     ConverterBase< AxisModel >( rParent, rModel )
119*b1cdbd2cSJim Jagielski {
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski 
~AxisConverter()122*b1cdbd2cSJim Jagielski AxisConverter::~AxisConverter()
123*b1cdbd2cSJim Jagielski {
124*b1cdbd2cSJim Jagielski }
125*b1cdbd2cSJim Jagielski 
convertFromModel(const Reference<XCoordinateSystem> & rxCoordSystem,TypeGroupConverter & rTypeGroup,const AxisModel * pCrossingAxis,sal_Int32 nAxesSetIdx,sal_Int32 nAxisIdx)126*b1cdbd2cSJim Jagielski void AxisConverter::convertFromModel( const Reference< XCoordinateSystem >& rxCoordSystem,
127*b1cdbd2cSJim Jagielski         TypeGroupConverter& rTypeGroup, const AxisModel* pCrossingAxis, sal_Int32 nAxesSetIdx, sal_Int32 nAxisIdx )
128*b1cdbd2cSJim Jagielski {
129*b1cdbd2cSJim Jagielski     Reference< XAxis > xAxis;
130*b1cdbd2cSJim Jagielski     try
131*b1cdbd2cSJim Jagielski     {
132*b1cdbd2cSJim Jagielski         namespace cssc = ::com::sun::star::chart;
133*b1cdbd2cSJim Jagielski         namespace cssc2 = ::com::sun::star::chart2;
134*b1cdbd2cSJim Jagielski 
135*b1cdbd2cSJim Jagielski         const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
136*b1cdbd2cSJim Jagielski         ObjectFormatter& rFormatter = getFormatter();
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski         // create the axis object (always)
139*b1cdbd2cSJim Jagielski         xAxis.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Axis" ) ), UNO_QUERY_THROW );
140*b1cdbd2cSJim Jagielski         PropertySet aAxisProp( xAxis );
141*b1cdbd2cSJim Jagielski         // #i58688# axis enabled
142*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_Show, !mrModel.mbDeleted );
143*b1cdbd2cSJim Jagielski 
144*b1cdbd2cSJim Jagielski         // axis line, tick, and gridline properties ---------------------------
145*b1cdbd2cSJim Jagielski 
146*b1cdbd2cSJim Jagielski         // show axis labels
147*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_DisplayLabels, mrModel.mnTickLabelPos != XML_none );
148*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_LabelPosition, lclGetLabelPosition( mrModel.mnTickLabelPos ) );
149*b1cdbd2cSJim Jagielski         // no X axis line in radar charts
150*b1cdbd2cSJim Jagielski         if( (nAxisIdx == API_X_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_RADAR) )
151*b1cdbd2cSJim Jagielski             mrModel.mxShapeProp.getOrCreate().getLineProperties().maLineFill.moFillType = XML_noFill;
152*b1cdbd2cSJim Jagielski         // axis line and tick label formatting
153*b1cdbd2cSJim Jagielski         rFormatter.convertFormatting( aAxisProp, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_AXIS );
154*b1cdbd2cSJim Jagielski         // tick label rotation
155*b1cdbd2cSJim Jagielski         rFormatter.convertTextRotation( aAxisProp, mrModel.mxTextProp, true );
156*b1cdbd2cSJim Jagielski 
157*b1cdbd2cSJim Jagielski         // tick mark style
158*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_MajorTickmarks, lclGetTickMark( mrModel.mnMajorTickMark ) );
159*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_MinorTickmarks, lclGetTickMark( mrModel.mnMinorTickMark ) );
160*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_MarkPosition, cssc::ChartAxisMarkPosition_AT_AXIS );
161*b1cdbd2cSJim Jagielski 
162*b1cdbd2cSJim Jagielski         // main grid
163*b1cdbd2cSJim Jagielski         PropertySet aGridProp( xAxis->getGridProperties() );
164*b1cdbd2cSJim Jagielski         aGridProp.setProperty( PROP_Show, mrModel.mxMajorGridLines.is() );
165*b1cdbd2cSJim Jagielski         if( mrModel.mxMajorGridLines.is() )
166*b1cdbd2cSJim Jagielski             rFormatter.convertFrameFormatting( aGridProp, mrModel.mxMajorGridLines, OBJECTTYPE_MAJORGRIDLINE );
167*b1cdbd2cSJim Jagielski 
168*b1cdbd2cSJim Jagielski         // sub grid
169*b1cdbd2cSJim Jagielski         Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties();
170*b1cdbd2cSJim Jagielski         if( aSubGridPropSeq.hasElements() )
171*b1cdbd2cSJim Jagielski         {
172*b1cdbd2cSJim Jagielski             PropertySet aSubGridProp( aSubGridPropSeq[ 0 ] );
173*b1cdbd2cSJim Jagielski             aSubGridProp.setProperty( PROP_Show, mrModel.mxMinorGridLines.is() );
174*b1cdbd2cSJim Jagielski             if( mrModel.mxMinorGridLines.is() )
175*b1cdbd2cSJim Jagielski                 rFormatter.convertFrameFormatting( aSubGridProp, mrModel.mxMinorGridLines, OBJECTTYPE_MINORGRIDLINE );
176*b1cdbd2cSJim Jagielski         }
177*b1cdbd2cSJim Jagielski 
178*b1cdbd2cSJim Jagielski         // axis type and X axis categories ------------------------------------
179*b1cdbd2cSJim Jagielski 
180*b1cdbd2cSJim Jagielski         ScaleData aScaleData = xAxis->getScaleData();
181*b1cdbd2cSJim Jagielski         // set axis type
182*b1cdbd2cSJim Jagielski         switch( nAxisIdx )
183*b1cdbd2cSJim Jagielski         {
184*b1cdbd2cSJim Jagielski             case API_X_AXIS:
185*b1cdbd2cSJim Jagielski                 if( rTypeInfo.mbCategoryAxis )
186*b1cdbd2cSJim Jagielski                 {
187*b1cdbd2cSJim Jagielski                     OSL_ENSURE( (mrModel.mnTypeId == C_TOKEN( catAx )) || (mrModel.mnTypeId == C_TOKEN( dateAx )),
188*b1cdbd2cSJim Jagielski                         "AxisConverter::convertFromModel - unexpected axis model type (must: c:catAx or c:dateAx)" );
189*b1cdbd2cSJim Jagielski                     bool bDateAxis = mrModel.mnTypeId == C_TOKEN( dateAx );
190*b1cdbd2cSJim Jagielski                     /*  Chart2 requires axis type CATEGORY for automatic
191*b1cdbd2cSJim Jagielski                         category/date axis (even if it is a date axis
192*b1cdbd2cSJim Jagielski                         currently). */
193*b1cdbd2cSJim Jagielski                     aScaleData.AxisType = (bDateAxis && !mrModel.mbAuto) ? cssc2::AxisType::DATE : cssc2::AxisType::CATEGORY;
194*b1cdbd2cSJim Jagielski                     aScaleData.AutoDateAxis = mrModel.mbAuto;
195*b1cdbd2cSJim Jagielski                     aScaleData.Categories = rTypeGroup.createCategorySequence();
196*b1cdbd2cSJim Jagielski                 }
197*b1cdbd2cSJim Jagielski                 else
198*b1cdbd2cSJim Jagielski                 {
199*b1cdbd2cSJim Jagielski                     OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" );
200*b1cdbd2cSJim Jagielski                     aScaleData.AxisType = cssc2::AxisType::REALNUMBER;
201*b1cdbd2cSJim Jagielski                 }
202*b1cdbd2cSJim Jagielski             break;
203*b1cdbd2cSJim Jagielski             case API_Y_AXIS:
204*b1cdbd2cSJim Jagielski                 OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" );
205*b1cdbd2cSJim Jagielski                 aScaleData.AxisType = rTypeGroup.isPercent() ? cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER;
206*b1cdbd2cSJim Jagielski             break;
207*b1cdbd2cSJim Jagielski             case API_Z_AXIS:
208*b1cdbd2cSJim Jagielski                 OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( serAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:serAx)" );
209*b1cdbd2cSJim Jagielski                 OSL_ENSURE( rTypeGroup.isDeep3dChart(), "AxisConverter::convertFromModel - series axis not supported by this chart type" );
210*b1cdbd2cSJim Jagielski                 aScaleData.AxisType = cssc2::AxisType::SERIES;
211*b1cdbd2cSJim Jagielski             break;
212*b1cdbd2cSJim Jagielski         }
213*b1cdbd2cSJim Jagielski 
214*b1cdbd2cSJim Jagielski         // axis scaling and increment -----------------------------------------
215*b1cdbd2cSJim Jagielski 
216*b1cdbd2cSJim Jagielski         switch( aScaleData.AxisType )
217*b1cdbd2cSJim Jagielski         {
218*b1cdbd2cSJim Jagielski             case cssc2::AxisType::CATEGORY:
219*b1cdbd2cSJim Jagielski             case cssc2::AxisType::SERIES:
220*b1cdbd2cSJim Jagielski             case cssc2::AxisType::DATE:
221*b1cdbd2cSJim Jagielski             {
222*b1cdbd2cSJim Jagielski                 /*  Determine date axis type from XML type identifier, and not
223*b1cdbd2cSJim Jagielski                     via aScaleData.AxisType, as this value sticks to CATEGORY
224*b1cdbd2cSJim Jagielski                     for automatic category/date axes). */
225*b1cdbd2cSJim Jagielski                 if( mrModel.mnTypeId == C_TOKEN( dateAx ) )
226*b1cdbd2cSJim Jagielski                 {
227*b1cdbd2cSJim Jagielski                     // scaling algorithm
228*b1cdbd2cSJim Jagielski                     aScaleData.Scaling.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.LinearScaling" ) ), UNO_QUERY );
229*b1cdbd2cSJim Jagielski                     // min/max
230*b1cdbd2cSJim Jagielski                     lclSetValueOrClearAny( aScaleData.Minimum, mrModel.mofMin );
231*b1cdbd2cSJim Jagielski                     lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax );
232*b1cdbd2cSJim Jagielski                     // major/minor increment
233*b1cdbd2cSJim Jagielski                     lclConvertTimeInterval( aScaleData.TimeIncrement.MajorTimeInterval, mrModel.mofMajorUnit, mrModel.mnMajorTimeUnit );
234*b1cdbd2cSJim Jagielski                     lclConvertTimeInterval( aScaleData.TimeIncrement.MinorTimeInterval, mrModel.mofMinorUnit, mrModel.mnMinorTimeUnit );
235*b1cdbd2cSJim Jagielski                     // base time unit
236*b1cdbd2cSJim Jagielski                     if( mrModel.monBaseTimeUnit.has() )
237*b1cdbd2cSJim Jagielski                         aScaleData.TimeIncrement.TimeResolution <<= lclGetApiTimeUnit( mrModel.monBaseTimeUnit.get() );
238*b1cdbd2cSJim Jagielski                     else
239*b1cdbd2cSJim Jagielski                         aScaleData.TimeIncrement.TimeResolution.clear();
240*b1cdbd2cSJim Jagielski                 }
241*b1cdbd2cSJim Jagielski                 else
242*b1cdbd2cSJim Jagielski                 {
243*b1cdbd2cSJim Jagielski                     // do not overlap text unless all labels are visible
244*b1cdbd2cSJim Jagielski                     aAxisProp.setProperty( PROP_TextOverlap, mrModel.mnTickLabelSkip == 1 );
245*b1cdbd2cSJim Jagielski                     // do not break text into several lines
246*b1cdbd2cSJim Jagielski                     aAxisProp.setProperty( PROP_TextBreak, false );
247*b1cdbd2cSJim Jagielski                     // do not stagger labels in two lines
248*b1cdbd2cSJim Jagielski                     aAxisProp.setProperty( PROP_ArrangeOrder, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
249*b1cdbd2cSJim Jagielski                     //! TODO #i58731# show n-th category
250*b1cdbd2cSJim Jagielski                 }
251*b1cdbd2cSJim Jagielski             }
252*b1cdbd2cSJim Jagielski             break;
253*b1cdbd2cSJim Jagielski             case cssc2::AxisType::REALNUMBER:
254*b1cdbd2cSJim Jagielski             case cssc2::AxisType::PERCENT:
255*b1cdbd2cSJim Jagielski             {
256*b1cdbd2cSJim Jagielski                 // scaling algorithm
257*b1cdbd2cSJim Jagielski                 bool bLogScale = lclIsLogarithmicScale( mrModel );
258*b1cdbd2cSJim Jagielski                 OUString aScalingService = bLogScale ?
259*b1cdbd2cSJim Jagielski                     CREATE_OUSTRING( "com.sun.star.chart2.LogarithmicScaling" ) :
260*b1cdbd2cSJim Jagielski                     CREATE_OUSTRING( "com.sun.star.chart2.LinearScaling" );
261*b1cdbd2cSJim Jagielski                 aScaleData.Scaling.set( createInstance( aScalingService ), UNO_QUERY );
262*b1cdbd2cSJim Jagielski                 // min/max
263*b1cdbd2cSJim Jagielski                 lclSetValueOrClearAny( aScaleData.Minimum, mrModel.mofMin );
264*b1cdbd2cSJim Jagielski                 lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax );
265*b1cdbd2cSJim Jagielski                 // major increment
266*b1cdbd2cSJim Jagielski                 IncrementData& rIncrementData = aScaleData.IncrementData;
267*b1cdbd2cSJim Jagielski                 if( mrModel.mofMajorUnit.has() && aScaleData.Scaling.is() )
268*b1cdbd2cSJim Jagielski                     rIncrementData.Distance <<= aScaleData.Scaling->doScaling( mrModel.mofMajorUnit.get() );
269*b1cdbd2cSJim Jagielski                 else
270*b1cdbd2cSJim Jagielski                     lclSetValueOrClearAny( rIncrementData.Distance, mrModel.mofMajorUnit );
271*b1cdbd2cSJim Jagielski                 // minor increment
272*b1cdbd2cSJim Jagielski                 Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
273*b1cdbd2cSJim Jagielski                 rSubIncrementSeq.realloc( 1 );
274*b1cdbd2cSJim Jagielski                 Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount;
275*b1cdbd2cSJim Jagielski                 rIntervalCount.clear();
276*b1cdbd2cSJim Jagielski                 if( bLogScale )
277*b1cdbd2cSJim Jagielski                 {
278*b1cdbd2cSJim Jagielski                     if( mrModel.mofMinorUnit.has() )
279*b1cdbd2cSJim Jagielski                         rIntervalCount <<= sal_Int32( 9 );
280*b1cdbd2cSJim Jagielski                 }
281*b1cdbd2cSJim Jagielski                 else if( mrModel.mofMajorUnit.has() && mrModel.mofMinorUnit.has() && (0.0 < mrModel.mofMinorUnit.get()) && (mrModel.mofMinorUnit.get() <= mrModel.mofMajorUnit.get()) )
282*b1cdbd2cSJim Jagielski                 {
283*b1cdbd2cSJim Jagielski                     double fCount = mrModel.mofMajorUnit.get() / mrModel.mofMinorUnit.get() + 0.5;
284*b1cdbd2cSJim Jagielski                     if( (1.0 <= fCount) && (fCount < 1001.0) )
285*b1cdbd2cSJim Jagielski                         rIntervalCount <<= static_cast< sal_Int32 >( fCount );
286*b1cdbd2cSJim Jagielski                 }
287*b1cdbd2cSJim Jagielski             }
288*b1cdbd2cSJim Jagielski             break;
289*b1cdbd2cSJim Jagielski             default:
290*b1cdbd2cSJim Jagielski                 OSL_ENSURE( false, "AxisConverter::convertFromModel - unknown axis type" );
291*b1cdbd2cSJim Jagielski         }
292*b1cdbd2cSJim Jagielski 
293*b1cdbd2cSJim Jagielski         /*  Do not set a value to the Origin member anymore (already done via
294*b1cdbd2cSJim Jagielski             new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
295*b1cdbd2cSJim Jagielski         aScaleData.Origin.clear();
296*b1cdbd2cSJim Jagielski 
297*b1cdbd2cSJim Jagielski         // axis orientation ---------------------------------------------------
298*b1cdbd2cSJim Jagielski 
299*b1cdbd2cSJim Jagielski         // #i85167# pie/donut charts need opposite direction at Y axis
300*b1cdbd2cSJim Jagielski         // #i87747# radar charts need opposite direction at X axis
301*b1cdbd2cSJim Jagielski         bool bMirrorDirection =
302*b1cdbd2cSJim Jagielski             ((nAxisIdx == API_Y_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE)) ||
303*b1cdbd2cSJim Jagielski             ((nAxisIdx == API_X_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_RADAR));
304*b1cdbd2cSJim Jagielski         bool bReverse = (mrModel.mnOrientation == XML_maxMin) != bMirrorDirection;
305*b1cdbd2cSJim Jagielski         aScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
306*b1cdbd2cSJim Jagielski 
307*b1cdbd2cSJim Jagielski         // write back scaling data
308*b1cdbd2cSJim Jagielski         xAxis->setScaleData( aScaleData );
309*b1cdbd2cSJim Jagielski 
310*b1cdbd2cSJim Jagielski         // number format ------------------------------------------------------
311*b1cdbd2cSJim Jagielski 
312*b1cdbd2cSJim Jagielski         if( (aScaleData.AxisType == cssc2::AxisType::REALNUMBER) || (aScaleData.AxisType == cssc2::AxisType::PERCENT) )
313*b1cdbd2cSJim Jagielski             getFormatter().convertNumberFormat( aAxisProp, mrModel.maNumberFormat );
314*b1cdbd2cSJim Jagielski 
315*b1cdbd2cSJim Jagielski         // position of crossing axis ------------------------------------------
316*b1cdbd2cSJim Jagielski 
317*b1cdbd2cSJim Jagielski         bool bManualCrossing = mrModel.mofCrossesAt.has();
318*b1cdbd2cSJim Jagielski         cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE;
319*b1cdbd2cSJim Jagielski         if( !bManualCrossing ) switch( mrModel.mnCrossMode )
320*b1cdbd2cSJim Jagielski         {
321*b1cdbd2cSJim Jagielski             case XML_min:       eAxisPos = cssc::ChartAxisPosition_START;   break;
322*b1cdbd2cSJim Jagielski             case XML_max:       eAxisPos = cssc::ChartAxisPosition_END;     break;
323*b1cdbd2cSJim Jagielski             case XML_autoZero:  eAxisPos = cssc::ChartAxisPosition_VALUE;   break;
324*b1cdbd2cSJim Jagielski         }
325*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_CrossoverPosition, eAxisPos );
326*b1cdbd2cSJim Jagielski 
327*b1cdbd2cSJim Jagielski         // calculate automatic origin depending on scaling mode of crossing axis
328*b1cdbd2cSJim Jagielski         bool bCrossingLogScale = pCrossingAxis && lclIsLogarithmicScale( *pCrossingAxis );
329*b1cdbd2cSJim Jagielski         double fCrossingPos = bManualCrossing ? mrModel.mofCrossesAt.get() : (bCrossingLogScale ? 1.0 : 0.0);
330*b1cdbd2cSJim Jagielski         aAxisProp.setProperty( PROP_CrossoverValue, fCrossingPos );
331*b1cdbd2cSJim Jagielski 
332*b1cdbd2cSJim Jagielski         // axis title ---------------------------------------------------------
333*b1cdbd2cSJim Jagielski 
334*b1cdbd2cSJim Jagielski         // in radar charts, title objects may exist, but are not shown
335*b1cdbd2cSJim Jagielski         if( mrModel.mxTitle.is() && (rTypeGroup.getTypeInfo().meTypeCategory != TYPECATEGORY_RADAR) )
336*b1cdbd2cSJim Jagielski         {
337*b1cdbd2cSJim Jagielski             Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW );
338*b1cdbd2cSJim Jagielski             TitleConverter aTitleConv( *this, *mrModel.mxTitle );
339*b1cdbd2cSJim Jagielski             aTitleConv.convertFromModel( xTitled, CREATE_OUSTRING( "Axis Title" ), OBJECTTYPE_AXISTITLE, nAxesSetIdx, nAxisIdx );
340*b1cdbd2cSJim Jagielski         }
341*b1cdbd2cSJim Jagielski     }
342*b1cdbd2cSJim Jagielski     catch( Exception& )
343*b1cdbd2cSJim Jagielski     {
344*b1cdbd2cSJim Jagielski     }
345*b1cdbd2cSJim Jagielski 
346*b1cdbd2cSJim Jagielski     if( xAxis.is() && rxCoordSystem.is() ) try
347*b1cdbd2cSJim Jagielski     {
348*b1cdbd2cSJim Jagielski         // insert axis into coordinate system
349*b1cdbd2cSJim Jagielski         rxCoordSystem->setAxisByDimension( nAxisIdx, xAxis, nAxesSetIdx );
350*b1cdbd2cSJim Jagielski     }
351*b1cdbd2cSJim Jagielski     catch( Exception& )
352*b1cdbd2cSJim Jagielski     {
353*b1cdbd2cSJim Jagielski         OSL_ENSURE( false, "AxisConverter::convertFromModel - cannot insert axis into coordinate system" );
354*b1cdbd2cSJim Jagielski     }
355*b1cdbd2cSJim Jagielski }
356*b1cdbd2cSJim Jagielski 
357*b1cdbd2cSJim Jagielski // ============================================================================
358*b1cdbd2cSJim Jagielski 
359*b1cdbd2cSJim Jagielski } // namespace chart
360*b1cdbd2cSJim Jagielski } // namespace drawingml
361*b1cdbd2cSJim Jagielski } // namespace oox
362