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 "WrappedScaleProperty.hxx" 28 #include "macros.hxx" 29 #include "CommonConverters.hxx" 30 #include "AxisHelper.hxx" 31 #include <com/sun/star/chart2/XAxis.hpp> 32 #include <com/sun/star/chart/ChartAxisType.hpp> 33 #include <chartview/ExplicitScaleValues.hxx> 34 35 using namespace ::com::sun::star; 36 using ::com::sun::star::uno::Any; 37 using namespace ::com::sun::star::chart2; 38 using ::com::sun::star::uno::Reference; 39 using ::com::sun::star::uno::Sequence; 40 using ::rtl::OUString; 41 using ::com::sun::star::chart::TimeIncrement; 42 43 //............................................................................. 44 namespace chart 45 { 46 namespace wrapper 47 { 48 49 WrappedScaleProperty::WrappedScaleProperty( tScaleProperty eScaleProperty 50 , ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ) 51 : WrappedProperty(OUString(),OUString()) 52 , m_spChart2ModelContact( spChart2ModelContact ) 53 , m_eScaleProperty( eScaleProperty ) 54 { 55 switch( m_eScaleProperty ) 56 { 57 case SCALE_PROP_MAX: 58 m_aOuterName = C2U("Max"); 59 break; 60 case SCALE_PROP_MIN: 61 m_aOuterName = C2U("Min"); 62 break; 63 case SCALE_PROP_ORIGIN: 64 m_aOuterName = C2U("Origin"); 65 break; 66 case SCALE_PROP_STEPMAIN: 67 m_aOuterName = C2U("StepMain"); 68 break; 69 case SCALE_PROP_STEPHELP: 70 m_aOuterName = C2U("StepHelp"); 71 break; 72 case SCALE_PROP_STEPHELP_COUNT: 73 m_aOuterName = C2U("StepHelpCount"); 74 break; 75 case SCALE_PROP_AUTO_MAX: 76 m_aOuterName = C2U("AutoMax"); 77 break; 78 case SCALE_PROP_AUTO_MIN: 79 m_aOuterName = C2U("AutoMin"); 80 break; 81 case SCALE_PROP_AUTO_ORIGIN: 82 m_aOuterName = C2U("AutoOrigin"); 83 break; 84 case SCALE_PROP_AUTO_STEPMAIN: 85 m_aOuterName = C2U("AutoStepMain"); 86 break; 87 case SCALE_PROP_AUTO_STEPHELP: 88 m_aOuterName = C2U("AutoStepHelp"); 89 break; 90 case SCALE_PROP_AXIS_TYPE: 91 m_aOuterName = C2U("AxisType"); 92 break; 93 case SCALE_PROP_DATE_INCREMENT: 94 m_aOuterName = C2U("TimeIncrement"); 95 break; 96 case SCALE_PROP_EXPLICIT_DATE_INCREMENT: 97 m_aOuterName = C2U("ExplicitTimeIncrement"); 98 break; 99 case SCALE_PROP_LOGARITHMIC: 100 m_aOuterName = C2U("Logarithmic"); 101 break; 102 case SCALE_PROP_REVERSEDIRECTION: 103 m_aOuterName = C2U("ReverseDirection"); 104 break; 105 default: 106 OSL_ENSURE(false,"unknown scale property"); 107 break; 108 } 109 } 110 111 WrappedScaleProperty::~WrappedScaleProperty() 112 { 113 } 114 115 void WrappedScaleProperty::addWrappedProperties( std::vector< WrappedProperty* >& rList 116 , ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ) 117 { 118 rList.push_back( new WrappedScaleProperty( SCALE_PROP_MAX, spChart2ModelContact ) ); 119 rList.push_back( new WrappedScaleProperty( SCALE_PROP_MIN, spChart2ModelContact ) ); 120 rList.push_back( new WrappedScaleProperty( SCALE_PROP_ORIGIN, spChart2ModelContact ) ); 121 rList.push_back( new WrappedScaleProperty( SCALE_PROP_STEPMAIN, spChart2ModelContact ) ); 122 rList.push_back( new WrappedScaleProperty( SCALE_PROP_STEPHELP, spChart2ModelContact ) ); 123 rList.push_back( new WrappedScaleProperty( SCALE_PROP_STEPHELP_COUNT, spChart2ModelContact ) ); 124 rList.push_back( new WrappedScaleProperty( SCALE_PROP_AUTO_MAX, spChart2ModelContact ) ); 125 rList.push_back( new WrappedScaleProperty( SCALE_PROP_AUTO_MIN, spChart2ModelContact ) ); 126 rList.push_back( new WrappedScaleProperty( SCALE_PROP_AUTO_ORIGIN, spChart2ModelContact ) ); 127 rList.push_back( new WrappedScaleProperty( SCALE_PROP_AUTO_STEPMAIN, spChart2ModelContact ) ); 128 rList.push_back( new WrappedScaleProperty( SCALE_PROP_AUTO_STEPHELP, spChart2ModelContact ) ); 129 rList.push_back( new WrappedScaleProperty( SCALE_PROP_AXIS_TYPE, spChart2ModelContact ) ); 130 rList.push_back( new WrappedScaleProperty( SCALE_PROP_DATE_INCREMENT, spChart2ModelContact ) ); 131 rList.push_back( new WrappedScaleProperty( SCALE_PROP_EXPLICIT_DATE_INCREMENT, spChart2ModelContact ) ); 132 rList.push_back( new WrappedScaleProperty( SCALE_PROP_LOGARITHMIC, spChart2ModelContact ) ); 133 rList.push_back( new WrappedScaleProperty( SCALE_PROP_REVERSEDIRECTION, spChart2ModelContact ) ); 134 } 135 136 void WrappedScaleProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const 137 throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) 138 { 139 setPropertyValue( m_eScaleProperty, rOuterValue, xInnerPropertySet ); 140 } 141 142 Any WrappedScaleProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const 143 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) 144 { 145 return getPropertyValue( m_eScaleProperty, xInnerPropertySet ); 146 } 147 148 void WrappedScaleProperty::setPropertyValue( tScaleProperty eScaleProperty, const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const 149 throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) 150 { 151 m_aOuterValue = rOuterValue; 152 153 Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY ); 154 OSL_ENSURE(xAxis.is(),"need an XAxis"); 155 if(!xAxis.is()) 156 return; 157 158 bool bSetScaleData = false; 159 160 chart2::ScaleData aScaleData( xAxis->getScaleData() ); 161 162 sal_Bool bBool = false; 163 switch( eScaleProperty ) 164 { 165 case SCALE_PROP_MAX: 166 { 167 aScaleData.Maximum = rOuterValue; 168 bSetScaleData = true; 169 break; 170 } 171 case SCALE_PROP_MIN: 172 { 173 aScaleData.Minimum = rOuterValue; 174 bSetScaleData = true; 175 break; 176 } 177 case SCALE_PROP_STEPMAIN: 178 { 179 aScaleData.IncrementData.Distance = rOuterValue; 180 bSetScaleData = true; 181 break; 182 } 183 case SCALE_PROP_STEPHELP: 184 { 185 Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); 186 if( rSubIncrements.getLength() == 0 ) 187 rSubIncrements.realloc( 1 ); 188 189 double fStepMain = 0, fStepHelp = 0; 190 if( (rOuterValue >>= fStepHelp) ) 191 { 192 if( AxisHelper::isLogarithmic(aScaleData.Scaling) ) 193 { 194 sal_Int32 nIntervalCount = static_cast< sal_Int32 >(fStepHelp); 195 rSubIncrements[ 0 ].IntervalCount <<= nIntervalCount; 196 } 197 else if( (fStepHelp != 0.0) && 198 (aScaleData.IncrementData.Distance >>= fStepMain) ) 199 { 200 // approximate interval count 201 sal_Int32 nIntervalCount = static_cast< sal_Int32 >(fStepMain / fStepHelp); 202 rSubIncrements[ 0 ].IntervalCount <<= nIntervalCount; 203 } 204 } 205 bSetScaleData = true; 206 break; 207 } 208 case SCALE_PROP_STEPHELP_COUNT: 209 { 210 Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); 211 if( rSubIncrements.getLength() == 0 ) 212 rSubIncrements.realloc( 1 ); 213 sal_Int32 nIntervalCount=0; 214 if( rOuterValue>>=nIntervalCount ) 215 rSubIncrements[ 0 ].IntervalCount <<= nIntervalCount; 216 else 217 rSubIncrements[ 0 ].IntervalCount = Any(); 218 bSetScaleData = true; 219 break; 220 } 221 case SCALE_PROP_AUTO_MAX: 222 { 223 if( (rOuterValue >>= bBool) && bBool ) 224 aScaleData.Maximum = Any(); 225 else 226 aScaleData.Maximum = getPropertyValue( SCALE_PROP_MAX, xInnerPropertySet ); 227 bSetScaleData = true; 228 break; 229 } 230 case SCALE_PROP_AUTO_MIN: 231 { 232 if( (rOuterValue >>= bBool) && bBool ) 233 aScaleData.Minimum = Any(); 234 else 235 aScaleData.Minimum = getPropertyValue( SCALE_PROP_MIN, xInnerPropertySet ); 236 bSetScaleData = true; 237 break; 238 } 239 case SCALE_PROP_AUTO_STEPMAIN: 240 { 241 if( (rOuterValue >>= bBool) && bBool ) 242 aScaleData.IncrementData.Distance = Any(); 243 else 244 aScaleData.IncrementData.Distance = getPropertyValue( SCALE_PROP_STEPMAIN, xInnerPropertySet ); 245 bSetScaleData = true; 246 break; 247 } 248 case SCALE_PROP_AUTO_STEPHELP: 249 { 250 Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); 251 if( rSubIncrements.getLength() == 0 ) 252 rSubIncrements.realloc( 1 ); 253 254 if( (rOuterValue >>= bBool) && bBool ) 255 rSubIncrements[ 0 ].IntervalCount = Any(); 256 else 257 rSubIncrements[ 0 ].IntervalCount = getPropertyValue( SCALE_PROP_STEPHELP_COUNT, xInnerPropertySet ); 258 bSetScaleData = true; 259 break; 260 } 261 case SCALE_PROP_ORIGIN: 262 { 263 aScaleData.Origin = rOuterValue; 264 bSetScaleData = true; 265 break; 266 } 267 case SCALE_PROP_AUTO_ORIGIN: 268 { 269 if( (rOuterValue >>= bBool) && bBool ) 270 aScaleData.Origin = Any(); 271 else 272 aScaleData.Origin = getPropertyValue( SCALE_PROP_ORIGIN, xInnerPropertySet ); 273 bSetScaleData = true; 274 break; 275 } 276 case SCALE_PROP_AXIS_TYPE: 277 { 278 sal_Int32 nType = 0; 279 if( (rOuterValue >>= nType) ) 280 { 281 if( ::com::sun::star::chart::ChartAxisType::AUTOMATIC == nType ) 282 { 283 aScaleData.AutoDateAxis = true; 284 if( aScaleData.AxisType == AxisType::DATE ) 285 aScaleData.AxisType = AxisType::CATEGORY; 286 } 287 else if( ::com::sun::star::chart::ChartAxisType::CATEGORY == nType ) 288 { 289 aScaleData.AutoDateAxis = false; 290 if( aScaleData.AxisType == AxisType::DATE ) 291 aScaleData.AxisType = AxisType::CATEGORY; 292 } 293 else if( ::com::sun::star::chart::ChartAxisType::DATE == nType ) 294 { 295 if( aScaleData.AxisType == AxisType::CATEGORY ) 296 aScaleData.AxisType = AxisType::DATE; 297 } 298 bSetScaleData = true; 299 } 300 break; 301 } 302 case SCALE_PROP_DATE_INCREMENT: 303 { 304 TimeIncrement aTimeIncrement; 305 rOuterValue >>= aTimeIncrement; 306 aScaleData.TimeIncrement = aTimeIncrement; 307 bSetScaleData = true; 308 break; 309 } 310 case SCALE_PROP_EXPLICIT_DATE_INCREMENT: 311 //read only property 312 break; 313 case SCALE_PROP_LOGARITHMIC: 314 { 315 if( rOuterValue >>= bBool ) 316 { 317 bool bWasLogarithm = AxisHelper::isLogarithmic( aScaleData.Scaling ); 318 319 // safe comparison between sal_Bool and bool 320 if( (!bBool) != (!bWasLogarithm) ) 321 { 322 if( bBool ) 323 aScaleData.Scaling = AxisHelper::createLogarithmicScaling( 10.0 ); 324 else 325 aScaleData.Scaling = 0; 326 bSetScaleData = true; 327 } 328 } 329 break; 330 } 331 case SCALE_PROP_REVERSEDIRECTION: 332 { 333 if( rOuterValue >>= bBool ) 334 { 335 bool bWasReverse = ( AxisOrientation_REVERSE == aScaleData.Orientation ); 336 if( (!bBool) != (!bWasReverse) ) // safe comparison between sal_Bool and bool 337 { 338 aScaleData.Orientation = bBool ? AxisOrientation_REVERSE : AxisOrientation_MATHEMATICAL; 339 bSetScaleData = true; 340 } 341 } 342 break; 343 } 344 default: 345 { 346 OSL_ENSURE(false,"unknown scale property"); 347 break; 348 } 349 } 350 351 if( bSetScaleData ) 352 xAxis->setScaleData( aScaleData ); 353 } 354 355 Any WrappedScaleProperty::getPropertyValue( tScaleProperty eScaleProperty, const Reference< beans::XPropertySet >& xInnerPropertySet ) const 356 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) 357 { 358 Any aRet( m_aOuterValue ); 359 360 Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY ); 361 OSL_ENSURE(xAxis.is(),"need an XAxis"); 362 if(!xAxis.is()) 363 return aRet; 364 365 chart2::ScaleData aScaleData( xAxis->getScaleData() ); 366 367 ExplicitScaleData aExplicitScale; 368 ExplicitIncrementData aExplicitIncrement; 369 370 switch( eScaleProperty ) 371 { 372 case SCALE_PROP_MAX: 373 { 374 aRet = aScaleData.Maximum; 375 if( !aRet.hasValue() ) 376 { 377 m_spChart2ModelContact->getExplicitValuesForAxis( 378 xAxis, aExplicitScale, aExplicitIncrement ); 379 aRet <<= aExplicitScale.Maximum; 380 } 381 break; 382 } 383 case SCALE_PROP_MIN: 384 { 385 aRet = aScaleData.Minimum; 386 if( !aRet.hasValue() ) 387 { 388 m_spChart2ModelContact->getExplicitValuesForAxis( 389 xAxis, aExplicitScale, aExplicitIncrement ); 390 aRet <<= aExplicitScale.Minimum; 391 } 392 break; 393 } 394 395 case SCALE_PROP_STEPMAIN: 396 { 397 aRet = aScaleData.IncrementData.Distance; 398 if( !aRet.hasValue() ) 399 { 400 m_spChart2ModelContact->getExplicitValuesForAxis( 401 xAxis, aExplicitScale, aExplicitIncrement ); 402 aRet <<= aExplicitIncrement.Distance; 403 } 404 break; 405 } 406 case SCALE_PROP_STEPHELP: 407 { 408 // todo: evaluate PostEquidistant 409 bool bNeedToCalculateExplicitValues = true; 410 411 bool bLogarithmic( AxisHelper::isLogarithmic(aScaleData.Scaling) ); 412 Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); 413 if( bLogarithmic ) 414 { 415 if( rSubIncrements.getLength() > 0 ) 416 { 417 sal_Int32 nIntervalCount = 0; 418 rSubIncrements[ 0 ].IntervalCount >>= nIntervalCount; 419 aRet = uno::makeAny( double(nIntervalCount) ); 420 bNeedToCalculateExplicitValues = false; 421 } 422 } 423 else if( aScaleData.IncrementData.Distance.hasValue() ) 424 { 425 if( rSubIncrements.getLength() > 0 ) 426 { 427 double fStepMain = 0; 428 sal_Int32 nIntervalCount = 0; 429 if( (aScaleData.IncrementData.Distance >>= fStepMain) && 430 (rSubIncrements[ 0 ].IntervalCount >>= nIntervalCount) && 431 nIntervalCount > 0 ) 432 { 433 aRet <<= ( fStepMain / static_cast< double >( nIntervalCount ) ); 434 bNeedToCalculateExplicitValues = false; 435 } 436 } 437 else 438 { 439 aRet = aScaleData.IncrementData.Distance; 440 bNeedToCalculateExplicitValues = false; 441 } 442 } 443 444 if( bNeedToCalculateExplicitValues ) 445 { 446 m_spChart2ModelContact->getExplicitValuesForAxis( 447 xAxis, aExplicitScale, aExplicitIncrement ); 448 449 if( !aExplicitIncrement.SubIncrements.empty() && 450 aExplicitIncrement.SubIncrements[ 0 ].IntervalCount > 0 ) 451 { 452 if( bLogarithmic ) 453 { 454 if( rSubIncrements.getLength() > 0 ) 455 { 456 sal_Int32 nIntervalCount = aExplicitIncrement.SubIncrements[ 0 ].IntervalCount; 457 aRet = uno::makeAny( double(nIntervalCount) ); 458 } 459 } 460 else 461 aRet <<= ( aExplicitIncrement.Distance / 462 static_cast< double >( 463 aExplicitIncrement.SubIncrements[ 0 ].IntervalCount )); 464 } 465 else 466 { 467 if( bLogarithmic ) 468 aRet <<= 5.0; 469 else 470 aRet <<= aExplicitIncrement.Distance; 471 } 472 } 473 break; 474 } 475 case SCALE_PROP_STEPHELP_COUNT: 476 { 477 sal_Int32 nIntervalCount = 0; 478 bool bNeedToCalculateExplicitValues = true; 479 Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); 480 if( rSubIncrements.getLength() > 0 ) 481 { 482 if( (rSubIncrements[ 0 ].IntervalCount >>= nIntervalCount) && (nIntervalCount > 0) ) 483 bNeedToCalculateExplicitValues = false; 484 } 485 if( bNeedToCalculateExplicitValues ) 486 { 487 m_spChart2ModelContact->getExplicitValuesForAxis( xAxis, aExplicitScale, aExplicitIncrement ); 488 if( !aExplicitIncrement.SubIncrements.empty() ) 489 nIntervalCount = aExplicitIncrement.SubIncrements[ 0 ].IntervalCount; 490 } 491 aRet = uno::makeAny( nIntervalCount ); 492 break; 493 } 494 case SCALE_PROP_AUTO_MAX: 495 { 496 aRet <<= (sal_Bool)( !aScaleData.Maximum.hasValue() ); 497 break; 498 } 499 case SCALE_PROP_AUTO_MIN: 500 { 501 aRet <<= (sal_Bool)( !aScaleData.Minimum.hasValue() ); 502 break; 503 } 504 case SCALE_PROP_AUTO_STEPMAIN: 505 { 506 aRet <<= (sal_Bool)( !aScaleData.IncrementData.Distance.hasValue() ); 507 break; 508 } 509 case SCALE_PROP_AUTO_STEPHELP: 510 { 511 Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); 512 if( rSubIncrements.getLength() > 0 ) 513 aRet <<= (sal_Bool)( !rSubIncrements[ 0 ].IntervalCount.hasValue() ); 514 else 515 aRet <<= sal_True; 516 break; 517 } 518 case SCALE_PROP_ORIGIN: 519 { 520 aRet = aScaleData.Origin; 521 if( !aRet.hasValue() ) 522 { 523 m_spChart2ModelContact->getExplicitValuesForAxis( 524 xAxis, aExplicitScale, aExplicitIncrement ); 525 aRet <<= aExplicitScale.Origin; 526 } 527 break; 528 } 529 case SCALE_PROP_AUTO_ORIGIN: 530 { 531 aRet <<= !hasDoubleValue(aScaleData.Origin); 532 break; 533 } 534 case SCALE_PROP_AXIS_TYPE: 535 { 536 sal_Int32 nType = ::com::sun::star::chart::ChartAxisType::AUTOMATIC; 537 if( aScaleData.AxisType == AxisType::DATE ) 538 { 539 nType = ::com::sun::star::chart::ChartAxisType::DATE; 540 } 541 else if( aScaleData.AxisType == AxisType::CATEGORY ) 542 { 543 if( !aScaleData.AutoDateAxis ) 544 nType = ::com::sun::star::chart::ChartAxisType::CATEGORY; 545 } 546 aRet = uno::makeAny( nType ); 547 break; 548 } 549 case SCALE_PROP_DATE_INCREMENT: 550 { 551 if( aScaleData.AxisType == AxisType::DATE || aScaleData.AutoDateAxis ) 552 aRet = uno::makeAny( aScaleData.TimeIncrement ); 553 break; 554 } 555 case SCALE_PROP_EXPLICIT_DATE_INCREMENT: 556 { 557 if( aScaleData.AxisType == AxisType::DATE || aScaleData.AutoDateAxis ) 558 { 559 m_spChart2ModelContact->getExplicitValuesForAxis( xAxis, aExplicitScale, aExplicitIncrement ); 560 if( aExplicitScale.AxisType == AxisType::DATE ) 561 { 562 TimeIncrement aTimeIncrement; 563 aTimeIncrement.MajorTimeInterval = uno::makeAny( aExplicitIncrement.MajorTimeInterval ); 564 aTimeIncrement.MinorTimeInterval = uno::makeAny( aExplicitIncrement.MinorTimeInterval ); 565 aTimeIncrement.TimeResolution = uno::makeAny( aExplicitScale.TimeResolution ); 566 aRet = uno::makeAny(aTimeIncrement); 567 } 568 } 569 570 if( aScaleData.AxisType == AxisType::DATE || aScaleData.AutoDateAxis ) 571 aRet = uno::makeAny( aScaleData.TimeIncrement ); 572 break; 573 } 574 case SCALE_PROP_LOGARITHMIC: 575 { 576 aRet <<= static_cast< sal_Bool >( AxisHelper::isLogarithmic(aScaleData.Scaling) ); 577 break; 578 } 579 case SCALE_PROP_REVERSEDIRECTION: 580 { 581 aRet <<= static_cast< sal_Bool >( AxisOrientation_REVERSE == aScaleData.Orientation ); 582 break; 583 } 584 default: 585 { 586 OSL_ENSURE(false,"unknown scale property"); 587 break; 588 } 589 } 590 591 return aRet; 592 } 593 594 } // namespace wrapper 595 } // namespace chart 596 //............................................................................. 597