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 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 61 awt::Size ReferenceSizeProvider::getPageSize() const 62 { 63 return m_aPageSize; 64 } 65 66 bool ReferenceSizeProvider::useAutoScale() const 67 { 68 return m_bUseAutoScale; 69 } 70 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 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 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 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 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 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 */ 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 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 */ 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