1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26
27 #include "ReferenceSizeProvider.hxx"
28 #include "RelativeSizeHelper.hxx"
29 #include "ChartModelHelper.hxx"
30 #include "DiagramHelper.hxx"
31 #include "macros.hxx"
32 #include "AxisHelper.hxx"
33 #include "DataSeriesHelper.hxx"
34
35 #include <com/sun/star/chart2/XTitled.hpp>
36 #include <com/sun/star/chart2/XTitle.hpp>
37 #include <com/sun/star/chart2/XDataSeries.hpp>
38
39 #include <vector>
40
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::chart2;
43
44 using ::com::sun::star::uno::Reference;
45 using ::com::sun::star::uno::Sequence;
46 using ::rtl::OUString;
47
48 // ================================================================================
49
50 namespace chart
51 {
52
ReferenceSizeProvider(awt::Size aPageSize,const Reference<XChartDocument> & xChartDoc)53 ReferenceSizeProvider::ReferenceSizeProvider(
54 awt::Size aPageSize,
55 const Reference< XChartDocument > & xChartDoc ) :
56 m_aPageSize( aPageSize ),
57 m_xChartDoc( xChartDoc ),
58 m_bUseAutoScale( getAutoResizeState( xChartDoc ) == AUTO_RESIZE_YES )
59 {}
60
getPageSize() const61 awt::Size ReferenceSizeProvider::getPageSize() const
62 {
63 return m_aPageSize;
64 }
65
useAutoScale() const66 bool ReferenceSizeProvider::useAutoScale() const
67 {
68 return m_bUseAutoScale;
69 }
70
impl_setValuesAtTitled(const Reference<XTitled> & xTitled)71 void ReferenceSizeProvider::impl_setValuesAtTitled(
72 const Reference< XTitled > & xTitled )
73 {
74 if( xTitled.is())
75 {
76 Reference< XTitle > xTitle( xTitled->getTitleObject());
77 if( xTitle.is())
78 setValuesAtTitle( xTitle );
79 }
80 }
81
setValuesAtTitle(const Reference<XTitle> & xTitle)82 void ReferenceSizeProvider::setValuesAtTitle(
83 const Reference< XTitle > & xTitle )
84 {
85 try
86 {
87 Reference< beans::XPropertySet > xTitleProp( xTitle, uno::UNO_QUERY_THROW );
88 awt::Size aOldRefSize;
89 bool bHasOldRefSize(
90 xTitleProp->getPropertyValue( C2U("ReferencePageSize")) >>= aOldRefSize );
91
92 // set from auto-resize on to off -> adapt font sizes at XFormattedStrings
93 if( bHasOldRefSize && ! useAutoScale())
94 {
95 uno::Sequence< uno::Reference< XFormattedString > > aStrSeq(
96 xTitle->getText());
97 for( sal_Int32 i=0; i<aStrSeq.getLength(); ++i )
98 {
99 RelativeSizeHelper::adaptFontSizes(
100 Reference< beans::XPropertySet >( aStrSeq[i], uno::UNO_QUERY ),
101 aOldRefSize, getPageSize());
102 }
103 }
104
105 setValuesAtPropertySet( xTitleProp, /* bAdaptFontSizes = */ false );
106 }
107 catch( const uno::Exception & ex )
108 {
109 ASSERT_EXCEPTION( ex );
110 }
111 }
112
setValuesAtAllDataSeries()113 void ReferenceSizeProvider::setValuesAtAllDataSeries()
114 {
115 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDoc ));
116
117 // DataSeries/Points
118 ::std::vector< Reference< XDataSeries > > aSeries(
119 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
120
121 for( ::std::vector< Reference< XDataSeries > >::const_iterator aIt( aSeries.begin());
122 aIt != aSeries.end(); ++aIt )
123 {
124 Reference< beans::XPropertySet > xSeriesProp( *aIt, uno::UNO_QUERY );
125 if( xSeriesProp.is())
126 {
127 // data points
128 Sequence< sal_Int32 > aPointIndexes;
129 try
130 {
131 if( xSeriesProp->getPropertyValue( C2U("AttributedDataPoints")) >>= aPointIndexes )
132 {
133 for( sal_Int32 i=0; i< aPointIndexes.getLength(); ++i )
134 setValuesAtPropertySet(
135 (*aIt)->getDataPointByIndex( aPointIndexes[i] ) );
136 }
137 }
138 catch( const uno::Exception & ex )
139 {
140 ASSERT_EXCEPTION( ex );
141 }
142
143 //it is important to correct the datapoint properties first as they do reference the series properties
144 setValuesAtPropertySet( xSeriesProp );
145 }
146 }
147 }
148
setValuesAtPropertySet(const Reference<beans::XPropertySet> & xProp,bool bAdaptFontSizes)149 void ReferenceSizeProvider::setValuesAtPropertySet(
150 const Reference< beans::XPropertySet > & xProp,
151 bool bAdaptFontSizes /* = true */ )
152 {
153 if( ! xProp.is())
154 return;
155
156 static const OUString aRefSizeName( RTL_CONSTASCII_USTRINGPARAM("ReferencePageSize"));
157
158 try
159 {
160 awt::Size aRefSize( getPageSize() );
161 awt::Size aOldRefSize;
162 bool bHasOldRefSize( xProp->getPropertyValue( aRefSizeName ) >>= aOldRefSize );
163
164 if( useAutoScale())
165 {
166 if( ! bHasOldRefSize )
167 xProp->setPropertyValue( aRefSizeName, uno::makeAny( aRefSize ));
168 }
169 else
170 {
171 if( bHasOldRefSize )
172 {
173 xProp->setPropertyValue( aRefSizeName, uno::Any());
174
175 // adapt font sizes
176 if( bAdaptFontSizes )
177 RelativeSizeHelper::adaptFontSizes( xProp, aOldRefSize, aRefSize );
178 }
179 }
180 }
181 catch( const uno::Exception & ex )
182 {
183 ASSERT_EXCEPTION( ex );
184 }
185 }
186
getAutoResizeFromPropSet(const Reference<beans::XPropertySet> & xProp,ReferenceSizeProvider::AutoResizeState & rInOutState)187 void ReferenceSizeProvider::getAutoResizeFromPropSet(
188 const Reference< beans::XPropertySet > & xProp,
189 ReferenceSizeProvider::AutoResizeState & rInOutState )
190 {
191 static const OUString aRefSizeName( RTL_CONSTASCII_USTRINGPARAM("ReferencePageSize"));
192 AutoResizeState eSingleState = AUTO_RESIZE_UNKNOWN;
193
194 if( xProp.is())
195 {
196 try
197 {
198 if( xProp->getPropertyValue( aRefSizeName ).hasValue())
199 eSingleState = AUTO_RESIZE_YES;
200 else
201 eSingleState = AUTO_RESIZE_NO;
202 }
203 catch( uno::Exception )
204 {
205 // unknown property -> state stays unknown
206 }
207 }
208
209 // curent state unknown => nothing changes. Otherwise if current state
210 // differs from state so far, we have an ambiguity
211 if( rInOutState == AUTO_RESIZE_UNKNOWN )
212 {
213 rInOutState = eSingleState;
214 }
215 else if( eSingleState != AUTO_RESIZE_UNKNOWN &&
216 eSingleState != rInOutState )
217 {
218 rInOutState = AUTO_RESIZE_AMBIGUOUS;
219 }
220 }
221
impl_getAutoResizeFromTitled(const Reference<XTitled> & xTitled,ReferenceSizeProvider::AutoResizeState & rInOutState)222 void ReferenceSizeProvider::impl_getAutoResizeFromTitled(
223 const Reference< XTitled > & xTitled,
224 ReferenceSizeProvider::AutoResizeState & rInOutState )
225 {
226 if( xTitled.is())
227 {
228 Reference< beans::XPropertySet > xProp( xTitled->getTitleObject(), uno::UNO_QUERY );
229 if( xProp.is())
230 getAutoResizeFromPropSet( xProp, rInOutState );
231 }
232 }
233
234 /** Retrieves the state auto-resize from all objects that support this
235 feature. If all objects return the same state, AUTO_RESIZE_YES or
236 AUTO_RESIZE_NO is returned.
237
238 If no object supporting the feature is found, AUTO_RESIZE_UNKNOWN is
239 returned. If there are multiple objects, some with state YES and some
240 with state NO, AUTO_RESIZE_AMBIGUOUS is returned.
241 */
getAutoResizeState(const Reference<XChartDocument> & xChartDoc)242 ReferenceSizeProvider::AutoResizeState ReferenceSizeProvider::getAutoResizeState(
243 const Reference< XChartDocument > & xChartDoc )
244 {
245 AutoResizeState eResult = AUTO_RESIZE_UNKNOWN;
246
247 // Main Title
248 Reference< XTitled > xDocTitled( xChartDoc, uno::UNO_QUERY );
249 if( xDocTitled.is())
250 impl_getAutoResizeFromTitled( xDocTitled, eResult );
251 if( eResult == AUTO_RESIZE_AMBIGUOUS )
252 return eResult;
253
254 // diagram is needed by the rest of the objects
255 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ), uno::UNO_QUERY );
256 if( ! xDiagram.is())
257 return eResult;
258
259 // Sub Title
260 Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY );
261 if( xDiaTitled.is())
262 impl_getAutoResizeFromTitled( xDiaTitled, eResult );
263 if( eResult == AUTO_RESIZE_AMBIGUOUS )
264 return eResult;
265
266 // Legend
267 Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY );
268 if( xLegendProp.is())
269 getAutoResizeFromPropSet( xLegendProp, eResult );
270 if( eResult == AUTO_RESIZE_AMBIGUOUS )
271 return eResult;
272
273 // Axes (incl. Axis Titles)
274 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
275 for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
276 {
277 Reference< beans::XPropertySet > xProp( aAxes[i], uno::UNO_QUERY );
278 if( xProp.is())
279 getAutoResizeFromPropSet( xProp, eResult );
280 Reference< XTitled > xTitled( aAxes[i], uno::UNO_QUERY );
281 if( xTitled.is())
282 {
283 impl_getAutoResizeFromTitled( xTitled, eResult );
284 if( eResult == AUTO_RESIZE_AMBIGUOUS )
285 return eResult;
286 }
287 }
288
289 // DataSeries/Points
290 ::std::vector< Reference< XDataSeries > > aSeries(
291 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
292
293 for( ::std::vector< Reference< XDataSeries > >::const_iterator aIt( aSeries.begin());
294 aIt != aSeries.end(); ++aIt )
295 {
296 Reference< beans::XPropertySet > xSeriesProp( *aIt, uno::UNO_QUERY );
297 if( xSeriesProp.is())
298 {
299 getAutoResizeFromPropSet( xSeriesProp, eResult );
300 if( eResult == AUTO_RESIZE_AMBIGUOUS )
301 return eResult;
302
303 // data points
304 Sequence< sal_Int32 > aPointIndexes;
305 try
306 {
307 if( xSeriesProp->getPropertyValue( C2U("AttributedDataPoints")) >>= aPointIndexes )
308 {
309 for( sal_Int32 i=0; i< aPointIndexes.getLength(); ++i )
310 {
311 getAutoResizeFromPropSet(
312 (*aIt)->getDataPointByIndex( aPointIndexes[i] ), eResult );
313 if( eResult == AUTO_RESIZE_AMBIGUOUS )
314 return eResult;
315 }
316 }
317 }
318 catch( const uno::Exception & ex )
319 {
320 ASSERT_EXCEPTION( ex );
321 }
322 }
323 }
324
325 return eResult;
326 }
327
toggleAutoResizeState()328 void ReferenceSizeProvider::toggleAutoResizeState()
329 {
330 setAutoResizeState( m_bUseAutoScale ? AUTO_RESIZE_NO : AUTO_RESIZE_YES );
331 }
332
333
334 /** sets the auto-resize at all objects that support this feature for text.
335 eNewState must be either AUTO_RESIZE_YES or AUTO_RESIZE_NO
336 */
setAutoResizeState(ReferenceSizeProvider::AutoResizeState eNewState)337 void ReferenceSizeProvider::setAutoResizeState( ReferenceSizeProvider::AutoResizeState eNewState )
338 {
339 m_bUseAutoScale = (eNewState == AUTO_RESIZE_YES);
340
341 // Main Title
342 impl_setValuesAtTitled( Reference< XTitled >( m_xChartDoc, uno::UNO_QUERY ));
343
344 // diagram is needed by the rest of the objects
345 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDoc ), uno::UNO_QUERY );
346 if( ! xDiagram.is())
347 return;
348
349 // Sub Title
350 impl_setValuesAtTitled( Reference< XTitled >( xDiagram, uno::UNO_QUERY ));
351
352 // Legend
353 Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY );
354 if( xLegendProp.is())
355 setValuesAtPropertySet( xLegendProp );
356
357 // Axes (incl. Axis Titles)
358 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
359 for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
360 {
361 Reference< beans::XPropertySet > xProp( aAxes[i], uno::UNO_QUERY );
362 if( xProp.is())
363 setValuesAtPropertySet( xProp );
364 impl_setValuesAtTitled( Reference< XTitled >( aAxes[i], uno::UNO_QUERY ));
365 }
366
367 // DataSeries/Points
368 setValuesAtAllDataSeries();
369
370 // recalculate new state (in case it stays unknown or is ambiguous
371 m_bUseAutoScale = (getAutoResizeState( m_xChartDoc ) == AUTO_RESIZE_YES);
372 }
373
374 } // namespace chart
375