tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / chart2 / source / view / axes / VCoordinateSystem.cxx
blob86d9c485fec70d259e868a2c6d81bb619cdd2e18
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 <BaseGFXHelper.hxx>
21 #include <DateHelper.hxx>
22 #include <VCoordinateSystem.hxx>
23 #include "VCartesianCoordinateSystem.hxx"
24 #include "VPolarCoordinateSystem.hxx"
25 #include <BaseCoordinateSystem.hxx>
26 #include <GridProperties.hxx>
27 #include <ChartModel.hxx>
28 #include <ScaleAutomatism.hxx>
29 #include <ShapeFactory.hxx>
30 #include <servicenames_coosystems.hxx>
31 #include <ObjectIdentifier.hxx>
32 #include <ExplicitCategoriesProvider.hxx>
33 #include <Axis.hxx>
34 #include "VAxisBase.hxx"
35 #include <defines.hxx>
36 #include <chartview/ExplicitValueProvider.hxx>
37 #include <com/sun/star/chart/TimeUnit.hpp>
38 #include <com/sun/star/chart2/AxisType.hpp>
39 #include <rtl/math.hxx>
40 #include <comphelper/diagnose_ex.hxx>
42 #include <algorithm>
43 #include <limits>
44 #include <utility>
46 namespace chart
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::chart2;
50 using ::com::sun::star::uno::Reference;
51 using ::com::sun::star::uno::Sequence;
53 std::unique_ptr<VCoordinateSystem> VCoordinateSystem::createCoordinateSystem(
54 const rtl::Reference< BaseCoordinateSystem >& xCooSysModel )
56 if( !xCooSysModel.is() )
57 return nullptr;
59 OUString aViewServiceName = xCooSysModel->getViewServiceName();
61 //@todo: in future the coordinatesystems should be instantiated via service factory
62 std::unique_ptr<VCoordinateSystem> pRet;
63 if( aViewServiceName == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME )
64 pRet.reset( new VCartesianCoordinateSystem(xCooSysModel) );
65 else if( aViewServiceName == CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME )
66 pRet.reset( new VPolarCoordinateSystem(xCooSysModel) );
67 if(!pRet)
68 pRet.reset( new VCoordinateSystem(xCooSysModel) );
69 return pRet;
72 VCoordinateSystem::VCoordinateSystem( rtl::Reference< BaseCoordinateSystem > xCooSys )
73 : m_xCooSysModel(std::move(xCooSys))
74 , m_eLeftWallPos(CuboidPlanePosition_Left)
75 , m_eBackWallPos(CuboidPlanePosition_Back)
76 , m_eBottomPos(CuboidPlanePosition_Bottom)
77 , m_aExplicitScales(3)
78 , m_aExplicitIncrements(3)
80 if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 )
82 m_aExplicitScales[2].Minimum = 1.0;
83 m_aExplicitScales[2].Maximum = 2.0;
84 m_aExplicitScales[2].Orientation = AxisOrientation_MATHEMATICAL;
87 VCoordinateSystem::~VCoordinateSystem()
91 void VCoordinateSystem::initPlottingTargets( const rtl::Reference< SvxShapeGroupAnyD >& xLogicTarget
92 , const rtl::Reference< SvxShapeGroupAnyD >& xFinalTarget
93 , rtl::Reference<SvxShapeGroupAnyD>& xLogicTargetForSeriesBehindAxis )
95 OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is(),"no proper initialization parameters");
96 //is only allowed to be called once
98 sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
99 //create group shape for grids first thus axes are always painted above grids
100 if(nDimensionCount==2)
102 //create and add to target
103 m_xLogicTargetForGrids = ShapeFactory::createGroup2D( xLogicTarget );
104 xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup2D( xLogicTarget );
105 m_xLogicTargetForAxes = ShapeFactory::createGroup2D( xLogicTarget );
107 else
109 //create and added to target
110 m_xLogicTargetForGrids = ShapeFactory::createGroup3D( xLogicTarget );
111 xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup3D( xLogicTarget );
112 m_xLogicTargetForAxes = ShapeFactory::createGroup3D( xLogicTarget );
114 m_xFinalTarget = xFinalTarget;
117 void VCoordinateSystem::setParticle( const OUString& rCooSysParticle )
119 m_aCooSysParticle = rCooSysParticle;
122 void VCoordinateSystem::setTransformationSceneToScreen(
123 const drawing::HomogenMatrix& rMatrix )
125 m_aMatrixSceneToScreen = rMatrix;
127 //correct transformation for axis
128 for (auto const& elem : m_aAxisMap)
130 VAxisBase* pVAxis = elem.second.get();
131 if( pVAxis )
133 if(pVAxis->getDimensionCount()==2)
134 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
139 //better performance for big data
140 uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution(
141 const awt::Size& rPageSize, const awt::Size& rPageResolution )
143 uno::Sequence<sal_Int32> aResolution(
144 std::max<sal_Int32>(m_xCooSysModel->getDimension(), 2));
145 auto aResolutionRange = asNonConstRange(aResolution);
146 for( auto& i : aResolutionRange )
147 i = 1000;
149 ::basegfx::B3DTuple aScale( BaseGFXHelper::GetScaleFromMatrix(
150 BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
151 m_aMatrixSceneToScreen ) ) );
153 double fCoosysWidth = fabs(aScale.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
154 double fCoosysHeight = fabs(aScale.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
156 double fPageWidth = rPageSize.Width;
157 double fPageHeight = rPageSize.Height;
159 //factor 2 to avoid rounding problems
160 sal_Int32 nXResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Width)*fCoosysWidth/fPageWidth);
161 sal_Int32 nYResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Height)*fCoosysHeight/fPageHeight);
163 if( nXResolution < 10 )
164 nXResolution = 10;
165 if( nYResolution < 10 )
166 nYResolution = 10;
168 if( getPropertySwapXAndYAxis() )
169 std::swap(nXResolution,nYResolution);
171 //2D
172 if( aResolution.getLength() == 2 )
174 aResolutionRange[0]=nXResolution;
175 aResolutionRange[1]=nYResolution;
177 else
179 //this maybe can be optimized further ...
180 sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution );
181 nMaxResolution*=2;
182 for( auto& i : asNonConstRange(aResolution) )
183 i = nMaxResolution;
186 return aResolution;
189 rtl::Reference< Axis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
191 if( m_xCooSysModel.is() )
192 return m_xCooSysModel->getAxisByDimension2( nDimensionIndex, nAxisIndex );
193 return nullptr;
196 std::vector< rtl::Reference< ::chart::GridProperties > > VCoordinateSystem::getGridListFromAxis( const rtl::Reference< Axis >& xAxis )
198 std::vector< rtl::Reference< ::chart::GridProperties > > aRet;
200 if( xAxis.is() )
202 aRet.push_back( xAxis->getGridProperties2() );
203 std::vector<rtl::Reference<::chart::GridProperties>> aSubGrids = xAxis->getSubGridProperties2();
204 aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() );
207 return aRet;
210 void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex )
212 rDimensionIndex = std::clamp<sal_Int32>(rDimensionIndex, 0, 2);
215 void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const
217 impl_adjustDimension( rDimensionIndex );
219 if( rAxisIndex < 0 || rAxisIndex > getMaximumAxisIndexByDimension(rDimensionIndex) )
220 rAxisIndex = 0;
223 void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider /*takes ownership*/ )
225 m_apExplicitCategoriesProvider.reset(pExplicitCategoriesProvider);
228 ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider()
230 return m_apExplicitCategoriesProvider.get();
233 std::vector< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
235 std::vector< ExplicitScaleData > aRet(m_aExplicitScales);
237 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
238 aRet[nDimensionIndex]=getExplicitScale( nDimensionIndex, nAxisIndex );
240 return aRet;
243 std::vector< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
245 std::vector< ExplicitIncrementData > aRet(m_aExplicitIncrements);
247 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
248 aRet[nDimensionIndex]=getExplicitIncrement( nDimensionIndex, nAxisIndex );
250 return aRet;
253 ExplicitScaleData VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
255 ExplicitScaleData aRet;
257 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
259 if( nAxisIndex == 0)
261 aRet = m_aExplicitScales[nDimensionIndex];
263 else
265 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
266 tFullExplicitScaleMap::const_iterator aIt = m_aSecondaryExplicitScales.find( aFullAxisIndex );
267 if( aIt != m_aSecondaryExplicitScales.end() )
268 aRet = aIt->second;
269 else
270 aRet = m_aExplicitScales[nDimensionIndex];
273 return aRet;
276 ExplicitIncrementData VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
278 ExplicitIncrementData aRet;
280 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
282 if( nAxisIndex == 0)
284 aRet = m_aExplicitIncrements[nDimensionIndex];
286 else
288 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
289 tFullExplicitIncrementMap::const_iterator aIt = m_aSecondaryExplicitIncrements.find( aFullAxisIndex );
290 if( aIt != m_aSecondaryExplicitIncrements.end() )
291 aRet = aIt->second;
292 else
293 aRet = m_aExplicitIncrements[nDimensionIndex];
296 return aRet;
299 OUString VCoordinateSystem::createCIDForAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
301 OUString aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex, nAxisIndex ) );
302 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aAxisParticle );
304 OUString VCoordinateSystem::createCIDForGrid( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
306 OUString aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex, nAxisIndex ) );
307 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aGridParticle );
310 sal_Int32 VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const
312 sal_Int32 nRet = 0;
313 for (auto const& elem : m_aSecondaryExplicitScales)
315 if(elem.first.first==nDimensionIndex)
317 sal_Int32 nLocalIdx = elem.first.second;
318 if( nRet < nLocalIdx )
319 nRet = nLocalIdx;
322 return nRet;
325 void VCoordinateSystem::createVAxisList(
326 const rtl::Reference<::chart::ChartModel> & /* xChartDoc */,
327 const awt::Size& /* rFontReferenceSize */,
328 const awt::Rectangle& /* rMaximumSpaceForLabels */,
329 bool /* bLimitSpaceForLabels */,
330 std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/,
331 uno::Reference<uno::XComponentContext> const& /*rComponentContext*/)
335 void VCoordinateSystem::initVAxisInList()
338 void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
342 void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
344 bool bDateAxisX = (rScaleAutomatism.getScale().AxisType == AxisType::DATE) && (nDimIndex == 0);
345 if( bDateAxisX )
347 // This is a date X dimension. Determine proper time resolution.
348 sal_Int32 nTimeResolution = css::chart::TimeUnit::MONTH;
349 if( !(rScaleAutomatism.getScale().TimeIncrement.TimeResolution >>= nTimeResolution) )
351 nTimeResolution = m_aMergedMinMaxSupplier.calculateTimeResolutionOnXAxis();
352 rScaleAutomatism.setAutomaticTimeResolution( nTimeResolution );
354 m_aMergedMinMaxSupplier.setTimeResolutionOnXAxis( nTimeResolution, rScaleAutomatism.getNullDate() );
357 double fMin = std::numeric_limits<double>::infinity();
358 double fMax = -std::numeric_limits<double>::infinity();
359 if( nDimIndex == 0 )
361 // x dimension
362 fMin = m_aMergedMinMaxSupplier.getMinimumX();
363 fMax = m_aMergedMinMaxSupplier.getMaximumX();
365 else if( nDimIndex == 1 )
367 // y dimension
368 ExplicitScaleData aScale = getExplicitScale( 0, 0 );
369 double fMaximum = aScale.Maximum;
370 if (!aScale.m_bShiftedCategoryPosition && aScale.AxisType == AxisType::DATE)
372 // tdf#146066 Increase maximum date value by one month/year,
373 // because the automatic scaling of the Y axis was incorrect when the last Y value was the highest value.
374 Date aMaxDate(aScale.NullDate);
375 aMaxDate.AddDays(::rtl::math::approxFloor(fMaximum));
376 switch (aScale.TimeResolution)
378 case css::chart::TimeUnit::MONTH:
379 aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate, 1);
380 break;
381 case css::chart::TimeUnit::YEAR:
382 aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate, 1);
383 break;
385 fMaximum = aMaxDate - aScale.NullDate;
387 fMin = m_aMergedMinMaxSupplier.getMinimumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex);
388 fMax = m_aMergedMinMaxSupplier.getMaximumYInRange(aScale.Minimum, fMaximum, nAxisIndex);
390 else if( nDimIndex == 2 )
392 // z dimension
393 fMin = m_aMergedMinMaxSupplier.getMinimumZ();
394 fMax = m_aMergedMinMaxSupplier.getMaximumZ();
397 //merge our values with those already contained in rScaleAutomatism
398 rScaleAutomatism.expandValueRange( fMin, fMax );
400 rScaleAutomatism.setAutoScalingOptions(
401 m_aMergedMinMaxSupplier.isExpandBorderToIncrementRhythm( nDimIndex ),
402 m_aMergedMinMaxSupplier.isExpandIfValuesCloseToBorder( nDimIndex ),
403 m_aMergedMinMaxSupplier.isExpandWideValuesToZero( nDimIndex ),
404 m_aMergedMinMaxSupplier.isExpandNarrowValuesTowardZero( nDimIndex ) );
406 if (bDateAxisX)
407 return;
409 VAxisBase* pVAxis = getVAxis(nDimIndex, nAxisIndex);
410 if( pVAxis )
411 rScaleAutomatism.setMaximumAutoMainIncrementCount( pVAxis->estimateMaximumAutoMainIncrementCount() );
414 VAxisBase* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
416 VAxisBase* pRet = nullptr;
418 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
420 tVAxisMap::const_iterator aIt = m_aAxisMap.find( aFullAxisIndex );
421 if (aIt != m_aAxisMap.cend())
422 pRet = aIt->second.get();
424 return pRet;
427 void VCoordinateSystem::setExplicitScaleAndIncrement(
428 sal_Int32 nDimensionIndex
429 , sal_Int32 nAxisIndex
430 , const ExplicitScaleData& rExplicitScale
431 , const ExplicitIncrementData& rExplicitIncrement )
433 impl_adjustDimension( nDimensionIndex );
435 if( nAxisIndex==0 )
437 m_aExplicitScales[nDimensionIndex]=rExplicitScale;
438 m_aExplicitIncrements[nDimensionIndex]=rExplicitIncrement;
440 else
442 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
443 m_aSecondaryExplicitScales[aFullAxisIndex] = rExplicitScale;
444 m_aSecondaryExplicitIncrements[aFullAxisIndex] = rExplicitIncrement;
448 void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
450 m_eLeftWallPos = eLeftWallPos;
451 m_eBackWallPos = eBackWallPos;
452 m_eBottomPos = eBottomPos;
455 void VCoordinateSystem::createMaximumAxesLabels()
457 for (auto const&[unused, pVAxis] : m_aAxisMap)
459 (void)unused;
460 if (pVAxis)
462 if (pVAxis->getDimensionCount() == 2)
463 pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen);
464 pVAxis->createMaximumLabels();
468 void VCoordinateSystem::createAxesLabels()
470 for (auto const&[unused, pVAxis] : m_aAxisMap)
472 (void)unused;
473 if (pVAxis)
475 if (pVAxis->getDimensionCount() == 2)
476 pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen);
477 pVAxis->createLabels();
482 void VCoordinateSystem::updatePositions()
484 for (auto const&[unused, pVAxis] : m_aAxisMap)
486 (void)unused;
487 if (pVAxis)
489 if (pVAxis->getDimensionCount() == 2)
490 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
491 pVAxis->updatePositions();
496 void VCoordinateSystem::createAxesShapes()
498 for (auto const&[aFullAxisIndex, pVAxis] : m_aAxisMap)
500 if (pVAxis)
502 auto const&[nDimensionIndex, nAxisIndex] = aFullAxisIndex;
504 if (pVAxis->getDimensionCount() == 2)
505 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
507 if (nAxisIndex == 0)
509 if (nDimensionIndex == 0)
511 if( m_aExplicitScales[1].AxisType!=AxisType::CATEGORY )
512 pVAxis->setExtraLinePositionAtOtherAxis(
513 m_aExplicitScales[1].Origin );
515 else if (nDimensionIndex == 1)
517 if( m_aExplicitScales[0].AxisType!=AxisType::CATEGORY )
518 pVAxis->setExtraLinePositionAtOtherAxis(
519 m_aExplicitScales[0].Origin );
523 pVAxis->createShapes();
527 void VCoordinateSystem::createGridShapes()
530 void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
532 m_aMergedMinMaxSupplier.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
535 bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
537 return m_aMergedMinMaxSupplier.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
540 void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
542 m_aMergedMinMaxSupplier.clearMinimumAndMaximumSupplierList();
545 bool VCoordinateSystem::getPropertySwapXAndYAxis() const
547 bool bSwapXAndY = false;
548 if( m_xCooSysModel.is()) try
550 m_xCooSysModel->getPropertyValue( u"SwapXAndYAxis"_ustr ) >>= bSwapXAndY;
552 catch( const uno::Exception& )
554 TOOLS_WARN_EXCEPTION("chart2", "" );
556 return bSwapXAndY;
559 bool VCoordinateSystem::needSeriesNamesForAxis() const
561 return ( m_xCooSysModel.is() && m_xCooSysModel->getDimension() == 3 );
563 void VCoordinateSystem::setSeriesNamesForAxis( const Sequence< OUString >& rSeriesNames )
565 m_aSeriesNamesForZAxis = rSeriesNames;
568 sal_Int32 VCoordinateSystem::getNumberFormatKeyForAxis(
569 const rtl::Reference< Axis >& xAxis
570 , const rtl::Reference<::chart::ChartModel>& xChartDoc)
572 return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
573 xAxis, m_xCooSysModel, xChartDoc);
576 } //namespace chart
578 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */