1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "VAxisProperties.hxx"
22 #include "ViewDefines.hxx"
23 #include "CommonConverters.hxx"
24 #include "AxisHelper.hxx"
25 #include "DiagramHelper.hxx"
26 #include "ChartModelHelper.hxx"
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
30 #include <com/sun/star/drawing/LineStyle.hpp>
31 #include <com/sun/star/text/WritingMode2.hpp>
33 using namespace ::com::sun::star
;
34 using namespace ::com::sun::star::chart2
;
38 AxisLabelAlignment::AxisLabelAlignment() :
39 mfLabelDirection(1.0),
40 mfInnerTickDirection(1.0),
41 meAlignment(LABEL_ALIGN_RIGHT_TOP
) {}
43 sal_Int32
lcl_calcTickLengthForDepth(sal_Int32 nDepth
,sal_Int32 nTickmarkStyle
)
45 sal_Int32 nWidth
= AXIS2D_TICKLENGTH
; //@maybefuturetodo this length could be offered by the model
46 double fPercent
= 1.0;
53 fPercent
= 0.75;//percentage like in the old chart
62 if(nTickmarkStyle
==3)//inner and outer tickmarks
64 return static_cast<sal_Int32
>(nWidth
*fPercent
);
67 double lcl_getTickOffset(sal_Int32 nLength
,sal_Int32 nTickmarkStyle
)
69 double fPercent
= 0.0; //0<=fPercent<=1
70 //0.0: completely inner
71 //1.0: completely outer
78 3: inner and outer tickmarks
80 switch(nTickmarkStyle
)
92 return fPercent
*nLength
;
95 TickmarkProperties
AxisProperties::makeTickmarkProperties(
96 sal_Int32 nDepth
) const
102 3: inner and outer tickmarks
104 sal_Int32 nTickmarkStyle
= 1;
107 nTickmarkStyle
= m_nMajorTickmarks
;
110 //create major tickmarks as if they were minor tickmarks
112 nTickmarkStyle
= m_nMinorTickmarks
;
117 nTickmarkStyle
= m_nMinorTickmarks
;
120 if (maLabelAlignment
.mfInnerTickDirection
== 0.0)
122 if( nTickmarkStyle
!= 0 )
123 nTickmarkStyle
= 3; //inner and outer tickmarks
126 TickmarkProperties aTickmarkProperties
;
127 aTickmarkProperties
.Length
= lcl_calcTickLengthForDepth(nDepth
,nTickmarkStyle
);
128 aTickmarkProperties
.RelativePos
= static_cast<sal_Int32
>(lcl_getTickOffset(aTickmarkProperties
.Length
,nTickmarkStyle
));
129 aTickmarkProperties
.aLineProperties
= this->makeLinePropertiesForDepth( nDepth
);
130 return aTickmarkProperties
;
133 TickmarkProperties
AxisProperties::makeTickmarkPropertiesForComplexCategories(
134 sal_Int32 nTickLength
, sal_Int32 nTickStartDistanceToAxis
, sal_Int32
/*nTextLevel*/ ) const
136 sal_Int32 nTickmarkStyle
= (maLabelAlignment
.mfLabelDirection
== maLabelAlignment
.mfInnerTickDirection
) ? 2/*outside*/ : 1/*inside*/;
138 TickmarkProperties aTickmarkProperties
;
139 aTickmarkProperties
.Length
= nTickLength
;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) );
140 aTickmarkProperties
.RelativePos
= static_cast<sal_Int32
>(lcl_getTickOffset(aTickmarkProperties
.Length
+nTickStartDistanceToAxis
,nTickmarkStyle
));
141 aTickmarkProperties
.aLineProperties
= this->makeLinePropertiesForDepth( 0 );
142 return aTickmarkProperties
;
145 TickmarkProperties
AxisProperties::getBiggestTickmarkProperties()
147 TickmarkProperties aTickmarkProperties
;
148 sal_Int32 nDepth
= 0;
149 sal_Int32 nTickmarkStyle
= 3;//inner and outer tickmarks
150 aTickmarkProperties
.Length
= lcl_calcTickLengthForDepth( nDepth
,nTickmarkStyle
);
151 aTickmarkProperties
.RelativePos
= static_cast<sal_Int32
>( lcl_getTickOffset( aTickmarkProperties
.Length
, nTickmarkStyle
) );
152 return aTickmarkProperties
;
155 AxisProperties::AxisProperties( const uno::Reference
< XAxis
>& xAxisModel
156 , ExplicitCategoriesProvider
* pExplicitCategoriesProvider
)
157 : m_xAxisModel(xAxisModel
)
158 , m_nDimensionIndex(0)
159 , m_bIsMainAxis(true)
160 , m_bSwapXAndY(false)
161 , m_eCrossoverType( ::com::sun::star::chart::ChartAxisPosition_ZERO
)
162 , m_eLabelPos( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS
)
163 , m_eTickmarkPos( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS
)
164 , m_bCrossingAxisHasReverseDirection(false)
165 , m_bCrossingAxisIsCategoryAxes(false)
166 , m_bDisplayLabels( true )
167 , m_nNumberFormatKey(0)
168 , m_nMajorTickmarks(1)
169 , m_nMinorTickmarks(1)
170 , m_aTickmarkPropertiesList()
171 , m_aLineProperties()
173 , m_nAxisType(AxisType::REALNUMBER
)
174 , m_bComplexCategories(false)
175 , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider
)
176 , m_xAxisTextProvider(0)
180 AxisProperties::AxisProperties( const AxisProperties
& rAxisProperties
)
181 : m_xAxisModel( rAxisProperties
.m_xAxisModel
)
182 , m_nDimensionIndex( rAxisProperties
.m_nDimensionIndex
)
183 , m_bIsMainAxis( rAxisProperties
.m_bIsMainAxis
)
184 , m_bSwapXAndY( rAxisProperties
.m_bSwapXAndY
)
185 , m_eCrossoverType( rAxisProperties
.m_eCrossoverType
)
186 , m_eLabelPos( rAxisProperties
.m_eLabelPos
)
187 , m_eTickmarkPos( rAxisProperties
.m_eTickmarkPos
)
188 , m_bCrossingAxisHasReverseDirection( rAxisProperties
.m_bCrossingAxisHasReverseDirection
)
189 , m_bCrossingAxisIsCategoryAxes( rAxisProperties
.m_bCrossingAxisIsCategoryAxes
)
190 , maLabelAlignment( rAxisProperties
.maLabelAlignment
)
191 , m_bDisplayLabels( rAxisProperties
.m_bDisplayLabels
)
192 , m_nNumberFormatKey( rAxisProperties
.m_nNumberFormatKey
)
193 , m_nMajorTickmarks( rAxisProperties
.m_nMajorTickmarks
)
194 , m_nMinorTickmarks( rAxisProperties
.m_nMinorTickmarks
)
195 , m_aTickmarkPropertiesList( rAxisProperties
.m_aTickmarkPropertiesList
)
196 , m_aLineProperties( rAxisProperties
.m_aLineProperties
)
198 , m_nAxisType( rAxisProperties
.m_nAxisType
)
199 , m_bComplexCategories( rAxisProperties
.m_bComplexCategories
)
200 , m_pExplicitCategoriesProvider( rAxisProperties
.m_pExplicitCategoriesProvider
)
201 , m_xAxisTextProvider( rAxisProperties
.m_xAxisTextProvider
)
203 if( rAxisProperties
.m_pfMainLinePositionAtOtherAxis
)
204 m_pfMainLinePositionAtOtherAxis
.reset(*rAxisProperties
.m_pfMainLinePositionAtOtherAxis
);
205 if( rAxisProperties
.m_pfExrtaLinePositionAtOtherAxis
)
206 m_pfExrtaLinePositionAtOtherAxis
.reset(*rAxisProperties
.m_pfExrtaLinePositionAtOtherAxis
);
209 LabelAlignment
lcl_getLabelAlignmentForZAxis( const AxisProperties
& rAxisProperties
)
211 LabelAlignment
aRet( LABEL_ALIGN_RIGHT
);
212 if (rAxisProperties
.maLabelAlignment
.mfLabelDirection
< 0)
213 aRet
= LABEL_ALIGN_LEFT
;
217 LabelAlignment
lcl_getLabelAlignmentForYAxis( const AxisProperties
& rAxisProperties
)
219 LabelAlignment
aRet( LABEL_ALIGN_RIGHT
);
220 if (rAxisProperties
.maLabelAlignment
.mfLabelDirection
< 0)
221 aRet
= LABEL_ALIGN_LEFT
;
225 LabelAlignment
lcl_getLabelAlignmentForXAxis( const AxisProperties
& rAxisProperties
)
227 LabelAlignment
aRet( LABEL_ALIGN_BOTTOM
);
228 if (rAxisProperties
.maLabelAlignment
.mfLabelDirection
< 0)
229 aRet
= LABEL_ALIGN_TOP
;
233 void AxisProperties::initAxisPositioning( const uno::Reference
< beans::XPropertySet
>& xAxisProp
)
235 if( !xAxisProp
.is() )
239 if( AxisHelper::isAxisPositioningEnabled() )
241 xAxisProp
->getPropertyValue("CrossoverPosition") >>= m_eCrossoverType
;
242 if( ::com::sun::star::chart::ChartAxisPosition_VALUE
== m_eCrossoverType
)
245 xAxisProp
->getPropertyValue("CrossoverValue") >>= fValue
;
247 if( m_bCrossingAxisIsCategoryAxes
)
248 fValue
= ::rtl::math::round(fValue
);
249 m_pfMainLinePositionAtOtherAxis
.reset(fValue
);
251 else if( ::com::sun::star::chart::ChartAxisPosition_ZERO
== m_eCrossoverType
)
252 m_pfMainLinePositionAtOtherAxis
.reset(0.0);
254 xAxisProp
->getPropertyValue("LabelPosition") >>= m_eLabelPos
;
255 xAxisProp
->getPropertyValue("MarkPosition") >>= m_eTickmarkPos
;
259 m_eCrossoverType
= ::com::sun::star::chart::ChartAxisPosition_START
;
260 if( m_bIsMainAxis
== m_bCrossingAxisHasReverseDirection
)
261 m_eCrossoverType
= ::com::sun::star::chart::ChartAxisPosition_END
;
262 m_eLabelPos
= ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS
;
263 m_eTickmarkPos
= ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS
;
266 catch( const uno::Exception
& e
)
268 ASSERT_EXCEPTION( e
);
272 void AxisProperties::init( bool bCartesian
)
274 uno::Reference
< beans::XPropertySet
> xProp
=
275 uno::Reference
<beans::XPropertySet
>::query( this->m_xAxisModel
);
279 if( m_nDimensionIndex
<2 )
280 initAxisPositioning( xProp
);
282 ScaleData aScaleData
= m_xAxisModel
->getScaleData();
283 if( m_nDimensionIndex
==0 )
284 AxisHelper::checkDateAxis( aScaleData
, m_pExplicitCategoriesProvider
, bCartesian
);
285 m_nAxisType
= aScaleData
.AxisType
;
289 if( m_nDimensionIndex
== 0 && m_nAxisType
== AxisType::CATEGORY
290 && m_pExplicitCategoriesProvider
&& m_pExplicitCategoriesProvider
->hasComplexCategories() )
291 m_bComplexCategories
= true;
293 if( ::com::sun::star::chart::ChartAxisPosition_END
== m_eCrossoverType
)
294 maLabelAlignment
.mfInnerTickDirection
= m_bCrossingAxisHasReverseDirection
? 1.0 : -1.0;
296 maLabelAlignment
.mfInnerTickDirection
= m_bCrossingAxisHasReverseDirection
? -1.0 : 1.0;
298 if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS
== m_eLabelPos
)
299 maLabelAlignment
.mfLabelDirection
= maLabelAlignment
.mfInnerTickDirection
;
300 else if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE
== m_eLabelPos
)
301 maLabelAlignment
.mfLabelDirection
= -maLabelAlignment
.mfInnerTickDirection
;
302 else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START
== m_eLabelPos
)
303 maLabelAlignment
.mfLabelDirection
= m_bCrossingAxisHasReverseDirection
? -1 : 1;
304 else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END
== m_eLabelPos
)
305 maLabelAlignment
.mfLabelDirection
= m_bCrossingAxisHasReverseDirection
? 1 : -1;
307 if( m_nDimensionIndex
==2 )
308 maLabelAlignment
.meAlignment
= lcl_getLabelAlignmentForZAxis(*this);
311 bool bIsYAxisPosition
= (m_nDimensionIndex
==1 && !m_bSwapXAndY
)
312 || (m_nDimensionIndex
==0 && m_bSwapXAndY
);
313 if( bIsYAxisPosition
)
315 maLabelAlignment
.mfLabelDirection
*= -1.0;
316 maLabelAlignment
.mfInnerTickDirection
*= -1.0;
319 if( bIsYAxisPosition
)
320 maLabelAlignment
.meAlignment
= lcl_getLabelAlignmentForYAxis(*this);
322 maLabelAlignment
.meAlignment
= lcl_getLabelAlignmentForXAxis(*this);
328 //init LineProperties
329 m_aLineProperties
.initFromPropertySet( xProp
);
331 //init display labels
332 xProp
->getPropertyValue( "DisplayLabels" ) >>= m_bDisplayLabels
;
334 //init TickmarkProperties
335 xProp
->getPropertyValue( "MajorTickmarks" ) >>= m_nMajorTickmarks
;
336 xProp
->getPropertyValue( "MinorTickmarks" ) >>= m_nMinorTickmarks
;
338 sal_Int32 nMaxDepth
= 0;
339 if(m_nMinorTickmarks
!=0)
341 else if(m_nMajorTickmarks
!=0)
344 this->m_aTickmarkPropertiesList
.clear();
345 for( sal_Int32 nDepth
=0; nDepth
<nMaxDepth
; nDepth
++ )
347 TickmarkProperties aTickmarkProperties
= this->makeTickmarkProperties( nDepth
);
348 this->m_aTickmarkPropertiesList
.push_back( aTickmarkProperties
);
351 catch( const uno::Exception
& e
)
353 ASSERT_EXCEPTION( e
);
357 AxisLabelProperties::AxisLabelProperties()
358 : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() )
359 , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize
.Width
, m_aFontReferenceSize
.Height
)
360 , nNumberFormatKey(0)
361 , eStaggering( SIDE_BY_SIDE
)
362 , bLineBreakAllowed( false )
363 , bOverlapAllowed( false )
364 , bStackCharacters( false )
365 , fRotationAngleDegree( 0.0 )
367 , bRhythmIsFix(false)
372 void AxisLabelProperties::init( const uno::Reference
< XAxis
>& xAxisModel
)
374 uno::Reference
< beans::XPropertySet
> xProp
=
375 uno::Reference
<beans::XPropertySet
>::query( xAxisModel
);
380 xProp
->getPropertyValue( "TextBreak" ) >>= this->bLineBreakAllowed
;
381 xProp
->getPropertyValue( "TextOverlap" ) >>= this->bOverlapAllowed
;
382 xProp
->getPropertyValue( "StackCharacters" ) >>= this->bStackCharacters
;
383 xProp
->getPropertyValue( "TextRotation" ) >>= this->fRotationAngleDegree
;
385 ::com::sun::star::chart::ChartAxisArrangeOrderType eArrangeOrder
;
386 xProp
->getPropertyValue( "ArrangeOrder" ) >>= eArrangeOrder
;
387 switch(eArrangeOrder
)
389 case ::com::sun::star::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE
:
390 this->eStaggering
= SIDE_BY_SIDE
;
392 case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_EVEN
:
393 this->eStaggering
= STAGGER_EVEN
;
395 case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_ODD
:
396 this->eStaggering
= STAGGER_ODD
;
399 this->eStaggering
= STAGGER_AUTO
;
403 catch( const uno::Exception
& e
)
405 ASSERT_EXCEPTION( e
);
410 bool AxisLabelProperties::isStaggered() const
412 return ( STAGGER_ODD
== eStaggering
|| STAGGER_EVEN
== eStaggering
);
415 void AxisLabelProperties::autoRotate45()
417 fRotationAngleDegree
= 45;
418 bLineBreakAllowed
= false;
419 eStaggering
= SIDE_BY_SIDE
;
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */