LibreOffice Module chart2 (master) 1
SeriesPlotterContainer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <cstddef>
23
25
26#include <ChartView.hxx>
27#include <Diagram.hxx>
28#include <ChartType.hxx>
29#include <DataSeries.hxx>
30#include <ChartModel.hxx>
31#include <ChartTypeHelper.hxx>
32#include <ObjectIdentifier.hxx>
33#include <DiagramHelper.hxx>
34#include <Axis.hxx>
35#include <AxisIndexDefines.hxx>
36#include <DataSeriesHelper.hxx>
38#include <unonames.hxx>
39
40#include <com/sun/star/chart/ChartAxisPosition.hpp>
41#include <com/sun/star/chart2/AxisType.hpp>
42#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
43
47
48namespace chart
49{
50using namespace ::css;
51using namespace ::css::chart2;
52
53using ::css::uno::Reference;
54using ::css::uno::Sequence;
55using ::css::uno::Any;
56
58 std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList)
59 : m_rVCooSysList(rVCooSysList)
60 , m_nMaxAxisIndex(0)
61 , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
62 , m_nDefaultDateNumberFormat(0)
63{
64}
65
67{
68 // - remove plotter from coordinatesystems
69 for (auto& nC : m_rVCooSysList)
70 nC->clearMinimumAndMaximumSupplierList();
71}
72
73std::vector<LegendEntryProvider*> SeriesPlotterContainer::getLegendEntryProviderList()
74{
75 std::vector<LegendEntryProvider*> aRet(m_aSeriesPlotterList.size());
76 sal_Int32 nN = 0;
77 for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
78 aRet[nN++] = aPlotter.get();
79 return aRet;
80}
81
83 const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
85{
86 for (auto& pVCooSys : rVCooSysList)
87 {
88 if (pVCooSys->getModel() == xCooSys)
89 return pVCooSys.get();
90 }
91 return nullptr;
92}
93
95 const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
96 MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier)
97{
98 if (!pMinimumAndMaximumSupplier)
99 return nullptr;
100 for (auto& pVCooSys : rVCooSysList)
101 {
102 if (pVCooSys->hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier))
103 return pVCooSys.get();
104 }
105 return nullptr;
106}
107
109 std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
110 const rtl::Reference<BaseCoordinateSystem>& xCooSys, ChartModel& rChartModel)
111{
112 VCoordinateSystem* pExistingVCooSys
113 = SeriesPlotterContainer::findInCooSysList(rVCooSysList, xCooSys);
114 if (pExistingVCooSys)
115 return pExistingVCooSys;
116
117 std::unique_ptr<VCoordinateSystem> pVCooSys
119 if (!pVCooSys)
120 return nullptr;
121
122 OUString aCooSysParticle(
124 pVCooSys->setParticle(aCooSysParticle);
125
126 pVCooSys->setExplicitCategoriesProvider(new ExplicitCategoriesProvider(xCooSys, rChartModel));
127 rVCooSysList.push_back(std::move(pVCooSys));
128 return rVCooSysList.back().get();
129}
130
132{
133 rtl::Reference<Diagram> xDiagram = rChartModel.getFirstChartDiagram();
134 if (!xDiagram.is())
135 return;
136
137 uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(&rChartModel);
138 if (rChartModel.hasInternalDataProvider() && xDiagram->isSupportingDateAxis())
140
141 sal_Int32 nDimensionCount = xDiagram->getDimension();
142 if (!nDimensionCount)
143 {
144 //@todo handle mixed dimension
145 nDimensionCount = 2;
146 }
147
148 bool bSortByXValues = false;
149 bool bConnectBars = false;
150 bool bGroupBarsPerAxis = true;
151 bool bIncludeHiddenCells = true;
152 bool bSecondaryYaxisVisible = true;
153 sal_Int32 nStartingAngle = 90;
154 sal_Int32 n3DRelativeHeight = 100;
155 try
156 {
157 xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues;
158 xDiagram->getPropertyValue("ConnectBars") >>= bConnectBars;
159 xDiagram->getPropertyValue("GroupBarsPerAxis") >>= bGroupBarsPerAxis;
160 xDiagram->getPropertyValue("IncludeHiddenCells") >>= bIncludeHiddenCells;
161 xDiagram->getPropertyValue("StartingAngle") >>= nStartingAngle;
162
163 if (nDimensionCount == 3)
164 {
165 xDiagram->getPropertyValue("3DRelativeHeight") >>= n3DRelativeHeight;
166 }
167 }
168 catch (const uno::Exception&)
169 {
170 DBG_UNHANDLED_EXCEPTION("chart2");
171 }
172
173 if (xDiagram->getDataTable().is())
175
176 //prepare for autoscaling and shape creation
177 // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
178 // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
179 // - add plotter to coordinate systems
180
181 //iterate through all coordinate systems
182 uno::Reference<XColorScheme> xColorScheme(xDiagram->getDefaultColorScheme());
183 auto aCooSysList = xDiagram->getBaseCoordinateSystems();
184 sal_Int32 nGlobalSeriesIndex = 0; //for automatic symbols
185 for (std::size_t nCS = 0; nCS < aCooSysList.size(); ++nCS)
186 {
187 rtl::Reference<BaseCoordinateSystem> xCooSys(aCooSysList[nCS]);
188 VCoordinateSystem* pVCooSys
190 // Let's check whether the secondary Y axis is visible
191 try
192 {
193 if (xCooSys->getMaximumAxisIndexByDimension(1) > 0)
194 {
195 rtl::Reference<Axis> xAxisProp = xCooSys->getAxisByDimension2(1, 1);
196 xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible;
197 }
198 }
199 catch (const lang::IndexOutOfBoundsException&)
200 {
201 TOOLS_WARN_EXCEPTION("chart2", "");
202 }
203 //iterate through all chart types in the current coordinate system
204 std::vector<rtl::Reference<ChartType>> aChartTypeList(xCooSys->getChartTypes2());
205 for (std::size_t nT = 0; nT < aChartTypeList.size(); ++nT)
206 {
207 rtl::Reference<ChartType> xChartType(aChartTypeList[nT]);
208 if (nDimensionCount == 3
209 && xChartType->getChartType().equalsIgnoreAsciiCase(
211 {
212 try
213 {
214 sal_Int32 n3DRelativeHeightOldValue(100);
215 uno::Any aAny = xChartType->getFastPropertyValue(
216 PROP_PIECHARTTYPE_3DRELATIVEHEIGHT); // "3DRelativeHeight"
217 aAny >>= n3DRelativeHeightOldValue;
218 if (n3DRelativeHeightOldValue != n3DRelativeHeight)
219 xChartType->setFastPropertyValue(
220 PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, // "3DRelativeHeight"
221 uno::Any(n3DRelativeHeight));
222 }
223 catch (const uno::Exception&)
224 {
225 }
226 }
227
228 if (nT == 0)
231
232 bool bExcludingPositioning
233 = xDiagram->getDiagramPositioningMode() == DiagramPositioningMode::Excluding;
235 xChartType, nDimensionCount, bExcludingPositioning);
236 if (!pPlotter)
237 continue;
238
239 m_aSeriesPlotterList.push_back(std::unique_ptr<VSeriesPlotter>(pPlotter));
240 pPlotter->setNumberFormatsSupplier(xNumberFormatsSupplier);
241 pPlotter->setColorScheme(xColorScheme);
242 if (pVCooSys)
244 sal_Int32 nMissingValueTreatment
245 = xDiagram->getCorrectedMissingValueTreatment(xChartType);
246
247 if (pVCooSys)
248 pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
249
250 sal_Int32 zSlot = -1;
251 sal_Int32 xSlot = -1;
252 sal_Int32 ySlot = -1;
253 const std::vector<rtl::Reference<DataSeries>>& aSeriesList
254 = xChartType->getDataSeries2();
255 for (std::size_t nS = 0; nS < aSeriesList.size(); ++nS)
256 {
257 rtl::Reference<DataSeries> const& xDataSeries = aSeriesList[nS];
258 if (!bIncludeHiddenCells && !xDataSeries->hasUnhiddenData())
259 continue;
260
261 std::unique_ptr<VDataSeries> pSeries(new VDataSeries(xDataSeries));
262
263 pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
264 nGlobalSeriesIndex++;
265
266 if (bSortByXValues)
267 pSeries->doSortByXValues();
268
269 pSeries->setConnectBars(bConnectBars);
270 pSeries->setGroupBarsPerAxis(bGroupBarsPerAxis);
271 pSeries->setStartingAngle(nStartingAngle);
272
273 pSeries->setMissingValueTreatment(nMissingValueTreatment);
274
275 OUString aSeriesParticle(ObjectIdentifier::createParticleForSeries(0, nCS, nT, nS));
276 pSeries->setParticle(aSeriesParticle);
277
279 xChartType));
280 pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
281
282 //ignore secondary axis for charttypes that do not support them
283 if (pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX
284 && (!ChartTypeHelper::isSupportingSecondaryAxis(xChartType, nDimensionCount)
285 || !bSecondaryYaxisVisible))
286 {
287 pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
288 }
289
290 StackingDirection eDirection = pSeries->getStackingDirection();
291 switch (eDirection)
292 {
293 case StackingDirection_NO_STACKING:
294 xSlot++;
295 ySlot = -1;
296 if (zSlot < 0)
297 zSlot = 0;
298 break;
299 case StackingDirection_Y_STACKING:
300 ySlot++;
301 if (xSlot < 0)
302 xSlot = 0;
303 if (zSlot < 0)
304 zSlot = 0;
305 break;
306 case StackingDirection_Z_STACKING:
307 zSlot++;
308 xSlot = -1;
309 ySlot = -1;
310 break;
311 default:
312 // UNO enums have one additional auto-generated case
313 break;
314 }
315 pPlotter->addSeries(std::move(pSeries), zSlot, xSlot, ySlot);
316 }
317 }
318 }
319
320 //transport seriesnames to the coordinatesystems if needed
321 if (m_aSeriesPlotterList.empty())
322 return;
323
324 uno::Sequence<OUString> aSeriesNames;
325 bool bSeriesNamesInitialized = false;
326 for (auto& pVCooSys : m_rVCooSysList)
327 {
328 if (pVCooSys->needSeriesNamesForAxis())
329 {
330 if (!bSeriesNamesInitialized)
331 {
332 aSeriesNames = m_aSeriesPlotterList[0]->getSeriesNames();
333 bSeriesNamesInitialized = true;
334 }
335 pVCooSys->setSeriesNamesForAxis(aSeriesNames);
336 }
337 }
338}
339
340bool SeriesPlotterContainer::isCategoryPositionShifted(const chart2::ScaleData& rSourceScale,
341 bool bHasComplexCategories)
342{
344 return true;
345
346 if (rSourceScale.AxisType == AxisType::CATEGORY)
347 return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition
349
350 if (rSourceScale.AxisType == AxisType::DATE)
351 return rSourceScale.ShiftedCategoryPosition;
352
353 return rSourceScale.AxisType == AxisType::SERIES;
354}
355
357{
358 m_aAxisUsageList.clear();
359
360 // Loop through coordinate systems in the diagram (though for now
361 // there should only be one coordinate system per diagram).
362 for (auto& pVCooSys : m_rVCooSysList)
363 {
364 rtl::Reference<BaseCoordinateSystem> xCooSys = pVCooSys->getModel();
365 sal_Int32 nDimCount = xCooSys->getDimension();
366 bool bComplexCategoryAllowed = ChartTypeHelper::isSupportingComplexCategory(
368
369 for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
370 {
371 bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis(
372 AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimIndex);
373
374 // Each dimension may have primary and secondary axes.
375 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
376 for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; ++nAxisIndex)
377 {
378 rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimIndex, nAxisIndex);
379
380 if (!xAxis.is())
381 continue;
382
383 if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end())
384 {
385 // Create axis usage object for this axis.
386
387 chart2::ScaleData aSourceScale = xAxis->getScaleData();
388 ExplicitCategoriesProvider* pCatProvider
389 = pVCooSys->getExplicitCategoriesProvider();
390 if (nDimIndex == 0)
391 AxisHelper::checkDateAxis(aSourceScale, pCatProvider, bDateAxisAllowed);
392
393 bool bHasComplexCat = pCatProvider && pCatProvider->hasComplexCategories()
394 && bComplexCategoryAllowed;
395 aSourceScale.ShiftedCategoryPosition
396 = isCategoryPositionShifted(aSourceScale, bHasComplexCat);
397
398 m_aAxisUsageList[xAxis].aAutoScaling = ScaleAutomatism(aSourceScale, rNullDate);
399 }
400
401 AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
402 rAxisUsage.addCoordinateSystem(pVCooSys.get(), nDimIndex, nAxisIndex);
403 }
404 }
405 }
406
407 // Determine the highest axis index of all dimensions.
408 m_nMaxAxisIndex = 0;
409 for (const auto& pVCooSys : m_rVCooSysList)
410 {
411 uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
412 sal_Int32 nDimCount = xCooSys->getDimension();
413
414 for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
415 {
416 for (auto& axisUsage : m_aAxisUsageList)
417 {
418 sal_Int32 nLocalMax = axisUsage.second.getMaxAxisIndexForDimension(nDimIndex);
419 if (m_nMaxAxisIndex < nLocalMax)
420 m_nMaxAxisIndex = nLocalMax;
421 }
422 }
423 }
424}
425
427{
428 //set scales to plotter to enable them to provide the preferred scene AspectRatio
429 for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
430 {
431 VSeriesPlotter* pSeriesPlotter = aPlotter.get();
432 VCoordinateSystem* pVCooSys
434 if (pVCooSys)
435 {
436 pSeriesPlotter->setScales(pVCooSys->getExplicitScales(0, 0),
437 pVCooSys->getPropertySwapXAndYAxis());
438 sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(
439 1); //only additional value axis are relevant for series plotter
440 for (sal_Int32 nI = 1; nI <= nMaxAxisIndex; nI++)
441 pSeriesPlotter->addSecondaryValueScale(pVCooSys->getExplicitScale(1, nI), nI);
442 }
443 }
444}
445
447{
448 //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis
449 for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
450 {
451 VSeriesPlotter* pSeriesPlotter = aPlotter.get();
452 VCoordinateSystem* pVCooSys
454 if (pVCooSys)
455 {
456 AxesNumberFormats aAxesNumberFormats;
457 const rtl::Reference<BaseCoordinateSystem>& xCooSys = pVCooSys->getModel();
458 sal_Int32 nDimensionCount = xCooSys->getDimension();
459 for (sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount;
460 ++nDimensionIndex)
461 {
462 const sal_Int32 nMaximumAxisIndex
463 = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
464 for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaximumAxisIndex; ++nAxisIndex)
465 {
466 try
467 {
468 rtl::Reference<Axis> xAxisProp
469 = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex);
470 if (xAxisProp.is())
471 {
472 sal_Int32 nNumberFormatKey(0);
473 if (xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT)
474 >>= nNumberFormatKey)
475 {
476 aAxesNumberFormats.setFormat(nNumberFormatKey, nDimensionIndex,
477 nAxisIndex);
478 }
479 else if (nDimensionIndex == 0)
480 {
481 //provide a default date format for date axis with own data
482 aAxesNumberFormats.setFormat(m_nDefaultDateNumberFormat,
483 nDimensionIndex, nAxisIndex);
484 }
485 }
486 }
487 catch (const lang::IndexOutOfBoundsException&)
488 {
489 TOOLS_WARN_EXCEPTION("chart2", "");
490 }
491 }
492 }
493 }
494 }
495}
496
498{
499 for (auto& nC : m_rVCooSysList)
500 nC->updateScalesAndIncrementsOnAxes();
501}
502
503void SeriesPlotterContainer::doAutoScaling(ChartModel& rChartModel)
504{
505 if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty())
506 // We need these two containers populated to do auto-scaling. Bail out.
507 return;
508
509 //iterate over the main scales first than secondary axis
510 for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex)
511 {
512 // - first do autoscale for all x and z scales (because they are treated independent)
513 for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
514 {
515 (void)rAxis;
516 rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, nAxisIndex);
517 rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, nAxisIndex);
518
519 ExplicitScaleData aExplicitScale;
520 ExplicitIncrementData aExplicitIncrement;
521 rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale,
522 aExplicitIncrement);
523
524 rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale,
525 aExplicitIncrement);
526 rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale,
527 aExplicitIncrement);
528 }
529
530 // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
531 for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
532 {
533 (void)rAxis;
534 rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAxisIndex);
535
536 ExplicitScaleData aExplicitScale;
537 ExplicitIncrementData aExplicitIncrement;
538 rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale,
539 aExplicitIncrement);
540
541 rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale,
542 aExplicitIncrement);
543 rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScale,
544 aExplicitIncrement);
545 rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale,
546 aExplicitIncrement);
547 }
548 }
550}
551
553{
554 //issue #i80518#
555 for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; nAxisIndex++)
556 {
557 for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
558 {
559 (void)rAxis;
560 std::vector<VCoordinateSystem*> aVCooSysList_Y
561 = rAxisUsage.getCoordinateSystems(1, nAxisIndex);
562 if (aVCooSysList_Y.empty())
563 continue;
564
565 rtl::Reference<Diagram> xDiagram(rModel.getFirstChartDiagram());
566 if (!xDiagram.is())
567 continue;
568
569 bool bSeriesAttachedToThisAxis = false;
570 sal_Int32 nAttachedAxisIndex = -1;
571 {
572 std::vector<rtl::Reference<DataSeries>> aSeriesVector = xDiagram->getDataSeries();
573 for (auto const& series : aSeriesVector)
574 {
575 sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series);
576 if (nAxisIndex == nCurrentIndex)
577 {
578 bSeriesAttachedToThisAxis = true;
579 break;
580 }
581 else if (nAttachedAxisIndex < 0 || nAttachedAxisIndex > nCurrentIndex)
582 nAttachedAxisIndex = nCurrentIndex;
583 }
584 }
585
586 if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0)
587 continue;
588
589 for (VCoordinateSystem* nC : aVCooSysList_Y)
590 {
591 nC->prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAttachedAxisIndex);
592
593 ExplicitScaleData aExplicitScaleSource
594 = nC->getExplicitScale(1, nAttachedAxisIndex);
595 ExplicitIncrementData aExplicitIncrementSource
596 = nC->getExplicitIncrement(1, nAttachedAxisIndex);
597
598 ExplicitScaleData aExplicitScaleDest = nC->getExplicitScale(1, nAxisIndex);
599 ExplicitIncrementData aExplicitIncrementDest
600 = nC->getExplicitIncrement(1, nAxisIndex);
601
602 aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
603 aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
604 aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
605
606 aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
607
608 ScaleData aScale(rAxisUsage.aAutoScaling.getScale());
609 if (!aScale.Minimum.hasValue())
610 {
611 bool bNewMinOK = true;
612 double fMax = 0.0;
613 if (aScale.Maximum >>= fMax)
614 bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
615 if (bNewMinOK)
616 aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
617 }
618 else
619 aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
620
621 if (!aScale.Maximum.hasValue())
622 {
623 bool bNewMaxOK = true;
624 double fMin = 0.0;
625 if (aScale.Minimum >>= fMin)
626 bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
627 if (bNewMaxOK)
628 aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
629 }
630 if (!aScale.Origin.hasValue())
631 aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
632
633 if (!aScale.IncrementData.Distance.hasValue())
634 aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
635
636 bool bAutoMinorInterval = true;
637 if (aScale.IncrementData.SubIncrements.hasElements())
638 bAutoMinorInterval
639 = !(aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue());
640 if (bAutoMinorInterval)
641 {
642 if (!aExplicitIncrementDest.SubIncrements.empty()
643 && !aExplicitIncrementSource.SubIncrements.empty())
644 aExplicitIncrementDest.SubIncrements[0].IntervalCount
645 = aExplicitIncrementSource.SubIncrements[0].IntervalCount;
646 }
647
648 nC->setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScaleDest,
649 aExplicitIncrementDest);
650 }
651 }
652 }
653
655 return;
656
657 //correct origin for y main axis (the origin is where the other main axis crosses)
658 sal_Int32 nAxisIndex = 0;
659 sal_Int32 nDimensionIndex = 1;
660 for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
661 {
662 (void)rAxis;
663 std::vector<VCoordinateSystem*> aVCooSysList
664 = rAxisUsage.getCoordinateSystems(nDimensionIndex, nAxisIndex);
665 size_t nC;
666 for (nC = 0; nC < aVCooSysList.size(); nC++)
667 {
668 ExplicitScaleData aExplicitScale(
669 aVCooSysList[nC]->getExplicitScale(nDimensionIndex, nAxisIndex));
670 ExplicitIncrementData aExplicitIncrement(
671 aVCooSysList[nC]->getExplicitIncrement(nDimensionIndex, nAxisIndex));
672
673 rtl::Reference<BaseCoordinateSystem> xCooSys(aVCooSysList[nC]->getModel());
674 rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex);
675 rtl::Reference<Axis> xCrossingMainAxis
676 = AxisHelper::getCrossingMainAxis(xAxis, xCooSys);
677
678 if (xCrossingMainAxis.is())
679 {
680 css::chart::ChartAxisPosition eCrossingMainAxisPos(
681 css::chart::ChartAxisPosition_ZERO);
682 xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos;
683 if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_VALUE)
684 {
685 double fValue = 0.0;
686 xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= fValue;
687 aExplicitScale.Origin = fValue;
688 }
689 else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_ZERO)
690 aExplicitScale.Origin = 0.0;
691 else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_START)
692 aExplicitScale.Origin = aExplicitScale.Minimum;
693 else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_END)
694 aExplicitScale.Origin = aExplicitScale.Maximum;
695 }
696
697 aVCooSysList[nC]->setExplicitScaleAndIncrement(nDimensionIndex, nAxisIndex,
698 aExplicitScale, aExplicitIncrement);
699 }
700 }
701}
702
704{
705 drawing::Direction3D aPreferredAspectRatio(1.0, 1.0, 1.0);
706
707 //get a list of all preferred aspect ratios and combine them
708 //first with special demands wins (less or equal zero <-> arbitrary)
709 double fx, fy, fz;
710 fx = fy = fz = -1.0;
711 for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
712 {
713 drawing::Direction3D aSingleRatio(aPlotter->getPreferredDiagramAspectRatio());
714 if (fx < 0 && aSingleRatio.DirectionX > 0)
715 fx = aSingleRatio.DirectionX;
716
717 if (fy < 0 && aSingleRatio.DirectionY > 0)
718 {
719 if (fx > 0 && aSingleRatio.DirectionX > 0)
720 fy = fx * aSingleRatio.DirectionY / aSingleRatio.DirectionX;
721 else if (fz > 0 && aSingleRatio.DirectionZ > 0)
722 fy = fz * aSingleRatio.DirectionY / aSingleRatio.DirectionZ;
723 else
724 fy = aSingleRatio.DirectionY;
725 }
726
727 if (fz < 0 && aSingleRatio.DirectionZ > 0)
728 {
729 if (fx > 0 && aSingleRatio.DirectionX > 0)
730 fz = fx * aSingleRatio.DirectionZ / aSingleRatio.DirectionX;
731 else if (fy > 0 && aSingleRatio.DirectionY > 0)
732 fz = fy * aSingleRatio.DirectionZ / aSingleRatio.DirectionY;
733 else
734 fz = aSingleRatio.DirectionZ;
735 }
736
737 if (fx > 0 && fy > 0 && fz > 0)
738 break;
739 }
740 aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
741 return aPreferredAspectRatio;
742}
743
744} //end chart2 namespace
745
746/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
int nDimCount
void setFormat(sal_Int32 nFormatKey, sal_Int32 nDimIndex, sal_Int32 nAxisIndex)
static rtl::Reference< ::chart::Axis > getCrossingMainAxis(const rtl::Reference< ::chart::Axis > &xAxis, const rtl::Reference< ::chart::BaseCoordinateSystem > &xCooSys)
Definition: AxisHelper.cxx:595
static void checkDateAxis(css::chart2::ScaleData &rScale, ExplicitCategoriesProvider *pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis)
Definition: AxisHelper.cxx:124
static rtl::Reference< ::chart::ChartType > getChartTypeByIndex(const rtl::Reference< ::chart::BaseCoordinateSystem > &xCooSys, sal_Int32 nIndex)
static bool isAxisPositioningEnabled()
This class handles a collection of coordinate systems and is used for executing some action on all co...
Definition: AxisUsage.hxx:46
void addCoordinateSystem(VCoordinateSystem *pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex)
Definition: AxisUsage.hxx:53
static bool shiftCategoryPosAtXAxisPerDefault(const rtl::Reference< ::chart::ChartType > &xChartType)
static bool isSupportingDateAxis(const rtl::Reference< ::chart::ChartType > &xChartType, sal_Int32 nDimensionIndex)
static bool isSupportingComplexCategory(const rtl::Reference< ::chart::ChartType > &xChartType)
static OUString getRoleOfSequenceForDataLabelNumberFormatDetection(const rtl::Reference< ::chart::ChartType > &xChartType)
static bool isSupportingSecondaryAxis(const rtl::Reference< ::chart::ChartType > &xChartType, sal_Int32 nDimensionCount)
static sal_Int32 getDateNumberFormat(const css::uno::Reference< css::util::XNumberFormatsSupplier > &xNumberFormatsSupplier)
static OUString createParticleForCoordinateSystem(const rtl::Reference< ::chart::BaseCoordinateSystem > &xCooSys, const rtl::Reference<::chart::ChartModel > &xChartModel)
static OUString createParticleForSeries(sal_Int32 nDiagramIndex, sal_Int32 nCooSysIndex, sal_Int32 nChartTypeIndex, sal_Int32 nSeriesIndex)
virtual void setScales(std::vector< ExplicitScaleData > &&rScales, bool bSwapXAndYAxis)
Definition: PlotterBase.cxx:51
This class implements the calculation of automatic axis limits.
std::map< rtl::Reference< Axis >, AxisUsage > m_aAxisUsageList
A map whose key is a XAxis interface and the related value is an object of AxisUsage type.
std::vector< std::unique_ptr< VCoordinateSystem > > & m_rVCooSysList
A vector of coordinate systems.
static VCoordinateSystem * getCooSysForPlotter(const std::vector< std::unique_ptr< VCoordinateSystem > > &rVCooSysList, MinimumAndMaximumSupplier *pMinimumAndMaximumSupplier)
css::drawing::Direction3D getPreferredAspectRatio()
bool isCategoryPositionShifted(const css::chart2::ScaleData &rSourceScale, bool bHasComplexCategories)
std::vector< LegendEntryProvider * > getLegendEntryProviderList()
static VCoordinateSystem * addCooSysToList(std::vector< std::unique_ptr< VCoordinateSystem > > &rVCooSysList, const rtl::Reference< BaseCoordinateSystem > &xCooSys, ChartModel &rChartModel)
void initAxisUsageList(const Date &rNullDate)
This method is invoked by ChartView::impl_createDiagramAndContent.
void AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel &rModel)
sal_Int32 m_nMaxAxisIndex
Max axis index of all dimensions.
static VCoordinateSystem * findInCooSysList(const std::vector< std::unique_ptr< VCoordinateSystem > > &rVCooSysList, const rtl::Reference< BaseCoordinateSystem > &xCooSys)
void doAutoScaling(ChartModel &rModel)
Perform automatic axis scaling and determine the amount and spacing of increments.
void initializeCooSysAndSeriesPlotter(ChartModel &rModel)
It is used to set coordinate systems (m_rVCooSysList), this method is invoked by ChartView::createSha...
void updateScalesAndIncrementsOnAxes()
After auto-scaling is performed, call this method to set the explicit scaling and increment data to a...
void setScalesFromCooSysToPlotter()
After auto-scaling is performed, call this method to set the explicit scaling data to all the plotter...
std::vector< std::unique_ptr< VSeriesPlotter > > m_aSeriesPlotterList
A vector of series plotters.
SeriesPlotterContainer(std::vector< std::unique_ptr< VCoordinateSystem > > &rVCooSysList)
ExplicitCategoriesProvider * getExplicitCategoriesProvider()
void addMinimumAndMaximumSupplier(MinimumAndMaximumSupplier *pMinimumAndMaximumSupplier)
sal_Int32 getMaximumAxisIndexByDimension(sal_Int32 nDimensionIndex) const
std::vector< ExplicitScaleData > getExplicitScales(sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex) const
ExplicitScaleData getExplicitScale(sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex) const
static std::unique_ptr< VCoordinateSystem > createCoordinateSystem(const rtl::Reference< ::chart::BaseCoordinateSystem > &xCooSysModel)
const rtl::Reference< ::chart::BaseCoordinateSystem > & getModel() const
void addSecondaryValueScale(const ExplicitScaleData &rScale, sal_Int32 nAxisIndex)
this enables you to handle series on the same x axis with different y axis the property AttachedAxisI...
void setNumberFormatsSupplier(const css::uno::Reference< css::util::XNumberFormatsSupplier > &xNumFmtSupplier)
static VSeriesPlotter * createSeriesPlotter(const rtl::Reference< ::chart::ChartType > &xChartTypeModel, sal_Int32 nDimensionCount, bool bExcludingPositioning)
virtual void addSeries(std::unique_ptr< VDataSeries > pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot)
A new series can be positioned relative to other series in a chart.
void setColorScheme(const css::uno::Reference< css::chart2::XColorScheme > &xColorScheme)
void setExplicitCategoriesProvider(ExplicitCategoriesProvider *pExplicitCategoriesProvider)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getAttachedAxisIndex(const rtl::Reference< ::chart::DataSeries > &xSeries)
@ PROP_PIECHARTTYPE_3DRELATIVEHEIGHT
Definition: ChartType.hxx:44
const sal_Int32 MAIN_AXIS_INDEX
constexpr OUStringLiteral CHART2_SERVICE_NAME_CHARTTYPE_PIE
describes how tickmarks are positioned on the scale of an axis.
std::vector< ExplicitSubIncrement > SubIncrements
<member>SubIncrements</member> describes the positioning of further sub tickmarks on the scale of an ...
double Distance
the other members are for not date-time axis
double BaseValue
The <member>BaseValue</member> gives a starting point on the scale to which all further main tickmark...
This structure contains the explicit values for a scale like Minimum and Maximum.
css::uno::Reference< css::chart2::XScaling > Scaling
css::chart2::AxisOrientation Orientation
constexpr OUStringLiteral CHART_UNONAME_NUMFMT
Definition: unonames.hxx:20
constexpr OUStringLiteral CHART_UNONAME_SORT_BY_XVALUES
Definition: unonames.hxx:14