tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / chart2 / source / view / charttypes / CandleStickChart.cxx
blobd7e338017905f0ae68e95968c4fd7442955ca957
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 "CandleStickChart.hxx"
21 #include <ChartType.hxx>
22 #include <ShapeFactory.hxx>
23 #include <CommonConverters.hxx>
24 #include <ExplicitCategoriesProvider.hxx>
25 #include <ObjectIdentifier.hxx>
26 #include "BarPositionHelper.hxx"
27 #include <DateHelper.hxx>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <comphelper/diagnose_ex.hxx>
30 #include <osl/diagnose.h>
32 namespace chart
34 using namespace ::com::sun::star;
36 CandleStickChart::CandleStickChart( const rtl::Reference<ChartType>& xChartTypeModel
37 , sal_Int32 nDimensionCount )
38 : VSeriesPlotter( xChartTypeModel, nDimensionCount )
40 PlotterBase::m_pPosHelper = &m_aMainPosHelper;
41 VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper;
44 CandleStickChart::~CandleStickChart()
48 // MinimumAndMaximumSupplier
50 bool CandleStickChart::isSeparateStackingForDifferentSigns( sal_Int32 /* nDimensionIndex */ )
52 return false;
55 LegendSymbolStyle CandleStickChart::getLegendSymbolStyle()
57 return LegendSymbolStyle::Line;
60 drawing::Direction3D CandleStickChart::getPreferredDiagramAspectRatio() const
62 return drawing::Direction3D(-1,-1,-1);
65 void CandleStickChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 /* zSlot */, sal_Int32 xSlot, sal_Int32 ySlot )
67 //ignore y stacking for candle stick chart
68 VSeriesPlotter::addSeries( std::move(pSeries), 0, xSlot, ySlot );
71 void CandleStickChart::createShapes()
73 if( m_aZSlots.empty() ) //no series
74 return;
76 if( m_nDimension!=2 )
77 return;
79 OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"CandleStickChart is not proper initialized");
80 if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
81 return;
83 //the text labels should be always on top of the other series shapes
84 //therefore create an own group for the texts to move them to front
85 //(because the text group is created after the series group the texts are displayed on top)
87 rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget =
88 createGroupShape( m_xLogicTarget );
89 rtl::Reference<SvxShapeGroupAnyD> xLossTarget =
90 createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier(
91 OBJECTTYPE_DATA_STOCK_LOSS, u"" ));
92 rtl::Reference<SvxShapeGroupAnyD> xGainTarget =
93 createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier(
94 OBJECTTYPE_DATA_STOCK_GAIN, u"" ));
95 rtl::Reference< SvxShapeGroup > xTextTarget =
96 ShapeFactory::createGroup2D( m_xFinalTarget );
98 //check necessary here that different Y axis can not be stacked in the same group? ... hm?
100 bool bJapaneseStyle=true;//@todo is this the correct default?
101 bool bShowFirst = true;//is only important if bJapaneseStyle == false
102 tNameSequence aWhiteBox_Names, aBlackBox_Names;
103 tAnySequence aWhiteBox_Values, aBlackBox_Values;
106 if( m_xChartTypeModel.is() )
108 m_xChartTypeModel->getPropertyValue( u"ShowFirst"_ustr ) >>= bShowFirst;
110 uno::Reference< beans::XPropertySet > xWhiteDayProps;
111 uno::Reference< beans::XPropertySet > xBlackDayProps;
112 m_xChartTypeModel->getPropertyValue( u"Japanese"_ustr ) >>= bJapaneseStyle;
113 m_xChartTypeModel->getPropertyValue( u"WhiteDay"_ustr ) >>= xWhiteDayProps;
114 m_xChartTypeModel->getPropertyValue( u"BlackDay"_ustr ) >>= xBlackDayProps;
116 tPropertyNameValueMap aWhiteBox_Map;
117 PropertyMapper::getValueMap( aWhiteBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xWhiteDayProps );
118 PropertyMapper::getMultiPropertyListsFromValueMap( aWhiteBox_Names, aWhiteBox_Values, aWhiteBox_Map );
120 tPropertyNameValueMap aBlackBox_Map;
121 PropertyMapper::getValueMap( aBlackBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xBlackDayProps );
122 PropertyMapper::getMultiPropertyListsFromValueMap( aBlackBox_Names, aBlackBox_Values, aBlackBox_Map );
125 catch( const uno::Exception& )
127 TOOLS_WARN_EXCEPTION("chart2", "" );
130 //(@todo maybe different iteration for breaks in axis ?)
131 sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
132 double fLogicZ = 1.5;//as defined
133 //iterate through all x values per indices
134 for( sal_Int32 nIndex = 0; nIndex < nEndIndex; nIndex++ )
136 for( auto const& rZSlot : m_aZSlots )
138 BarPositionHelper* pPosHelper = &m_aMainPosHelper;
139 if( !rZSlot.empty() )
141 sal_Int32 nAttachedAxisIndex = rZSlot.front().getAttachedAxisIndexForFirstSeries();
142 //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
143 pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) );
144 if(!pPosHelper)
145 pPosHelper = &m_aMainPosHelper;
147 PlotterBase::m_pPosHelper = pPosHelper;
149 //update/create information for current group
150 pPosHelper->updateSeriesCount( rZSlot.size() );
151 double fSlotX=0;
152 //iterate through all x slots in this category
153 for( auto const& rXSlot : rZSlot )
155 //iterate through all series in this x slot
156 for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
158 //collect data point information (logic coordinates, style ):
159 double fUnscaledX = pSeries->getXValue( nIndex );
160 if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() )
161 fUnscaledX = DateHelper::RasterizeDateValue( fUnscaledX, m_aNullDate, m_nTimeResolution );
162 if(fUnscaledX<pPosHelper->getLogicMinX() || fUnscaledX>pPosHelper->getLogicMaxX())
163 continue;//point not visible
164 double fScaledX = pPosHelper->getScaledSlotPos( fUnscaledX, fSlotX );
166 double fUnscaledY_First = pSeries->getY_First( nIndex );
167 double fUnscaledY_Last = pSeries->getY_Last( nIndex );
168 double fUnscaledY_Min = pSeries->getY_Min( nIndex );
169 double fUnscaledY_Max = pSeries->getY_Max( nIndex );
171 bool bBlack=false;
172 if(fUnscaledY_Last<=fUnscaledY_First)
174 std::swap(fUnscaledY_First,fUnscaledY_Last);
175 bBlack=true;
177 if(fUnscaledY_Max<fUnscaledY_Min)
178 std::swap(fUnscaledY_Min,fUnscaledY_Max);
179 //transformation 3) -> 4)
180 double fHalfScaledWidth = pPosHelper->getScaledSlotWidth()/2.0;
182 double fScaledY_First(fUnscaledY_First);
183 double fScaledY_Last(fUnscaledY_Last);
184 double fScaledY_Min(fUnscaledY_Min);
185 double fScaledY_Max(fUnscaledY_Max);
186 pPosHelper->clipLogicValues( nullptr,&fScaledY_First,nullptr );
187 pPosHelper->clipLogicValues( nullptr,&fScaledY_Last,nullptr );
188 pPosHelper->clipLogicValues( nullptr,&fScaledY_Min,nullptr );
189 pPosHelper->clipLogicValues( nullptr,&fScaledY_Max,nullptr );
190 pPosHelper->doLogicScaling( nullptr,&fScaledY_First,nullptr );
191 pPosHelper->doLogicScaling( nullptr,&fScaledY_Last,nullptr );
192 pPosHelper->doLogicScaling( nullptr,&fScaledY_Min,nullptr );
193 pPosHelper->doLogicScaling( nullptr,&fScaledY_Max,nullptr );
195 drawing::Position3D aPosLeftFirst( pPosHelper->transformScaledLogicToScene( fScaledX-fHalfScaledWidth, fScaledY_First ,0 ,true ) );
196 drawing::Position3D aPosRightLast( pPosHelper->transformScaledLogicToScene( fScaledX+fHalfScaledWidth, fScaledY_Last ,0 ,true ) );
197 drawing::Position3D aPosMiddleFirst( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_First ,0 ,true ) );
198 drawing::Position3D aPosMiddleLast( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Last ,0 ,true ) );
199 drawing::Position3D aPosMiddleMinimum( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Min ,0 ,true ) );
200 drawing::Position3D aPosMiddleMaximum( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Max ,0 ,true ) );
202 rtl::Reference<SvxShapeGroupAnyD> xLossGainTarget(bBlack ? xLossTarget : xGainTarget);
204 uno::Reference< beans::XPropertySet > xPointProp( pSeries->getPropertiesOfPoint( nIndex ));
205 rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes;
207 OUString aPointCID = ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nIndex );
208 rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes( getSeriesGroupShape(pSeries.get(), xSeriesTarget) );
209 xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID);
212 //create min-max line
213 if( isValidPosition(aPosMiddleMinimum) && isValidPosition(aPosMiddleMaximum) )
215 std::vector<std::vector<css::drawing::Position3D>> aPoly
217 { aPosMiddleMinimum, aPosMiddleMaximum }
220 rtl::Reference<SvxShapePolyPolygon> xShape =
221 ShapeFactory::createLine2D( xPointGroupShape_Shapes, aPoly);
222 PropertyMapper::setMappedProperties( *xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
225 //create first-last shape
226 if(bJapaneseStyle && isValidPosition(aPosLeftFirst) && isValidPosition(aPosRightLast) )
228 drawing::Direction3D aDiff = aPosRightLast-aPosLeftFirst;
229 awt::Size aAWTSize( Direction3DToAWTSize( aDiff ));
230 // workaround for bug in drawing: if height is 0 the box gets infinitely large
231 if( aAWTSize.Height == 0 )
232 aAWTSize.Height = 1;
234 tNameSequence aNames;
235 tAnySequence aValues;
237 rtl::Reference<SvxShapeRect> xShape =
238 ShapeFactory::createRectangle( xLossGainTarget,
239 aAWTSize, Position3DToAWTPoint( aPosLeftFirst ),
240 aNames, aValues);
242 if(bBlack)
243 PropertyMapper::setMultiProperties( aBlackBox_Names, aBlackBox_Values, *xShape );
244 else
245 PropertyMapper::setMultiProperties( aWhiteBox_Names, aWhiteBox_Values, *xShape );
247 else
249 std::vector<std::vector<css::drawing::Position3D>> aPoly;
251 sal_Int32 nLineIndex = 0;
252 if( bShowFirst && pPosHelper->isLogicVisible( fUnscaledX, fUnscaledY_First ,fLogicZ )
253 && isValidPosition(aPosLeftFirst) && isValidPosition(aPosMiddleFirst) )
255 AddPointToPoly( aPoly, aPosLeftFirst, nLineIndex );
256 AddPointToPoly( aPoly, aPosMiddleFirst, nLineIndex++ );
258 if( pPosHelper->isLogicVisible( fUnscaledX, fUnscaledY_Last ,fLogicZ )
259 && isValidPosition(aPosMiddleLast) && isValidPosition(aPosRightLast) )
261 AddPointToPoly( aPoly, aPosMiddleLast, nLineIndex );
262 AddPointToPoly( aPoly, aPosRightLast, nLineIndex );
265 if( !aPoly.empty() )
267 rtl::Reference<SvxShapePolyPolygon> xShape =
268 ShapeFactory::createLine2D( xPointGroupShape_Shapes, aPoly );
269 PropertyMapper::setMappedProperties( *xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
273 //create data point label
274 if( pSeries->getDataPointLabelIfLabel(nIndex) )
276 if(isValidPosition(aPosMiddleFirst))
277 createDataLabel( xTextTarget, *pSeries, nIndex
278 , fUnscaledY_First, 1.0, Position3DToAWTPoint(aPosMiddleFirst), LABEL_ALIGN_LEFT_BOTTOM );
279 if(isValidPosition(aPosMiddleLast))
280 createDataLabel( xTextTarget, *pSeries, nIndex
281 , fUnscaledY_Last, 1.0, Position3DToAWTPoint(aPosMiddleLast), LABEL_ALIGN_RIGHT_TOP );
282 if(isValidPosition(aPosMiddleMinimum))
283 createDataLabel( xTextTarget, *pSeries, nIndex
284 , fUnscaledY_Min, 1.0, Position3DToAWTPoint(aPosMiddleMinimum), LABEL_ALIGN_BOTTOM );
285 if(isValidPosition(aPosMiddleMaximum))
286 createDataLabel( xTextTarget, *pSeries, nIndex
287 , fUnscaledY_Max, 1.0, Position3DToAWTPoint(aPosMiddleMaximum), LABEL_ALIGN_TOP );
289 }//next series in x slot (next y slot)
290 fSlotX+=1.0;
291 }//next x slot
292 }//next z slot
293 }//next category
294 /* @todo remove series shapes if empty
295 //remove and delete point-group-shape if empty
296 if(!xSeriesGroupShape_Shapes->getCount())
298 pSeries->m_xShape.set(NULL);
299 m_xLogicTarget->remove(xSeriesGroupShape_Shape);
303 //remove and delete series-group-shape if empty
305 //... todo
308 } //namespace chart
310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */