Avoid potential negative array index access to cached text.
[LibreOffice.git] / chart2 / source / tools / ReferenceSizeProvider.cxx
blobb1ca0b429a7b7e9cf1e0c132a696de7636d8db34
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 <ReferenceSizeProvider.hxx>
21 #include <RelativeSizeHelper.hxx>
22 #include <ChartModelHelper.hxx>
23 #include <ChartModel.hxx>
24 #include <DataSeries.hxx>
25 #include <DataSeriesProperties.hxx>
26 #include <DiagramHelper.hxx>
27 #include <Diagram.hxx>
28 #include <Axis.hxx>
29 #include <AxisHelper.hxx>
30 #include <Legend.hxx>
31 #include <comphelper/diagnose_ex.hxx>
33 #include <vector>
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::chart2;
37 using namespace ::chart::DataSeriesProperties;
39 using ::com::sun::star::uno::Reference;
40 using ::com::sun::star::uno::Sequence;
42 namespace chart
45 ReferenceSizeProvider::ReferenceSizeProvider(
46 awt::Size aPageSize,
47 const rtl::Reference<::chart::ChartModel> & xChartDoc ) :
48 m_aPageSize( aPageSize ),
49 m_xChartDoc( xChartDoc ),
50 m_bUseAutoScale( getAutoResizeState( xChartDoc ) == AUTO_RESIZE_YES )
53 void ReferenceSizeProvider::impl_setValuesAtTitled(
54 const Reference< XTitled > & xTitled )
56 if( xTitled.is())
58 Reference< XTitle > xTitle( xTitled->getTitleObject());
59 if( xTitle.is())
60 setValuesAtTitle( xTitle );
64 void ReferenceSizeProvider::setValuesAtTitle(
65 const Reference< XTitle > & xTitle )
67 try
69 Reference< beans::XPropertySet > xTitleProp( xTitle, uno::UNO_QUERY_THROW );
70 awt::Size aOldRefSize;
71 bool bHasOldRefSize(
72 xTitleProp->getPropertyValue( "ReferencePageSize") >>= aOldRefSize );
74 // set from auto-resize on to off -> adapt font sizes at XFormattedStrings
75 if( bHasOldRefSize && ! useAutoScale())
77 const uno::Sequence< uno::Reference< XFormattedString > > aStrSeq(
78 xTitle->getText());
79 for( uno::Reference< XFormattedString > const & formattedStr : aStrSeq )
81 RelativeSizeHelper::adaptFontSizes(
82 Reference< beans::XPropertySet >( formattedStr, uno::UNO_QUERY ),
83 aOldRefSize, getPageSize());
87 setValuesAtPropertySet( xTitleProp, /* bAdaptFontSizes = */ false );
89 catch (const uno::Exception&)
91 DBG_UNHANDLED_EXCEPTION("chart2");
95 void ReferenceSizeProvider::setValuesAtAllDataSeries()
97 rtl::Reference< Diagram > xDiagram( m_xChartDoc->getFirstChartDiagram());
98 if (!xDiagram)
99 return;
101 // DataSeries/Points
102 std::vector< rtl::Reference< DataSeries > > aSeries =
103 xDiagram->getDataSeries();
105 for (auto const& elem : aSeries)
107 // data points
108 Sequence< sal_Int32 > aPointIndexes;
111 // "AttributedDataPoints"
112 if( elem->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= aPointIndexes )
114 for( sal_Int32 idx : std::as_const(aPointIndexes) )
115 setValuesAtPropertySet(
116 elem->getDataPointByIndex( idx ) );
119 catch (const uno::Exception&)
121 DBG_UNHANDLED_EXCEPTION("chart2");
124 //it is important to correct the datapoint properties first as they do reference the series properties
125 setValuesAtPropertySet( elem );
129 void ReferenceSizeProvider::setValuesAtPropertySet(
130 const Reference< beans::XPropertySet > & xProp,
131 bool bAdaptFontSizes /* = true */ )
133 if( ! xProp.is())
134 return;
136 static constexpr OUString aRefSizeName = u"ReferencePageSize"_ustr;
140 awt::Size aRefSize( getPageSize() );
141 awt::Size aOldRefSize;
142 bool bHasOldRefSize( xProp->getPropertyValue( aRefSizeName ) >>= aOldRefSize );
144 if( useAutoScale())
146 if( ! bHasOldRefSize )
147 xProp->setPropertyValue( aRefSizeName, uno::Any( aRefSize ));
149 else
151 if( bHasOldRefSize )
153 xProp->setPropertyValue( aRefSizeName, uno::Any());
155 // adapt font sizes
156 if( bAdaptFontSizes )
157 RelativeSizeHelper::adaptFontSizes( xProp, aOldRefSize, aRefSize );
161 catch (const uno::Exception&)
163 DBG_UNHANDLED_EXCEPTION("chart2");
167 void ReferenceSizeProvider::getAutoResizeFromPropSet(
168 const Reference< beans::XPropertySet > & xProp,
169 ReferenceSizeProvider::AutoResizeState & rInOutState )
171 AutoResizeState eSingleState = AUTO_RESIZE_UNKNOWN;
173 if( xProp.is())
177 if( xProp->getPropertyValue( "ReferencePageSize" ).hasValue())
178 eSingleState = AUTO_RESIZE_YES;
179 else
180 eSingleState = AUTO_RESIZE_NO;
182 catch (const uno::Exception&)
184 // unknown property -> state stays unknown
188 // current state unknown => nothing changes. Otherwise if current state
189 // differs from state so far, we have an ambiguity
190 if( rInOutState == AUTO_RESIZE_UNKNOWN )
192 rInOutState = eSingleState;
194 else if( eSingleState != AUTO_RESIZE_UNKNOWN &&
195 eSingleState != rInOutState )
197 rInOutState = AUTO_RESIZE_AMBIGUOUS;
201 void ReferenceSizeProvider::impl_getAutoResizeFromTitled(
202 const Reference< XTitled > & xTitled,
203 ReferenceSizeProvider::AutoResizeState & rInOutState )
205 if( xTitled.is())
207 Reference< beans::XPropertySet > xProp( xTitled->getTitleObject(), uno::UNO_QUERY );
208 if( xProp.is())
209 getAutoResizeFromPropSet( xProp, rInOutState );
213 /** Retrieves the state auto-resize from all objects that support this
214 feature. If all objects return the same state, AUTO_RESIZE_YES or
215 AUTO_RESIZE_NO is returned.
217 If no object supporting the feature is found, AUTO_RESIZE_UNKNOWN is
218 returned. If there are multiple objects, some with state YES and some
219 with state NO, AUTO_RESIZE_AMBIGUOUS is returned.
221 ReferenceSizeProvider::AutoResizeState ReferenceSizeProvider::getAutoResizeState(
222 const rtl::Reference<::chart::ChartModel> & xChartDoc )
224 AutoResizeState eResult = AUTO_RESIZE_UNKNOWN;
226 // Main Title
227 if( xChartDoc.is())
228 impl_getAutoResizeFromTitled( xChartDoc, eResult );
229 if( eResult == AUTO_RESIZE_AMBIGUOUS )
230 return eResult;
232 // diagram is needed by the rest of the objects
233 rtl::Reference< Diagram > xDiagram = xChartDoc->getFirstChartDiagram();
234 if( ! xDiagram.is())
235 return eResult;
237 // Sub Title
238 if( xDiagram.is())
239 impl_getAutoResizeFromTitled( xDiagram, eResult );
240 if( eResult == AUTO_RESIZE_AMBIGUOUS )
241 return eResult;
243 // Legend
244 rtl::Reference< Legend > xLegend( xDiagram->getLegend2() );
245 if( xLegend.is())
246 getAutoResizeFromPropSet( xLegend, eResult );
247 if( eResult == AUTO_RESIZE_AMBIGUOUS )
248 return eResult;
250 // Axes (incl. Axis Titles)
251 const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
252 for( rtl::Reference< Axis > const & axis : aAxes )
254 getAutoResizeFromPropSet( axis, eResult );
255 impl_getAutoResizeFromTitled( axis, eResult );
256 if( eResult == AUTO_RESIZE_AMBIGUOUS )
257 return eResult;
260 // DataSeries/Points
261 std::vector< rtl::Reference< DataSeries > > aSeries =
262 xDiagram->getDataSeries();
264 for (auto const& elem : aSeries)
266 getAutoResizeFromPropSet( elem, eResult );
267 if( eResult == AUTO_RESIZE_AMBIGUOUS )
268 return eResult;
270 // data points
271 Sequence< sal_Int32 > aPointIndexes;
274 // "AttributedDataPoints"
275 if( elem->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= aPointIndexes )
277 for( sal_Int32 idx : std::as_const(aPointIndexes) )
279 getAutoResizeFromPropSet(
280 elem->getDataPointByIndex( idx ), eResult );
281 if( eResult == AUTO_RESIZE_AMBIGUOUS )
282 return eResult;
286 catch (const uno::Exception&)
288 DBG_UNHANDLED_EXCEPTION("chart2");
292 return eResult;
295 void ReferenceSizeProvider::toggleAutoResizeState()
297 setAutoResizeState( m_bUseAutoScale ? AUTO_RESIZE_NO : AUTO_RESIZE_YES );
300 /** sets the auto-resize at all objects that support this feature for text.
301 eNewState must be either AUTO_RESIZE_YES or AUTO_RESIZE_NO
303 void ReferenceSizeProvider::setAutoResizeState( ReferenceSizeProvider::AutoResizeState eNewState )
305 m_bUseAutoScale = (eNewState == AUTO_RESIZE_YES);
307 // Main Title
308 impl_setValuesAtTitled( m_xChartDoc );
310 // diagram is needed by the rest of the objects
311 rtl::Reference< Diagram > xDiagram = m_xChartDoc->getFirstChartDiagram();
312 if( ! xDiagram.is())
313 return;
315 // Sub Title
316 impl_setValuesAtTitled( xDiagram );
318 // Legend
319 rtl::Reference< Legend > xLegend( xDiagram->getLegend2() );
320 if( xLegend.is())
321 setValuesAtPropertySet( xLegend );
323 // Axes (incl. Axis Titles)
324 const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
325 for( rtl::Reference< Axis > const & axis : aAxes )
327 setValuesAtPropertySet( axis );
328 impl_setValuesAtTitled( axis );
331 // DataSeries/Points
332 setValuesAtAllDataSeries();
334 // recalculate new state (in case it stays unknown or is ambiguous
335 m_bUseAutoScale = (getAutoResizeState( m_xChartDoc ) == AUTO_RESIZE_YES);
338 } // namespace chart
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */