tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / chart2 / source / view / axes / VAxisProperties.cxx
blob11456dc412eaf0442e87246cf607deecfb244943
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
21 #include <ViewDefines.hxx>
22 #include <Axis.hxx>
23 #include <AxisHelper.hxx>
24 #include <ChartModelHelper.hxx>
25 #include <ExplicitCategoriesProvider.hxx>
27 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
28 #include <com/sun/star/chart2/AxisType.hpp>
30 #include <comphelper/diagnose_ex.hxx>
31 #include <rtl/math.hxx>
32 #include <utility>
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::chart2;
37 namespace chart {
39 AxisLabelAlignment::AxisLabelAlignment() :
40 mfLabelDirection(1.0),
41 mfInnerTickDirection(1.0),
42 meAlignment(LABEL_ALIGN_RIGHT_TOP) {}
44 static sal_Int32 lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle)
46 sal_Int32 const nWidth = AXIS2D_TICKLENGTH; //@maybefuturetodo this length could be offered by the model
47 double fPercent = 1.0;
48 switch(nDepth)
50 case 0:
51 fPercent = 1.0;
52 break;
53 case 1:
54 fPercent = 0.75;//percentage like in the old chart
55 break;
56 case 2:
57 fPercent = 0.5;
58 break;
59 default:
60 fPercent = 0.3;
61 break;
63 if(nTickmarkStyle==3)//inner and outer tickmarks
64 fPercent*=2.0;
65 return static_cast<sal_Int32>(nWidth*fPercent);
68 static double lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle)
70 double fPercent = 0.0; //0<=fPercent<=1
71 //0.0: completely inner
72 //1.0: completely outer
73 //0.5: half and half
76 nTickmarkStyle:
77 1: inner tickmarks
78 2: outer tickmarks
79 3: inner and outer tickmarks
81 switch(nTickmarkStyle)
83 case 1:
84 fPercent = 0.0;
85 break;
86 case 2:
87 fPercent = 1.0;
88 break;
89 default:
90 fPercent = 0.5;
91 break;
93 return fPercent*nLength;
96 TickmarkProperties AxisProperties::makeTickmarkProperties(
97 sal_Int32 nDepth ) const
100 nTickmarkStyle:
101 1: inner tickmarks
102 2: outer tickmarks
103 3: inner and outer tickmarks
105 sal_Int32 nTickmarkStyle = 1;
106 if(nDepth==0)
108 nTickmarkStyle = m_nMajorTickmarks;
109 if(!nTickmarkStyle)
111 //create major tickmarks as if they were minor tickmarks
112 nDepth = 1;
113 nTickmarkStyle = m_nMinorTickmarks;
116 else if( nDepth==1)
118 nTickmarkStyle = m_nMinorTickmarks;
121 if (maLabelAlignment.mfInnerTickDirection == 0.0)
123 if( nTickmarkStyle != 0 )
124 nTickmarkStyle = 3; //inner and outer tickmarks
127 TickmarkProperties aTickmarkProperties;
128 aTickmarkProperties.Length = lcl_calcTickLengthForDepth(nDepth,nTickmarkStyle);
129 aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length,nTickmarkStyle));
130 aTickmarkProperties.aLineProperties = makeLinePropertiesForDepth();
131 return aTickmarkProperties;
134 TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories(
135 sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis ) const
137 sal_Int32 nTickmarkStyle = (maLabelAlignment.mfLabelDirection == maLabelAlignment.mfInnerTickDirection) ? 2/*outside*/ : 1/*inside*/;
139 TickmarkProperties aTickmarkProperties;
140 aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) );
141 aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle));
142 aTickmarkProperties.aLineProperties = makeLinePropertiesForDepth();
143 return aTickmarkProperties;
146 TickmarkProperties AxisProperties::getBiggestTickmarkProperties()
148 TickmarkProperties aTickmarkProperties;
149 sal_Int32 nTickmarkStyle = 3;//inner and outer tickmarks
150 aTickmarkProperties.Length = lcl_calcTickLengthForDepth( 0/*nDepth*/,nTickmarkStyle );
151 aTickmarkProperties.RelativePos = static_cast<sal_Int32>( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) );
152 return aTickmarkProperties;
155 AxisProperties::AxisProperties(rtl::Reference<::chart::Axis> xAxisModel,
156 ExplicitCategoriesProvider* pExplicitCategoriesProvider,
157 rtl::Reference<::chart::DataTable> const& xDataTableModel)
158 : m_xAxisModel(std::move(xAxisModel))
159 , m_nDimensionIndex(0)
160 , m_bIsMainAxis(true)
161 , m_bSwapXAndY(false)
162 , m_eCrossoverType( css::chart::ChartAxisPosition_ZERO )
163 , m_eLabelPos( css::chart::ChartAxisLabelPosition_NEAR_AXIS )
164 , m_eTickmarkPos( css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
165 , m_bCrossingAxisHasReverseDirection(false)
166 , m_bCrossingAxisIsCategoryAxes(false)
167 , m_bDisplayDataTable(false)
168 , m_bDataTableAlignAxisValuesWithColumns(false)
169 , m_bDisplayLabels( true )
170 , m_bTryStaggeringFirst( false )
171 , m_nNumberFormatKey(0)
172 , m_nMajorTickmarks(1)
173 , m_nMinorTickmarks(1)
174 , m_nAxisType(AxisType::REALNUMBER)
175 , m_bComplexCategories(false)
176 , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider)
177 , m_bLimitSpaceForLabels(false)
178 , m_xDataTableModel(xDataTableModel)
182 static LabelAlignment lcl_getLabelAlignmentForZAxis( const AxisProperties& rAxisProperties )
184 LabelAlignment aRet( LABEL_ALIGN_RIGHT );
185 if (rAxisProperties.maLabelAlignment.mfLabelDirection < 0)
186 aRet = LABEL_ALIGN_LEFT;
187 return aRet;
190 static LabelAlignment lcl_getLabelAlignmentForYAxis( const AxisProperties& rAxisProperties )
192 LabelAlignment aRet( LABEL_ALIGN_RIGHT );
193 if (rAxisProperties.maLabelAlignment.mfLabelDirection < 0)
194 aRet = LABEL_ALIGN_LEFT;
195 return aRet;
198 static LabelAlignment lcl_getLabelAlignmentForXAxis( const AxisProperties& rAxisProperties )
200 LabelAlignment aRet( LABEL_ALIGN_BOTTOM );
201 if (rAxisProperties.maLabelAlignment.mfLabelDirection < 0)
202 aRet = LABEL_ALIGN_TOP;
203 return aRet;
206 void AxisProperties::initAxisPositioning( const uno::Reference< beans::XPropertySet >& xAxisProp )
208 if( !xAxisProp.is() )
209 return;
212 if( AxisHelper::isAxisPositioningEnabled() )
214 xAxisProp->getPropertyValue(u"CrossoverPosition"_ustr) >>= m_eCrossoverType;
215 if( m_eCrossoverType == css::chart::ChartAxisPosition_VALUE )
217 double fValue = 0.0;
218 xAxisProp->getPropertyValue(u"CrossoverValue"_ustr) >>= fValue;
220 if( m_bCrossingAxisIsCategoryAxes )
221 fValue = ::rtl::math::round(fValue);
222 m_pfMainLinePositionAtOtherAxis = fValue;
224 else if( m_eCrossoverType == css::chart::ChartAxisPosition_ZERO )
225 m_pfMainLinePositionAtOtherAxis = 0.0;
227 xAxisProp->getPropertyValue(u"LabelPosition"_ustr) >>= m_eLabelPos;
228 xAxisProp->getPropertyValue(u"MarkPosition"_ustr) >>= m_eTickmarkPos;
230 else
232 m_eCrossoverType = css::chart::ChartAxisPosition_START;
233 if( m_bIsMainAxis == m_bCrossingAxisHasReverseDirection )
234 m_eCrossoverType = css::chart::ChartAxisPosition_END;
235 m_eLabelPos = css::chart::ChartAxisLabelPosition_NEAR_AXIS;
236 m_eTickmarkPos = css::chart::ChartAxisMarkPosition_AT_LABELS;
239 catch( const uno::Exception& )
241 TOOLS_WARN_EXCEPTION("chart2", "" );
245 void AxisProperties::init( bool bCartesian )
247 if( !m_xAxisModel.is() )
248 return;
250 if( m_nDimensionIndex<2 )
251 initAxisPositioning( m_xAxisModel );
253 ScaleData aScaleData = m_xAxisModel->getScaleData();
254 if( m_nDimensionIndex==0 )
255 AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian );
256 m_nAxisType = aScaleData.AxisType;
258 if( bCartesian )
260 if ((!m_bSwapXAndY && m_nDimensionIndex == 0) || (m_bSwapXAndY && m_nDimensionIndex == 1))
262 m_bDisplayDataTable = m_xDataTableModel.is();
265 if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY
266 && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() )
267 m_bComplexCategories = true;
269 if( m_eCrossoverType == css::chart::ChartAxisPosition_END )
270 maLabelAlignment.mfInnerTickDirection = m_bCrossingAxisHasReverseDirection ? 1.0 : -1.0;
271 else
272 maLabelAlignment.mfInnerTickDirection = m_bCrossingAxisHasReverseDirection ? -1.0 : 1.0;
274 if( m_eLabelPos == css::chart::ChartAxisLabelPosition_NEAR_AXIS )
275 maLabelAlignment.mfLabelDirection = maLabelAlignment.mfInnerTickDirection;
276 else if( m_eLabelPos == css::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE )
277 maLabelAlignment.mfLabelDirection = -maLabelAlignment.mfInnerTickDirection;
278 else if( m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START )
279 maLabelAlignment.mfLabelDirection = m_bCrossingAxisHasReverseDirection ? -1 : 1;
280 else if( m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END )
281 maLabelAlignment.mfLabelDirection = m_bCrossingAxisHasReverseDirection ? 1 : -1;
283 if( m_nDimensionIndex==2 )
284 maLabelAlignment.meAlignment = lcl_getLabelAlignmentForZAxis(*this);
285 else
287 bool bIsYAxisPosition = (m_nDimensionIndex==1 && !m_bSwapXAndY)
288 || (m_nDimensionIndex==0 && m_bSwapXAndY);
289 if( bIsYAxisPosition )
291 maLabelAlignment.mfLabelDirection *= -1.0;
292 maLabelAlignment.mfInnerTickDirection *= -1.0;
294 maLabelAlignment.meAlignment = lcl_getLabelAlignmentForYAxis(*this);
296 else
297 maLabelAlignment.meAlignment = lcl_getLabelAlignmentForXAxis(*this);
303 //init LineProperties
304 m_aLineProperties.initFromPropertySet( m_xAxisModel );
306 //init display labels
307 m_xAxisModel->getPropertyValue( u"DisplayLabels"_ustr ) >>= m_bDisplayLabels;
309 // Init layout strategy hint for axis labels.
310 // Compatibility option: starting from LibreOffice 5.1 the rotated
311 // layout is preferred to staggering for axis labels.
312 m_xAxisModel->getPropertyValue( u"TryStaggeringFirst"_ustr ) >>= m_bTryStaggeringFirst;
314 //init TickmarkProperties
315 m_xAxisModel->getPropertyValue( u"MajorTickmarks"_ustr ) >>= m_nMajorTickmarks;
316 m_xAxisModel->getPropertyValue( u"MinorTickmarks"_ustr ) >>= m_nMinorTickmarks;
318 sal_Int32 nMaxDepth = 0;
319 if(m_nMinorTickmarks!=0)
320 nMaxDepth=2;
321 else if(m_nMajorTickmarks!=0)
322 nMaxDepth=1;
324 m_aTickmarkPropertiesList.clear();
325 for( sal_Int32 nDepth=0; nDepth<nMaxDepth; nDepth++ )
327 TickmarkProperties aTickmarkProperties = makeTickmarkProperties( nDepth );
328 m_aTickmarkPropertiesList.push_back( aTickmarkProperties );
331 catch( const uno::Exception& )
333 TOOLS_WARN_EXCEPTION("chart2", "" );
336 if (m_bDisplayDataTable)
338 m_bDataTableAlignAxisValuesWithColumns = (m_nDimensionIndex == 0);
340 if (m_nDimensionIndex == 0)
342 m_bDisplayLabels = false;
348 AxisLabelProperties::AxisLabelProperties()
349 : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() )
350 , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height )
351 , m_nNumberFormatKey(0)
352 , m_eStaggering( AxisLabelStaggering::SideBySide )
353 , m_bLineBreakAllowed( false )
354 , m_bOverlapAllowed( false )
355 , m_bStackCharacters( false )
356 , m_fRotationAngleDegree( 0.0 )
357 , m_nRhythm( 1 )
362 void AxisLabelProperties::init( const rtl::Reference< Axis >& xAxisModel )
364 if(!xAxisModel.is())
365 return;
369 xAxisModel->getPropertyValue( u"TextBreak"_ustr ) >>= m_bLineBreakAllowed;
370 xAxisModel->getPropertyValue( u"TextOverlap"_ustr ) >>= m_bOverlapAllowed;
371 xAxisModel->getPropertyValue( u"StackCharacters"_ustr ) >>= m_bStackCharacters;
372 xAxisModel->getPropertyValue( u"TextRotation"_ustr ) >>= m_fRotationAngleDegree;
374 css::chart::ChartAxisArrangeOrderType eArrangeOrder;
375 xAxisModel->getPropertyValue( u"ArrangeOrder"_ustr ) >>= eArrangeOrder;
376 switch(eArrangeOrder)
378 case css::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE:
379 m_eStaggering = AxisLabelStaggering::SideBySide;
380 break;
381 case css::chart::ChartAxisArrangeOrderType_STAGGER_EVEN:
382 m_eStaggering = AxisLabelStaggering::StaggerEven;
383 break;
384 case css::chart::ChartAxisArrangeOrderType_STAGGER_ODD:
385 m_eStaggering = AxisLabelStaggering::StaggerOdd;
386 break;
387 default:
388 m_eStaggering = AxisLabelStaggering::StaggerAuto;
389 break;
392 catch( const uno::Exception& )
394 TOOLS_WARN_EXCEPTION("chart2", "" );
398 bool AxisLabelProperties::isStaggered() const
400 return ( m_eStaggering == AxisLabelStaggering::StaggerOdd || m_eStaggering == AxisLabelStaggering::StaggerEven );
403 void AxisLabelProperties::autoRotate45()
405 m_fRotationAngleDegree = 45;
406 m_bLineBreakAllowed = false;
407 m_eStaggering = AxisLabelStaggering::SideBySide;
410 } //namespace chart
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */