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_chartcontroller.hxx" 26 27 #include "SeriesOptionsItemConverter.hxx" 28 #include "SchWhichPairs.hxx" 29 30 #include "macros.hxx" 31 #include "ItemPropertyMap.hxx" 32 #include "GraphicPropertyItemConverter.hxx" 33 #include "MultipleItemConverter.hxx" 34 #include "ChartModelHelper.hxx" 35 #include "AxisHelper.hxx" 36 #include "DiagramHelper.hxx" 37 #include "ChartTypeHelper.hxx" 38 #include "DataSeriesHelper.hxx" 39 40 #include <com/sun/star/chart/MissingValueTreatment.hpp> 41 #include <com/sun/star/chart2/XDataSeries.hpp> 42 43 // for SfxBoolItem 44 #include <svl/eitem.hxx> 45 #include <svl/intitem.hxx> 46 47 //SfxIntegerListItem 48 #include <svl/ilstitem.hxx> 49 #define _SVSTDARR_ULONGS 50 #include <svl/svstdarr.hxx> 51 52 #include <rtl/math.hxx> 53 #include <functional> 54 #include <algorithm> 55 56 using namespace ::com::sun::star; 57 using namespace ::com::sun::star::chart2; 58 59 namespace chart 60 { 61 namespace wrapper 62 { 63 64 // ======================================== 65 66 SeriesOptionsItemConverter::SeriesOptionsItemConverter( 67 const uno::Reference< frame::XModel >& xChartModel 68 , const uno::Reference< uno::XComponentContext > & xContext 69 , const uno::Reference< beans::XPropertySet >& xPropertySet 70 , SfxItemPool& rItemPool ) 71 : ItemConverter( xPropertySet, rItemPool ) 72 , m_xChartModel(xChartModel) 73 , m_xCC(xContext) 74 , m_bAttachToMainAxis(true) 75 , m_bSupportingOverlapAndGapWidthProperties(false) 76 , m_bSupportingBarConnectors(false) 77 , m_nBarOverlap(0) 78 , m_nGapWidth(100) 79 , m_bConnectBars(false) 80 , m_bSupportingAxisSideBySide(false) 81 , m_bGroupBarsPerAxis(true) 82 , m_bAllSeriesAttachedToSameAxis(true) 83 , m_nAllSeriesAxisIndex(-1) 84 , m_bSupportingStartingAngle(false) 85 , m_nStartingAngle(90) 86 , m_bClockwise(false) 87 , m_aSupportedMissingValueTreatments() 88 , m_nMissingValueTreatment(0) 89 , m_bSupportingPlottingOfHiddenCells(false) 90 , m_bIncludeHiddenCells(true) 91 { 92 try 93 { 94 uno::Reference< XDataSeries > xDataSeries( xPropertySet, uno::UNO_QUERY ); 95 96 m_bAttachToMainAxis = DiagramHelper::isSeriesAttachedToMainAxis( xDataSeries ); 97 98 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram(xChartModel) ); 99 uno::Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); 100 uno::Reference< XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram , xDataSeries ) ); 101 102 m_xCooSys = DataSeriesHelper::getCoordinateSystemOfSeries( xDataSeries, xDiagram ); 103 if( m_xCooSys.is() ) 104 { 105 uno::Reference< chart2::XAxis > xAxis( AxisHelper::getAxis( 1, 0, m_xCooSys ) ); 106 chart2::ScaleData aScale( xAxis->getScaleData() ); 107 m_bClockwise = (aScale.Orientation == chart2::AxisOrientation_REVERSE); 108 } 109 110 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); 111 m_bSupportingOverlapAndGapWidthProperties = ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( xChartType, nDimensionCount ); 112 113 if( m_bSupportingOverlapAndGapWidthProperties ) 114 { 115 116 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); 117 118 uno::Sequence< sal_Int32 > m_aBarPositionSequence; 119 uno::Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY ); 120 if( xChartTypeProps.is() ) 121 { 122 if( xChartTypeProps->getPropertyValue( C2U( "OverlapSequence" ) ) >>= m_aBarPositionSequence ) 123 { 124 if( nAxisIndex >= 0 && nAxisIndex < m_aBarPositionSequence.getLength() ) 125 m_nBarOverlap = m_aBarPositionSequence[nAxisIndex]; 126 } 127 if( xChartTypeProps->getPropertyValue( C2U( "GapwidthSequence" ) ) >>= m_aBarPositionSequence ) 128 { 129 if( nAxisIndex >= 0 && nAxisIndex < m_aBarPositionSequence.getLength() ) 130 m_nGapWidth = m_aBarPositionSequence[nAxisIndex]; 131 } 132 } 133 } 134 135 m_bSupportingBarConnectors = ChartTypeHelper::isSupportingBarConnectors( xChartType, nDimensionCount ); 136 if( m_bSupportingBarConnectors && xDiagramProperties.is() ) 137 { 138 xDiagramProperties->getPropertyValue( C2U("ConnectBars")) >>= m_bConnectBars; 139 } 140 141 m_bSupportingAxisSideBySide = ChartTypeHelper::isSupportingAxisSideBySide( xChartType, nDimensionCount ); 142 if( m_bSupportingAxisSideBySide && xDiagramProperties.is() ) 143 { 144 xDiagramProperties->getPropertyValue( C2U("GroupBarsPerAxis")) >>= m_bGroupBarsPerAxis; 145 m_bAllSeriesAttachedToSameAxis = DataSeriesHelper::areAllSeriesAttachedToSameAxis( xChartType, m_nAllSeriesAxisIndex ); 146 } 147 148 m_bSupportingStartingAngle = ChartTypeHelper::isSupportingStartingAngle( xChartType ); 149 if( m_bSupportingStartingAngle ) 150 { 151 xDiagramProperties->getPropertyValue( C2U( "StartingAngle" ) ) >>= m_nStartingAngle; 152 } 153 154 m_aSupportedMissingValueTreatments = ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ); 155 m_nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( 156 ChartModelHelper::findDiagram(m_xChartModel), xChartType ); 157 158 uno::Reference< XChartDocument > xChartDoc( m_xChartModel, uno::UNO_QUERY ); 159 uno::Reference< beans::XPropertySet > xProp( xChartDoc->getDataProvider(), uno::UNO_QUERY ); 160 if( xProp.is() ) 161 { 162 try 163 { 164 //test whether the data provider offers this property 165 xProp->getPropertyValue(C2U("IncludeHiddenCells")); 166 //if not exception is thrown the property is offered 167 m_bSupportingPlottingOfHiddenCells = true; 168 xDiagramProperties->getPropertyValue( C2U("IncludeHiddenCells") ) >>= m_bIncludeHiddenCells; 169 } 170 catch( const beans::UnknownPropertyException& ) 171 { 172 } 173 } 174 } 175 catch( uno::Exception ex ) 176 { 177 ASSERT_EXCEPTION( ex ); 178 } 179 } 180 181 SeriesOptionsItemConverter::~SeriesOptionsItemConverter() 182 { 183 } 184 185 const sal_uInt16 * SeriesOptionsItemConverter::GetWhichPairs() const 186 { 187 // must span all used items! 188 return nSeriesOptionsWhichPairs; 189 } 190 191 bool SeriesOptionsItemConverter::GetItemProperty( tWhichIdType /*nWhichId*/, tPropertyNameWithMemberId & /*rOutProperty*/ ) const 192 { 193 return false; 194 } 195 196 bool SeriesOptionsItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) 197 { 198 bool bChanged = false; 199 switch( nWhichId ) 200 { 201 case SCHATTR_AXIS: 202 { 203 sal_Int32 nItemValue = static_cast< const SfxInt32Item & >( 204 rItemSet.Get( nWhichId )).GetValue(); 205 bool bAttachToMainAxis = nItemValue == CHART_AXIS_PRIMARY_Y; 206 if( bAttachToMainAxis != m_bAttachToMainAxis ) 207 { 208 //change model: 209 bChanged = DiagramHelper::attachSeriesToAxis( bAttachToMainAxis, uno::Reference< XDataSeries >::query( GetPropertySet() ) 210 , ChartModelHelper::findDiagram(m_xChartModel), m_xCC ); 211 212 if( bChanged ) 213 m_bAttachToMainAxis = bAttachToMainAxis; 214 } 215 } 216 break; 217 218 case SCHATTR_BAR_OVERLAP: 219 case SCHATTR_BAR_GAPWIDTH: 220 { 221 if( m_bSupportingOverlapAndGapWidthProperties ) 222 { 223 sal_Int32& rBarPosition = ( SCHATTR_BAR_OVERLAP == nWhichId ) ? m_nBarOverlap : m_nGapWidth; 224 rBarPosition = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue(); 225 226 rtl::OUString aPropName( C2U( "GapwidthSequence" ) ); 227 if( SCHATTR_BAR_OVERLAP == nWhichId ) 228 aPropName = C2U( "OverlapSequence" ); 229 230 uno::Reference< XDataSeries > xDataSeries( GetPropertySet(), uno::UNO_QUERY ); 231 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram(m_xChartModel) ); 232 uno::Reference< beans::XPropertySet > xChartTypeProps( DiagramHelper::getChartTypeOfSeries( xDiagram , xDataSeries ), uno::UNO_QUERY ); 233 if( xChartTypeProps.is() ) 234 { 235 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); 236 uno::Sequence< sal_Int32 > m_aBarPositionSequence; 237 if( xChartTypeProps.is() ) 238 { 239 if( xChartTypeProps->getPropertyValue( aPropName ) >>= m_aBarPositionSequence ) 240 { 241 bool bGroupBarsPerAxis = static_cast< const SfxBoolItem & >(rItemSet.Get( SCHATTR_GROUP_BARS_PER_AXIS )).GetValue(); 242 if(!bGroupBarsPerAxis) 243 { 244 //set the same value for all axes 245 for( sal_Int32 nN = 0; nN < m_aBarPositionSequence.getLength(); nN++ ) 246 m_aBarPositionSequence[nN] = rBarPosition; 247 } 248 else if( nAxisIndex >= 0 && nAxisIndex < m_aBarPositionSequence.getLength() ) 249 m_aBarPositionSequence[nAxisIndex] = rBarPosition; 250 251 xChartTypeProps->setPropertyValue( aPropName, uno::makeAny(m_aBarPositionSequence) ); 252 bChanged = true; 253 } 254 } 255 } 256 } 257 } 258 break; 259 260 case SCHATTR_BAR_CONNECT: 261 { 262 sal_Bool bOldConnectBars = sal_False; 263 m_bConnectBars = static_cast< const SfxBoolItem & >( 264 rItemSet.Get( nWhichId )).GetValue(); 265 if( m_bSupportingBarConnectors ) 266 { 267 uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); 268 if( xDiagramProperties.is() && 269 (xDiagramProperties->getPropertyValue( C2U("ConnectBars")) >>= bOldConnectBars) && 270 bOldConnectBars != m_bConnectBars ) 271 { 272 xDiagramProperties->setPropertyValue( C2U("ConnectBars"), uno::makeAny(m_bConnectBars) ); 273 bChanged = true; 274 } 275 } 276 } 277 break; 278 279 case SCHATTR_GROUP_BARS_PER_AXIS: 280 { 281 bool bOldGroupBarsPerAxis = true; 282 m_bGroupBarsPerAxis = static_cast< const SfxBoolItem & >( 283 rItemSet.Get( nWhichId )).GetValue(); 284 if( m_bSupportingAxisSideBySide ) 285 { 286 uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); 287 if( xDiagramProperties.is() && 288 (xDiagramProperties->getPropertyValue( C2U("GroupBarsPerAxis")) >>= bOldGroupBarsPerAxis) && 289 bOldGroupBarsPerAxis != m_bGroupBarsPerAxis ) 290 { 291 xDiagramProperties->setPropertyValue( C2U("GroupBarsPerAxis"), uno::makeAny(m_bGroupBarsPerAxis) ); 292 bChanged = true; 293 } 294 } 295 } 296 break; 297 298 case SCHATTR_STARTING_ANGLE: 299 { 300 if( m_bSupportingStartingAngle ) 301 { 302 m_nStartingAngle = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue(); 303 uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); 304 if( xDiagramProperties.is() ) 305 { 306 xDiagramProperties->setPropertyValue( C2U("StartingAngle"), uno::makeAny(m_nStartingAngle) ); 307 bChanged = true; 308 } 309 } 310 } 311 break; 312 313 case SCHATTR_CLOCKWISE: 314 { 315 bool bClockwise = (static_cast< const SfxBoolItem & >( 316 rItemSet.Get( nWhichId )).GetValue() ); 317 if( m_xCooSys.is() ) 318 { 319 uno::Reference< chart2::XAxis > xAxis( AxisHelper::getAxis( 1, 0, m_xCooSys ) ); 320 if( xAxis.is() ) 321 { 322 chart2::ScaleData aScaleData( xAxis->getScaleData() ); 323 aScaleData.Orientation = bClockwise ? chart2::AxisOrientation_REVERSE : chart2::AxisOrientation_MATHEMATICAL; 324 xAxis->setScaleData( aScaleData ); 325 bChanged = true; 326 } 327 } 328 } 329 break; 330 331 case SCHATTR_MISSING_VALUE_TREATMENT: 332 { 333 if( m_aSupportedMissingValueTreatments.getLength() ) 334 { 335 sal_Int32 nNew = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue(); 336 if( m_nMissingValueTreatment != nNew ) 337 { 338 try 339 { 340 uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); 341 if( xDiagramProperties.is() ) 342 { 343 xDiagramProperties->setPropertyValue( C2U( "MissingValueTreatment" ), uno::makeAny( nNew )); 344 bChanged = true; 345 } 346 } 347 catch( uno::Exception& e ) 348 { 349 ASSERT_EXCEPTION( e ); 350 } 351 } 352 } 353 } 354 break; 355 case SCHATTR_INCLUDE_HIDDEN_CELLS: 356 { 357 if( m_bSupportingPlottingOfHiddenCells ) 358 { 359 bool bIncludeHiddenCells = static_cast<const SfxBoolItem &>(rItemSet.Get(nWhichId)).GetValue(); 360 if (bIncludeHiddenCells != m_bIncludeHiddenCells) 361 bChanged = ChartModelHelper::setIncludeHiddenCells( bIncludeHiddenCells, m_xChartModel ); 362 } 363 } 364 break; 365 } 366 return bChanged; 367 } 368 369 void SeriesOptionsItemConverter::FillSpecialItem( 370 sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const 371 { 372 switch( nWhichId ) 373 { 374 case SCHATTR_AXIS: 375 { 376 sal_Int32 nItemValue = m_bAttachToMainAxis ? CHART_AXIS_PRIMARY_Y : CHART_AXIS_SECONDARY_Y; 377 rOutItemSet.Put( SfxInt32Item(nWhichId,nItemValue ) ); 378 break; 379 } 380 case SCHATTR_BAR_OVERLAP: 381 { 382 if( m_bSupportingOverlapAndGapWidthProperties ) 383 rOutItemSet.Put( SfxInt32Item(nWhichId,m_nBarOverlap) ); 384 break; 385 } 386 case SCHATTR_BAR_GAPWIDTH: 387 { 388 if( m_bSupportingOverlapAndGapWidthProperties ) 389 rOutItemSet.Put( SfxInt32Item(nWhichId,m_nGapWidth) ); 390 break; 391 } 392 case SCHATTR_BAR_CONNECT: 393 { 394 if( m_bSupportingBarConnectors ) 395 rOutItemSet.Put( SfxBoolItem(nWhichId,m_bConnectBars)); 396 break; 397 } 398 case SCHATTR_GROUP_BARS_PER_AXIS: 399 { 400 if( m_bSupportingAxisSideBySide ) 401 rOutItemSet.Put( SfxBoolItem(nWhichId,m_bGroupBarsPerAxis) ); 402 break; 403 } 404 case SCHATTR_AXIS_FOR_ALL_SERIES: 405 { 406 if( m_nAllSeriesAxisIndex != - 1) 407 rOutItemSet.Put( SfxInt32Item(nWhichId, m_nAllSeriesAxisIndex)); 408 break; 409 } 410 case SCHATTR_STARTING_ANGLE: 411 { 412 if( m_bSupportingStartingAngle ) 413 rOutItemSet.Put( SfxInt32Item(nWhichId,m_nStartingAngle)); 414 break; 415 } 416 case SCHATTR_CLOCKWISE: 417 { 418 rOutItemSet.Put( SfxBoolItem(nWhichId,m_bClockwise) ); 419 break; 420 } 421 case SCHATTR_MISSING_VALUE_TREATMENT: 422 { 423 if( m_aSupportedMissingValueTreatments.getLength() ) 424 rOutItemSet.Put( SfxInt32Item( nWhichId, m_nMissingValueTreatment )); 425 break; 426 } 427 case SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS: 428 { 429 SvULongs aList; 430 for ( sal_Int32 nN=0; nN<m_aSupportedMissingValueTreatments.getLength(); nN++ ) 431 aList.Insert( m_aSupportedMissingValueTreatments[nN], sal::static_int_cast< sal_uInt16 >(nN) ); 432 rOutItemSet.Put( SfxIntegerListItem( nWhichId, aList ) ); 433 break; 434 } 435 case SCHATTR_INCLUDE_HIDDEN_CELLS: 436 { 437 if( m_bSupportingPlottingOfHiddenCells ) 438 rOutItemSet.Put( SfxBoolItem(nWhichId, m_bIncludeHiddenCells) ); 439 break; 440 } 441 default: 442 break; 443 } 444 } 445 446 } // namespace wrapper 447 } // namespace chart 448