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_xmloff.hxx" 26 27 #include "SchXMLAxisContext.hxx" 28 #include "SchXMLChartContext.hxx" 29 #include "SchXMLTools.hxx" 30 #include <xmloff/xmlnmspe.hxx> 31 #include <xmloff/xmlement.hxx> 32 #include <xmloff/xmlstyle.hxx> 33 #include <xmloff/prstylei.hxx> 34 #include <xmloff/nmspmap.hxx> 35 #include <xmloff/xmluconv.hxx> 36 37 #include <tools/debug.hxx> 38 39 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp> 40 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp> 41 #include <com/sun/star/chart/ChartAxisPosition.hpp> 42 #include <com/sun/star/chart/ChartAxisType.hpp> 43 #include <com/sun/star/chart/TimeIncrement.hpp> 44 #include <com/sun/star/chart/TimeInterval.hpp> 45 #include <com/sun/star/chart/TimeUnit.hpp> 46 #include <com/sun/star/chart/XAxis.hpp> 47 #include <com/sun/star/chart/XAxisSupplier.hpp> 48 #include <com/sun/star/chart2/AxisType.hpp> 49 #include <com/sun/star/chart2/XChartDocument.hpp> 50 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> 51 52 #include <com/sun/star/drawing/LineStyle.hpp> 53 54 using namespace ::xmloff::token; 55 using namespace com::sun::star; 56 57 using rtl::OUString; 58 using com::sun::star::uno::Reference; 59 60 //---------------------------------------- 61 //---------------------------------------- 62 63 static SvXMLEnumMapEntry aXMLAxisDimensionMap[] = 64 { 65 { XML_X, SCH_XML_AXIS_X }, 66 { XML_Y, SCH_XML_AXIS_Y }, 67 { XML_Z, SCH_XML_AXIS_Z }, 68 { XML_TOKEN_INVALID, 0 } 69 }; 70 71 static SvXMLEnumMapEntry aXMLAxisTypeMap[] = 72 { 73 { XML_AUTO, ::com::sun::star::chart::ChartAxisType::AUTOMATIC }, 74 { XML_TEXT, ::com::sun::star::chart::ChartAxisType::CATEGORY }, 75 { XML_DATE, ::com::sun::star::chart::ChartAxisType::DATE }, 76 { XML_TOKEN_INVALID, 0 } 77 }; 78 79 //---------------------------------------- 80 //---------------------------------------- 81 82 class SchXMLCategoriesContext : public SvXMLImportContext 83 { 84 private: 85 SchXMLImportHelper& m_rImportHelper; 86 OUString& mrAddress; 87 88 public: 89 SchXMLCategoriesContext( SchXMLImportHelper& rImpHelper, 90 SvXMLImport& rImport, 91 sal_uInt16 nPrefix, 92 const OUString& rLocalName, 93 OUString& rAddress ); 94 virtual ~SchXMLCategoriesContext(); 95 virtual void StartElement( const Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList ); 96 }; 97 98 //---------------------------------------- 99 //---------------------------------------- 100 101 102 class DateScaleContext : public SvXMLImportContext 103 { 104 public: 105 DateScaleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport, 106 sal_uInt16 nPrefix, const OUString& rLocalName, 107 const Reference< beans::XPropertySet > xAxisProps ); 108 109 virtual ~DateScaleContext(); 110 virtual void StartElement( const Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList ); 111 112 private: 113 SchXMLImportHelper& m_rImportHelper; 114 Reference< beans::XPropertySet > m_xAxisProps; 115 }; 116 117 118 //---------------------------------------- 119 //---------------------------------------- 120 121 SchXMLAxisContext::SchXMLAxisContext( SchXMLImportHelper& rImpHelper, 122 SvXMLImport& rImport, const OUString& rLocalName, 123 Reference< chart::XDiagram > xDiagram, 124 std::vector< SchXMLAxis >& rAxes, 125 OUString & rCategoriesAddress, 126 bool bAddMissingXAxisForNetCharts, 127 bool bAdaptWrongPercentScaleValues, 128 bool bAdaptXAxisOrientationForOld2DBarCharts, 129 bool& rbAxisPositionAttributeImported ) : 130 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ), 131 m_rImportHelper( rImpHelper ), 132 m_xDiagram( xDiagram ), 133 m_rAxes( rAxes ), 134 m_rCategoriesAddress( rCategoriesAddress ), 135 m_nAxisType(chart::ChartAxisType::AUTOMATIC), 136 m_bAxisTypeImported(false), 137 m_bDateScaleImported(false), 138 m_bAddMissingXAxisForNetCharts( bAddMissingXAxisForNetCharts ), 139 m_bAdaptWrongPercentScaleValues( bAdaptWrongPercentScaleValues ), 140 m_bAdaptXAxisOrientationForOld2DBarCharts( bAdaptXAxisOrientationForOld2DBarCharts ), 141 m_rbAxisPositionAttributeImported( rbAxisPositionAttributeImported ) 142 { 143 } 144 145 SchXMLAxisContext::~SchXMLAxisContext() 146 {} 147 148 Reference< chart::XAxis > lcl_getChartAxis( SchXMLAxis aCurrentAxis, const Reference< chart::XDiagram > xDiagram ) 149 { 150 Reference< chart::XAxis > xAxis; 151 Reference< chart::XAxisSupplier > xAxisSuppl( xDiagram, uno::UNO_QUERY ); 152 if( !xAxisSuppl.is() ) 153 return xAxis; 154 if( aCurrentAxis.nAxisIndex == 0 ) 155 xAxis = xAxisSuppl->getAxis(aCurrentAxis.eDimension); 156 else 157 xAxis = xAxisSuppl->getSecondaryAxis(aCurrentAxis.eDimension); 158 return xAxis; 159 } 160 161 /* returns a shape for the current axis's title. The property 162 "Has...AxisTitle" is set to "True" to get the shape 163 */ 164 Reference< drawing::XShape > SchXMLAxisContext::getTitleShape() 165 { 166 Reference< drawing::XShape > xResult; 167 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY ); 168 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) ); 169 if( !xDiaProp.is() || !xAxis.is() ) 170 return xResult; 171 172 rtl::OUString aPropName; 173 switch( m_aCurrentAxis.eDimension ) 174 { 175 case SCH_XML_AXIS_X: 176 if( m_aCurrentAxis.nAxisIndex == 0 ) 177 aPropName = OUString::createFromAscii( "HasXAxisTitle" ); 178 else 179 aPropName = OUString::createFromAscii( "HasSecondaryXAxisTitle" ); 180 break; 181 case SCH_XML_AXIS_Y: 182 if( m_aCurrentAxis.nAxisIndex == 0 ) 183 aPropName = OUString::createFromAscii( "HasYAxisTitle" ); 184 else 185 aPropName = OUString::createFromAscii( "HasSecondaryYAxisTitle" ); 186 break; 187 case SCH_XML_AXIS_Z: 188 aPropName = OUString::createFromAscii( "HasZAxisTitle" ); 189 break; 190 case SCH_XML_AXIS_UNDEF: 191 DBG_ERROR( "Invalid axis" ); 192 break; 193 } 194 xDiaProp->setPropertyValue( aPropName, uno::makeAny(sal_True) ); 195 xResult = Reference< drawing::XShape >( xAxis->getAxisTitle(), uno::UNO_QUERY ); 196 return xResult; 197 } 198 199 void SchXMLAxisContext::CreateGrid( OUString sAutoStyleName, bool bIsMajor ) 200 { 201 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY ); 202 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) ); 203 if( !xDiaProp.is() || !xAxis.is() ) 204 return; 205 206 rtl::OUString aPropName; 207 switch( m_aCurrentAxis.eDimension ) 208 { 209 case SCH_XML_AXIS_X: 210 if( bIsMajor ) 211 aPropName = OUString::createFromAscii("HasXAxisGrid"); 212 else 213 aPropName = OUString::createFromAscii("HasXAxisHelpGrid"); 214 break; 215 case SCH_XML_AXIS_Y: 216 if( bIsMajor ) 217 aPropName = OUString::createFromAscii("HasYAxisGrid"); 218 else 219 aPropName = OUString::createFromAscii("HasYAxisHelpGrid"); 220 break; 221 case SCH_XML_AXIS_Z: 222 if( bIsMajor ) 223 aPropName = OUString::createFromAscii("HasZAxisGrid"); 224 else 225 aPropName = OUString::createFromAscii("HasZAxisHelpGrid"); 226 break; 227 case SCH_XML_AXIS_UNDEF: 228 DBG_ERROR( "Invalid axis" ); 229 break; 230 } 231 xDiaProp->setPropertyValue( aPropName, uno::makeAny(sal_True) ); 232 233 Reference< beans::XPropertySet > xGridProp; 234 if( bIsMajor ) 235 xGridProp = xAxis->getMajorGrid(); 236 else 237 xGridProp = xAxis->getMinorGrid(); 238 239 // set properties 240 if( xGridProp.is()) 241 { 242 // the line color is black as default, in the model it is a light gray 243 xGridProp->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "LineColor" )), 244 uno::makeAny( COL_BLACK )); 245 if( sAutoStyleName.getLength()) 246 { 247 const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext(); 248 if( pStylesCtxt ) 249 { 250 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext( 251 m_rImportHelper.GetChartFamilyID(), sAutoStyleName ); 252 253 if( pStyle && pStyle->ISA( XMLPropStyleContext )) 254 (( XMLPropStyleContext* )pStyle )->FillPropertySet( xGridProp ); 255 } 256 } 257 } 258 } 259 260 namespace 261 { 262 enum AxisAttributeTokens 263 { 264 XML_TOK_AXIS_DIMENSION, 265 XML_TOK_AXIS_NAME, 266 XML_TOK_AXIS_STYLE_NAME, 267 XML_TOK_AXIS_TYPE, 268 XML_TOK_AXIS_TYPE_EXT 269 }; 270 271 SvXMLTokenMapEntry aAxisAttributeTokenMap[] = 272 { 273 { XML_NAMESPACE_CHART, XML_DIMENSION, XML_TOK_AXIS_DIMENSION }, 274 { XML_NAMESPACE_CHART, XML_NAME, XML_TOK_AXIS_NAME }, 275 { XML_NAMESPACE_CHART, XML_STYLE_NAME, XML_TOK_AXIS_STYLE_NAME }, 276 { XML_NAMESPACE_CHART, XML_AXIS_TYPE, XML_TOK_AXIS_TYPE }, 277 { XML_NAMESPACE_CHART_EXT, XML_AXIS_TYPE, XML_TOK_AXIS_TYPE_EXT }, 278 XML_TOKEN_MAP_END 279 }; 280 281 class AxisAttributeTokenMap : public SvXMLTokenMap 282 { 283 public: 284 AxisAttributeTokenMap(): SvXMLTokenMap( aAxisAttributeTokenMap ) {} 285 virtual ~AxisAttributeTokenMap() {} 286 }; 287 288 //a AxisAttributeTokenMap Singleton 289 struct theAxisAttributeTokenMap : public rtl::Static< AxisAttributeTokenMap, theAxisAttributeTokenMap > {}; 290 } 291 292 void SchXMLAxisContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList ) 293 { 294 // parse attributes 295 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0; 296 SchXMLImport& rImport = ( SchXMLImport& )GetImport(); 297 const SvXMLTokenMap& rAttrTokenMap = theAxisAttributeTokenMap::get(); 298 299 for( sal_Int16 i = 0; i < nAttrCount; i++ ) 300 { 301 OUString sAttrName = xAttrList->getNameByIndex( i ); 302 OUString aLocalName; 303 OUString aValue = xAttrList->getValueByIndex( i ); 304 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 305 306 switch( rAttrTokenMap.Get( nPrefix, aLocalName )) 307 { 308 case XML_TOK_AXIS_DIMENSION: 309 { 310 sal_uInt16 nEnumVal; 311 if( rImport.GetMM100UnitConverter().convertEnum( nEnumVal, aValue, aXMLAxisDimensionMap )) 312 m_aCurrentAxis.eDimension = ( SchXMLAxisDimension )nEnumVal; 313 } 314 break; 315 case XML_TOK_AXIS_NAME: 316 m_aCurrentAxis.aName = aValue; 317 break; 318 case XML_TOK_AXIS_TYPE: 319 case XML_TOK_AXIS_TYPE_EXT: 320 sal_uInt16 nEnumVal; 321 if( rImport.GetMM100UnitConverter().convertEnum( nEnumVal, aValue, aXMLAxisTypeMap )) 322 { 323 m_nAxisType = nEnumVal; 324 m_bAxisTypeImported = true; 325 } 326 break; 327 case XML_TOK_AXIS_STYLE_NAME: 328 m_aAutoStyleName = aValue; 329 break; 330 } 331 } 332 333 // check for number of axes with same dimension 334 m_aCurrentAxis.nAxisIndex = 0; 335 sal_Int32 nNumOfAxes = m_rAxes.size(); 336 for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ ) 337 { 338 if( m_rAxes[ nCurrent ].eDimension == m_aCurrentAxis.eDimension ) 339 m_aCurrentAxis.nAxisIndex++; 340 } 341 CreateAxis(); 342 } 343 namespace 344 { 345 346 Reference< chart2::XAxis > lcl_getAxis( const Reference< frame::XModel >& xChartModel, 347 sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) 348 { 349 Reference< chart2::XAxis > xAxis; 350 351 try 352 { 353 Reference< chart2::XChartDocument > xChart2Document( xChartModel, uno::UNO_QUERY ); 354 if( xChart2Document.is() ) 355 { 356 Reference< chart2::XDiagram > xDiagram( xChart2Document->getFirstDiagram()); 357 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); 358 uno::Sequence< Reference< chart2::XCoordinateSystem > > 359 aCooSysSeq( xCooSysCnt->getCoordinateSystems()); 360 sal_Int32 nCooSysIndex = 0; 361 if( nCooSysIndex < aCooSysSeq.getLength() ) 362 { 363 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] ); 364 if( xCooSys.is() && nDimensionIndex < xCooSys->getDimension() ) 365 { 366 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex); 367 if( nAxisIndex <= nMaxAxisIndex ) 368 xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ); 369 } 370 } 371 } 372 } 373 catch( uno::Exception & ) 374 { 375 DBG_ERROR( "Couldn't get axis" ); 376 } 377 378 return xAxis; 379 } 380 381 bool lcl_divideBy100( uno::Any& rDoubleAny ) 382 { 383 bool bChanged = false; 384 double fValue=0.0; 385 if( (rDoubleAny>>=fValue) && (fValue!=0.0) ) 386 { 387 fValue/=100.0; 388 rDoubleAny = uno::makeAny(fValue); 389 bChanged = true; 390 } 391 return bChanged; 392 } 393 394 bool lcl_AdaptWrongPercentScaleValues(chart2::ScaleData& rScaleData) 395 { 396 bool bChanged = lcl_divideBy100( rScaleData.Minimum ); 397 bChanged = lcl_divideBy100( rScaleData.Maximum ) || bChanged; 398 bChanged = lcl_divideBy100( rScaleData.Origin ) || bChanged; 399 bChanged = lcl_divideBy100( rScaleData.IncrementData.Distance ) || bChanged; 400 return bChanged; 401 } 402 403 }//end anonymous namespace 404 405 void SchXMLAxisContext::CreateAxis() 406 { 407 m_rAxes.push_back( m_aCurrentAxis ); 408 409 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY ); 410 if( !xDiaProp.is() ) 411 return; 412 rtl::OUString aPropName; 413 switch( m_aCurrentAxis.eDimension ) 414 { 415 case SCH_XML_AXIS_X: 416 if( m_aCurrentAxis.nAxisIndex == 0 ) 417 aPropName = OUString::createFromAscii("HasXAxis"); 418 else 419 aPropName = OUString::createFromAscii("HasSecondaryXAxis"); 420 break; 421 case SCH_XML_AXIS_Y: 422 if( m_aCurrentAxis.nAxisIndex == 0 ) 423 aPropName = OUString::createFromAscii("HasYAxis"); 424 else 425 aPropName = OUString::createFromAscii("HasSecondaryYAxis"); 426 break; 427 case SCH_XML_AXIS_Z: 428 if( m_aCurrentAxis.nAxisIndex == 0 ) 429 aPropName = OUString::createFromAscii("HasXAxis"); 430 else 431 aPropName = OUString::createFromAscii("HasSecondaryXAxis"); 432 break; 433 case SCH_XML_AXIS_UNDEF: 434 DBG_ERROR( "Invalid axis" ); 435 break; 436 } 437 try 438 { 439 xDiaProp->setPropertyValue( aPropName, uno::makeAny(sal_True) ); 440 } 441 catch( beans::UnknownPropertyException & ) 442 { 443 DBG_ERROR( "Couldn't turn on axis" ); 444 } 445 if( m_aCurrentAxis.eDimension==SCH_XML_AXIS_Z ) 446 { 447 bool bSettingZAxisSuccedded = false; 448 try 449 { 450 xDiaProp->getPropertyValue( aPropName ) >>= bSettingZAxisSuccedded; 451 } 452 catch( beans::UnknownPropertyException & ) 453 { 454 DBG_ERROR( "Couldn't turn on z axis" ); 455 } 456 if( !bSettingZAxisSuccedded ) 457 return; 458 } 459 460 461 m_xAxisProps = Reference<beans::XPropertySet>( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ), uno::UNO_QUERY ); 462 463 if( m_bAddMissingXAxisForNetCharts && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y && m_aCurrentAxis.nAxisIndex==0 ) 464 { 465 try 466 { 467 xDiaProp->setPropertyValue( OUString::createFromAscii( "HasXAxis" ), uno::makeAny(sal_True) ); 468 } 469 catch( beans::UnknownPropertyException & ) 470 { 471 DBG_ERROR( "Couldn't turn on x axis" ); 472 } 473 } 474 475 // set properties 476 if( m_xAxisProps.is()) 477 { 478 uno::Any aTrueBool( uno::makeAny( sal_True )); 479 uno::Any aFalseBool( uno::makeAny( sal_False )); 480 481 // #i109879# the line color is black as default, in the model it is a light gray 482 m_xAxisProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "LineColor" )), 483 uno::makeAny( COL_BLACK )); 484 485 m_xAxisProps->setPropertyValue( OUString::createFromAscii( "DisplayLabels" ), aFalseBool ); 486 487 // #88077# AutoOrigin 'on' is default 488 m_xAxisProps->setPropertyValue( OUString::createFromAscii( "AutoOrigin" ), aTrueBool ); 489 490 if( m_bAxisTypeImported ) 491 m_xAxisProps->setPropertyValue( OUString::createFromAscii( "AxisType" ), uno::makeAny(m_nAxisType) ); 492 493 if( m_aAutoStyleName.getLength()) 494 { 495 const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext(); 496 if( pStylesCtxt ) 497 { 498 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext( 499 m_rImportHelper.GetChartFamilyID(), m_aAutoStyleName ); 500 501 if( pStyle && pStyle->ISA( XMLPropStyleContext )) 502 { 503 // note: SvXMLStyleContext::FillPropertySet is not const 504 XMLPropStyleContext * pPropStyleContext = const_cast< XMLPropStyleContext * >( dynamic_cast< const XMLPropStyleContext * >( pStyle )); 505 if( pPropStyleContext ) 506 pPropStyleContext->FillPropertySet( m_xAxisProps ); 507 508 if( m_bAdaptWrongPercentScaleValues && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y ) 509 { 510 //set scale data of added x axis back to default 511 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(), 512 m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) ); 513 if( xAxis.is() ) 514 { 515 chart2::ScaleData aScaleData( xAxis->getScaleData()); 516 if( lcl_AdaptWrongPercentScaleValues(aScaleData) ) 517 xAxis->setScaleData( aScaleData ); 518 } 519 } 520 521 if( m_bAddMissingXAxisForNetCharts ) 522 { 523 //copy style from y axis to added x axis: 524 525 Reference< chart::XAxisSupplier > xAxisSuppl( xDiaProp, uno::UNO_QUERY ); 526 if( xAxisSuppl.is() ) 527 { 528 Reference< beans::XPropertySet > xXAxisProp( xAxisSuppl->getAxis(0), uno::UNO_QUERY ); 529 (( XMLPropStyleContext* )pStyle )->FillPropertySet( xXAxisProp ); 530 } 531 532 //set scale data of added x axis back to default 533 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(), 534 0 /*nDimensionIndex*/, 0 /*nAxisIndex*/ ) ); 535 if( xAxis.is() ) 536 { 537 chart2::ScaleData aScaleData; 538 aScaleData.AxisType = chart2::AxisType::CATEGORY; 539 aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; 540 xAxis->setScaleData( aScaleData ); 541 } 542 543 //set line style of added x axis to invisible 544 Reference< beans::XPropertySet > xNewAxisProp( xAxis, uno::UNO_QUERY ); 545 if( xNewAxisProp.is() ) 546 { 547 xNewAxisProp->setPropertyValue( OUString::createFromAscii("LineStyle") 548 , uno::makeAny(drawing::LineStyle_NONE)); 549 } 550 } 551 552 if( m_bAdaptXAxisOrientationForOld2DBarCharts && m_aCurrentAxis.eDimension == SCH_XML_AXIS_X ) 553 { 554 bool bIs3DChart = false; 555 if( xDiaProp.is() && ( xDiaProp->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Dim3D"))) >>= bIs3DChart ) 556 && !bIs3DChart ) 557 { 558 Reference< chart2::XChartDocument > xChart2Document( GetImport().GetModel(), uno::UNO_QUERY ); 559 if( xChart2Document.is() ) 560 { 561 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChart2Document->getFirstDiagram(), uno::UNO_QUERY ); 562 if( xCooSysCnt.is() ) 563 { 564 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); 565 if( aCooSysSeq.getLength() ) 566 { 567 bool bSwapXandYAxis = false; 568 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] ); 569 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY ); 570 if( xCooSysProp.is() && ( xCooSysProp->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("SwapXAndYAxis"))) >>= bSwapXandYAxis ) 571 && bSwapXandYAxis ) 572 { 573 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( 0, m_aCurrentAxis.nAxisIndex ); 574 if( xAxis.is() ) 575 { 576 chart2::ScaleData aScaleData = xAxis->getScaleData(); 577 aScaleData.Orientation = chart2::AxisOrientation_REVERSE; 578 xAxis->setScaleData( aScaleData ); 579 } 580 } 581 } 582 } 583 } 584 } 585 } 586 587 m_rbAxisPositionAttributeImported = m_rbAxisPositionAttributeImported || SchXMLTools::getPropertyFromContext( 588 OUString(RTL_CONSTASCII_USTRINGPARAM("CrossoverPosition")), pPropStyleContext, pStylesCtxt ).hasValue(); 589 } 590 } 591 } 592 } 593 } 594 595 void SchXMLAxisContext::SetAxisTitle() 596 { 597 if( !m_aCurrentAxis.aTitle.getLength() ) 598 return; 599 600 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) ); 601 if( !xAxis.is() ) 602 return; 603 604 Reference< beans::XPropertySet > xTitleProp( xAxis->getAxisTitle() ); 605 if( xTitleProp.is() ) 606 { 607 try 608 { 609 xTitleProp->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), uno::makeAny(m_aCurrentAxis.aTitle) ); 610 } 611 catch( beans::UnknownPropertyException & ) 612 { 613 DBG_ERROR( "Property String for Title not available" ); 614 } 615 } 616 } 617 618 //----------------------------------------------------------------------- 619 namespace 620 { 621 enum AxisChildTokens 622 { 623 XML_TOK_AXIS_TITLE, 624 XML_TOK_AXIS_CATEGORIES, 625 XML_TOK_AXIS_GRID, 626 XML_TOK_AXIS_DATE_SCALE, 627 XML_TOK_AXIS_DATE_SCALE_EXT 628 }; 629 630 SvXMLTokenMapEntry aAxisChildTokenMap[] = 631 { 632 { XML_NAMESPACE_CHART, XML_TITLE, XML_TOK_AXIS_TITLE }, 633 { XML_NAMESPACE_CHART, XML_CATEGORIES, XML_TOK_AXIS_CATEGORIES }, 634 { XML_NAMESPACE_CHART, XML_GRID, XML_TOK_AXIS_GRID }, 635 { XML_NAMESPACE_CHART, XML_DATE_SCALE, XML_TOK_AXIS_DATE_SCALE }, 636 { XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, XML_TOK_AXIS_DATE_SCALE_EXT }, 637 XML_TOKEN_MAP_END 638 }; 639 640 class AxisChildTokenMap : public SvXMLTokenMap 641 { 642 public: 643 AxisChildTokenMap(): SvXMLTokenMap( aAxisChildTokenMap ) {} 644 virtual ~AxisChildTokenMap() {} 645 }; 646 647 //a AxisChildTokenMap Singleton 648 struct theAxisChildTokenMap : public rtl::Static< AxisChildTokenMap, theAxisChildTokenMap > {}; 649 } 650 651 SvXMLImportContext* SchXMLAxisContext::CreateChildContext( 652 sal_uInt16 p_nPrefix, 653 const OUString& rLocalName, 654 const Reference< xml::sax::XAttributeList >& xAttrList ) 655 { 656 SvXMLImportContext* pContext = 0; 657 const SvXMLTokenMap& rTokenMap = theAxisChildTokenMap::get(); 658 659 switch( rTokenMap.Get( p_nPrefix, rLocalName )) 660 { 661 case XML_TOK_AXIS_TITLE: 662 { 663 Reference< drawing::XShape > xTitleShape = getTitleShape(); 664 pContext = new SchXMLTitleContext( m_rImportHelper, GetImport(), rLocalName, 665 m_aCurrentAxis.aTitle, 666 xTitleShape ); 667 } 668 break; 669 670 case XML_TOK_AXIS_CATEGORIES: 671 pContext = new SchXMLCategoriesContext( m_rImportHelper, GetImport(), 672 p_nPrefix, rLocalName, 673 m_rCategoriesAddress ); 674 m_aCurrentAxis.bHasCategories = true; 675 break; 676 677 case XML_TOK_AXIS_DATE_SCALE: 678 case XML_TOK_AXIS_DATE_SCALE_EXT: 679 pContext = new DateScaleContext( m_rImportHelper, GetImport(), 680 p_nPrefix, rLocalName, m_xAxisProps ); 681 m_bDateScaleImported = true; 682 break; 683 684 case XML_TOK_AXIS_GRID: 685 { 686 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0; 687 bool bIsMajor = true; // default value for class is "major" 688 OUString sAutoStyleName; 689 690 for( sal_Int16 i = 0; i < nAttrCount; i++ ) 691 { 692 OUString sAttrName = xAttrList->getNameByIndex( i ); 693 OUString aLocalName; 694 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 695 696 if( nPrefix == XML_NAMESPACE_CHART ) 697 { 698 if( IsXMLToken( aLocalName, XML_CLASS ) ) 699 { 700 if( IsXMLToken( xAttrList->getValueByIndex( i ), XML_MINOR ) ) 701 bIsMajor = false; 702 } 703 else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) ) 704 sAutoStyleName = xAttrList->getValueByIndex( i ); 705 } 706 } 707 708 CreateGrid( sAutoStyleName, bIsMajor ); 709 710 // don't create a context => use default context. grid elements are empty 711 pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName ); 712 } 713 break; 714 715 default: 716 pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName ); 717 break; 718 } 719 720 return pContext; 721 } 722 723 void SchXMLAxisContext::EndElement() 724 { 725 if( !m_bDateScaleImported && m_nAxisType==chart::ChartAxisType::AUTOMATIC ) 726 { 727 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) ); 728 if( xAxis.is() ) 729 { 730 chart2::ScaleData aScaleData( xAxis->getScaleData()); 731 aScaleData.AutoDateAxis = false;//different default for older documents 732 xAxis->setScaleData( aScaleData ); 733 } 734 } 735 736 SetAxisTitle(); 737 } 738 739 // ======================================== 740 741 namespace 742 { 743 744 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem > xCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) 745 { 746 Reference< chart2::XAxis > xAxis; 747 try 748 { 749 xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ); 750 } 751 catch( uno::Exception & ) 752 { 753 } 754 return xAxis; 755 } 756 757 } // anonymous namespace 758 759 void SchXMLAxisContext::CorrectAxisPositions( const Reference< chart2::XChartDocument >& xNewDoc, 760 const OUString& rChartTypeServiceName, 761 const OUString& rODFVersionOfFile, 762 bool bAxisPositionAttributeImported ) 763 { 764 if( ( !rODFVersionOfFile.getLength() || rODFVersionOfFile.equalsAscii("1.0") 765 || rODFVersionOfFile.equalsAscii("1.1") 766 || ( rODFVersionOfFile.equalsAscii("1.2") && !bAxisPositionAttributeImported ) ) ) 767 { 768 try 769 { 770 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDoc->getFirstDiagram(), uno::UNO_QUERY_THROW ); 771 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); 772 if( aCooSysSeq.getLength() ) 773 { 774 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] ); 775 if( xCooSys.is() ) 776 { 777 Reference< chart2::XAxis > xMainXAxis = lcl_getAxis( xCooSys, 0, 0 ); 778 Reference< chart2::XAxis > xMainYAxis = lcl_getAxis( xCooSys, 1, 0 ); 779 //Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 ); 780 Reference< chart2::XAxis > xSecondaryXAxis = lcl_getAxis( xCooSys, 0, 1 ); 781 Reference< chart2::XAxis > xSecondaryYAxis = lcl_getAxis( xCooSys, 1, 1 ); 782 783 Reference< beans::XPropertySet > xMainXAxisProp( xMainXAxis, uno::UNO_QUERY ); 784 Reference< beans::XPropertySet > xMainYAxisProp( xMainYAxis, uno::UNO_QUERY ); 785 Reference< beans::XPropertySet > xSecondaryXAxisProp( xSecondaryXAxis, uno::UNO_QUERY ); 786 Reference< beans::XPropertySet > xSecondaryYAxisProp( xSecondaryYAxis, uno::UNO_QUERY ); 787 788 if( xMainXAxisProp.is() && xMainYAxisProp.is() ) 789 { 790 chart2::ScaleData aMainXScale = xMainXAxis->getScaleData(); 791 if( 0 == rChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ScatterChartType" ) ) ) 792 { 793 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 794 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_VALUE) ); 795 double fCrossoverValue = 0.0; 796 aMainXScale.Origin >>= fCrossoverValue; 797 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverValue") 798 , uno::makeAny( fCrossoverValue ) ); 799 800 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE ) 801 { 802 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition") 803 , uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END) ); 804 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition") 805 , uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) ); 806 if( xSecondaryYAxisProp.is() ) 807 xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 808 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) ); 809 } 810 else 811 { 812 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition") 813 , uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START) ); 814 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition") 815 , uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) ); 816 if( xSecondaryYAxisProp.is() ) 817 xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 818 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) ); 819 } 820 } 821 else 822 { 823 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE ) 824 { 825 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 826 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) ); 827 if( xSecondaryYAxisProp.is() ) 828 xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 829 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) ); 830 } 831 else 832 { 833 xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 834 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) ); 835 if( xSecondaryYAxisProp.is() ) 836 xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 837 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) ); 838 } 839 } 840 841 chart2::ScaleData aMainYScale = xMainYAxis->getScaleData(); 842 xMainXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 843 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_VALUE) ); 844 double fCrossoverValue = 0.0; 845 aMainYScale.Origin >>= fCrossoverValue; 846 xMainXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverValue") 847 , uno::makeAny( fCrossoverValue ) ); 848 849 if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE ) 850 { 851 xMainXAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition") 852 , uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END) ); 853 xMainXAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition") 854 , uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) ); 855 if( xSecondaryXAxisProp.is() ) 856 xSecondaryXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 857 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) ); 858 } 859 else 860 { 861 xMainXAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition") 862 , uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START) ); 863 xMainXAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition") 864 , uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) ); 865 if( xSecondaryXAxisProp.is() ) 866 xSecondaryXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition") 867 , uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) ); 868 } 869 } 870 } 871 } 872 } 873 catch( uno::Exception & ) 874 { 875 } 876 } 877 } 878 879 // ======================================== 880 881 SchXMLCategoriesContext::SchXMLCategoriesContext( 882 SchXMLImportHelper& rImpHelper, 883 SvXMLImport& rImport, 884 sal_uInt16 nPrefix, 885 const OUString& rLocalName, 886 OUString& rAddress ) : 887 SvXMLImportContext( rImport, nPrefix, rLocalName ), 888 m_rImportHelper( rImpHelper ), 889 mrAddress( rAddress ) 890 { 891 } 892 893 SchXMLCategoriesContext::~SchXMLCategoriesContext() 894 { 895 } 896 897 void SchXMLCategoriesContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList ) 898 { 899 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0; 900 901 for( sal_Int16 i = 0; i < nAttrCount; i++ ) 902 { 903 OUString sAttrName = xAttrList->getNameByIndex( i ); 904 OUString aLocalName; 905 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 906 907 if( nPrefix == XML_NAMESPACE_TABLE && 908 IsXMLToken( aLocalName, XML_CELL_RANGE_ADDRESS ) ) 909 { 910 Reference< chart2::XChartDocument > xNewDoc( GetImport().GetModel(), uno::UNO_QUERY ); 911 mrAddress = xAttrList->getValueByIndex( i ); 912 } 913 } 914 } 915 916 // ======================================== 917 918 DateScaleContext::DateScaleContext( 919 SchXMLImportHelper& rImpHelper, 920 SvXMLImport& rImport, 921 sal_uInt16 nPrefix, 922 const OUString& rLocalName, 923 const Reference< beans::XPropertySet > xAxisProps ) : 924 SvXMLImportContext( rImport, nPrefix, rLocalName ), 925 m_rImportHelper( rImpHelper ), 926 m_xAxisProps( xAxisProps ) 927 { 928 } 929 930 DateScaleContext::~DateScaleContext() 931 { 932 } 933 934 namespace 935 { 936 enum DateScaleAttributeTokens 937 { 938 XML_TOK_DATESCALE_BASE_TIME_UNIT, 939 XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE, 940 XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT, 941 XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE, 942 XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT 943 }; 944 945 SvXMLTokenMapEntry aDateScaleAttributeTokenMap[] = 946 { 947 { XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, XML_TOK_DATESCALE_BASE_TIME_UNIT }, 948 { XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE }, 949 { XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT }, 950 { XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE }, 951 { XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT }, 952 XML_TOKEN_MAP_END 953 }; 954 955 class DateScaleAttributeTokenMap : public SvXMLTokenMap 956 { 957 public: 958 DateScaleAttributeTokenMap(): SvXMLTokenMap( aDateScaleAttributeTokenMap ) {} 959 virtual ~DateScaleAttributeTokenMap() {} 960 }; 961 962 struct theDateScaleAttributeTokenMap : public rtl::Static< DateScaleAttributeTokenMap, theDateScaleAttributeTokenMap > {}; 963 964 sal_Int32 lcl_getTimeUnit( const OUString& rValue ) 965 { 966 sal_Int32 nTimeUnit = ::com::sun::star::chart::TimeUnit::DAY; 967 if( IsXMLToken( rValue, XML_DAYS ) ) 968 nTimeUnit = ::com::sun::star::chart::TimeUnit::DAY; 969 else if( IsXMLToken( rValue, XML_MONTHS ) ) 970 nTimeUnit = ::com::sun::star::chart::TimeUnit::MONTH; 971 else if( IsXMLToken( rValue, XML_YEARS ) ) 972 nTimeUnit = ::com::sun::star::chart::TimeUnit::YEAR; 973 return nTimeUnit; 974 } 975 976 } 977 978 void DateScaleContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList ) 979 { 980 if( !m_xAxisProps.is() ) 981 return; 982 983 // parse attributes 984 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0; 985 const SvXMLTokenMap& rAttrTokenMap = theDateScaleAttributeTokenMap::get(); 986 987 bool bSetNewIncrement=false; 988 chart::TimeIncrement aIncrement; 989 m_xAxisProps->getPropertyValue( OUString::createFromAscii( "TimeIncrement" )) >>= aIncrement; 990 991 for( sal_Int16 i = 0; i < nAttrCount; i++ ) 992 { 993 OUString sAttrName = xAttrList->getNameByIndex( i ); 994 OUString aLocalName; 995 OUString aValue = xAttrList->getValueByIndex( i ); 996 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 997 998 switch( rAttrTokenMap.Get( nPrefix, aLocalName )) 999 { 1000 case XML_TOK_DATESCALE_BASE_TIME_UNIT: 1001 { 1002 aIncrement.TimeResolution = uno::makeAny( lcl_getTimeUnit(aValue) ); 1003 bSetNewIncrement = true; 1004 } 1005 break; 1006 case XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE: 1007 { 1008 chart::TimeInterval aInterval(1,0); 1009 aIncrement.MajorTimeInterval >>= aInterval; 1010 SvXMLUnitConverter::convertNumber( aInterval.Number, aValue ); 1011 aIncrement.MajorTimeInterval = uno::makeAny(aInterval); 1012 bSetNewIncrement = true; 1013 } 1014 break; 1015 case XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT: 1016 { 1017 chart::TimeInterval aInterval(1,0); 1018 aIncrement.MajorTimeInterval >>= aInterval; 1019 aInterval.TimeUnit = lcl_getTimeUnit(aValue); 1020 aIncrement.MajorTimeInterval = uno::makeAny(aInterval); 1021 bSetNewIncrement = true; 1022 } 1023 break; 1024 case XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE: 1025 { 1026 chart::TimeInterval aInterval(1,0); 1027 aIncrement.MinorTimeInterval >>= aInterval; 1028 SvXMLUnitConverter::convertNumber( aInterval.Number, aValue ); 1029 aIncrement.MinorTimeInterval = uno::makeAny(aInterval); 1030 bSetNewIncrement = true; 1031 } 1032 break; 1033 case XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT: 1034 { 1035 chart::TimeInterval aInterval(1,0); 1036 aIncrement.MinorTimeInterval >>= aInterval; 1037 aInterval.TimeUnit = lcl_getTimeUnit(aValue); 1038 aIncrement.MinorTimeInterval = uno::makeAny(aInterval); 1039 bSetNewIncrement = true; 1040 } 1041 break; 1042 } 1043 } 1044 1045 if( bSetNewIncrement ) 1046 m_xAxisProps->setPropertyValue( OUString::createFromAscii( "TimeIncrement" ), uno::makeAny( aIncrement ) ); 1047 } 1048 1049 // ======================================== 1050