1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 31 #include "CachedDataSequence.hxx" 32 #include "macros.hxx" 33 #include "PropertyHelper.hxx" 34 #include "ContainerHelper.hxx" 35 #include "CommonFunctors.hxx" 36 #include "ModifyListenerHelper.hxx" 37 38 #include <comphelper/sequenceashashmap.hxx> 39 40 #include <algorithm> 41 #include <com/sun/star/beans/PropertyAttribute.hpp> 42 #include <rtl/math.hxx> 43 44 using namespace ::com::sun::star; 45 using namespace ::chart::ContainerHelper; 46 47 using ::com::sun::star::uno::Sequence; 48 using ::com::sun::star::uno::Reference; 49 using ::com::sun::star::uno::Any; 50 using ::rtl::OUString; 51 using ::osl::MutexGuard; 52 53 // necessary for MS compiler 54 using ::comphelper::OPropertyContainer; 55 using ::comphelper::OMutexAndBroadcastHelper; 56 using ::comphelper::OPropertyArrayUsageHelper; 57 using ::chart::impl::CachedDataSequence_Base; 58 59 namespace 60 { 61 static const OUString lcl_aServiceName( 62 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.CachedDataSequence" )); 63 64 enum 65 { 66 // PROP_SOURCE_IDENTIFIER, 67 PROP_NUMBERFORMAT_KEY, 68 PROP_PROPOSED_ROLE 69 }; 70 } // anonymous namespace 71 72 73 // ____________________ 74 namespace chart 75 { 76 77 CachedDataSequence::CachedDataSequence() 78 : OPropertyContainer( GetBroadcastHelper()), 79 CachedDataSequence_Base( GetMutex()), 80 m_eCurrentDataType( NUMERICAL ), 81 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) 82 { 83 registerProperties(); 84 } 85 CachedDataSequence::CachedDataSequence( const Reference< uno::XComponentContext > & /*xContext*/ ) 86 : OPropertyContainer( GetBroadcastHelper()), 87 CachedDataSequence_Base( GetMutex()), 88 m_eCurrentDataType( MIXED ), 89 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder( )) 90 { 91 registerProperties(); 92 } 93 94 CachedDataSequence::CachedDataSequence( const OUString & rSingleText ) 95 : OPropertyContainer( GetBroadcastHelper()), 96 CachedDataSequence_Base( GetMutex()), 97 m_eCurrentDataType( TEXTUAL ), 98 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) 99 { 100 m_aTextualSequence.realloc(1); 101 m_aTextualSequence[0] = rSingleText; 102 registerProperties(); 103 } 104 105 CachedDataSequence::CachedDataSequence( const CachedDataSequence & rSource ) 106 : OMutexAndBroadcastHelper(), 107 OPropertyContainer( GetBroadcastHelper()), 108 OPropertyArrayUsageHelper< CachedDataSequence >(), 109 CachedDataSequence_Base( GetMutex()), 110 m_nNumberFormatKey( rSource.m_nNumberFormatKey ), 111 m_sRole( rSource.m_sRole ), 112 m_eCurrentDataType( rSource.m_eCurrentDataType ), 113 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) 114 { 115 switch( m_eCurrentDataType ) 116 { 117 case TEXTUAL: 118 m_aTextualSequence = rSource.m_aTextualSequence; 119 break; 120 case NUMERICAL: 121 m_aNumericalSequence = rSource.m_aNumericalSequence; 122 break; 123 case MIXED: 124 m_aMixedSequence = rSource.m_aMixedSequence; 125 break; 126 } 127 128 registerProperties(); 129 } 130 131 CachedDataSequence::~CachedDataSequence() 132 {} 133 134 void CachedDataSequence::registerProperties() 135 { 136 registerProperty( C2U( "NumberFormatKey" ), 137 PROP_NUMBERFORMAT_KEY, 138 0, // PropertyAttributes 139 & m_nNumberFormatKey, 140 ::getCppuType( & m_nNumberFormatKey ) ); 141 142 registerProperty( C2U( "Role" ), 143 PROP_PROPOSED_ROLE, 144 0, // PropertyAttributes 145 & m_sRole, 146 ::getCppuType( & m_sRole ) ); 147 } 148 149 Sequence< double > CachedDataSequence::Impl_getNumericalData() const 150 { 151 if( m_eCurrentDataType == NUMERICAL ) 152 return m_aNumericalSequence; 153 154 sal_Int32 nSize = ( m_eCurrentDataType == TEXTUAL ) 155 ? m_aTextualSequence.getLength() 156 : m_aMixedSequence.getLength(); 157 158 Sequence< double > aResult( nSize ); 159 double * pResultArray = aResult.getArray(); 160 161 if( m_eCurrentDataType == TEXTUAL ) 162 { 163 const OUString * pTextArray = m_aTextualSequence.getConstArray(); 164 ::std::transform( pTextArray, pTextArray + nSize, 165 pResultArray, 166 CommonFunctors::OUStringToDouble() ); 167 } 168 else 169 { 170 OSL_ASSERT( m_eCurrentDataType == MIXED ); 171 const Any * pMixedArray = m_aMixedSequence.getConstArray(); 172 ::std::transform( pMixedArray, pMixedArray + nSize, 173 pResultArray, 174 CommonFunctors::AnyToDouble() ); 175 } 176 return aResult; 177 } 178 179 Sequence< OUString > CachedDataSequence::Impl_getTextualData() const 180 { 181 if( m_eCurrentDataType == TEXTUAL ) 182 return m_aTextualSequence; 183 184 sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL ) 185 ? m_aNumericalSequence.getLength() 186 : m_aMixedSequence.getLength(); 187 188 Sequence< OUString > aResult( nSize ); 189 OUString * pResultArray = aResult.getArray(); 190 191 if( m_eCurrentDataType == NUMERICAL ) 192 { 193 const double * pTextArray = m_aNumericalSequence.getConstArray(); 194 ::std::transform( pTextArray, pTextArray + nSize, 195 pResultArray, 196 CommonFunctors::DoubleToOUString() ); 197 } 198 else 199 { 200 OSL_ASSERT( m_eCurrentDataType == MIXED ); 201 const Any * pMixedArray = m_aMixedSequence.getConstArray(); 202 ::std::transform( pMixedArray, pMixedArray + nSize, 203 pResultArray, 204 CommonFunctors::AnyToString() ); 205 } 206 207 return aResult; 208 } 209 210 Sequence< Any > CachedDataSequence::Impl_getMixedData() const 211 { 212 if( m_eCurrentDataType == MIXED ) 213 return m_aMixedSequence; 214 215 sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL ) 216 ? m_aNumericalSequence.getLength() 217 : m_aTextualSequence.getLength(); 218 219 Sequence< Any > aResult( nSize ); 220 Any * pResultArray = aResult.getArray(); 221 222 if( m_eCurrentDataType == NUMERICAL ) 223 { 224 const double * pTextArray = m_aNumericalSequence.getConstArray(); 225 ::std::transform( pTextArray, pTextArray + nSize, 226 pResultArray, 227 CommonFunctors::makeAny< double >() ); 228 } 229 else 230 { 231 OSL_ASSERT( m_eCurrentDataType == TEXTUAL ); 232 const OUString * pMixedArray = m_aTextualSequence.getConstArray(); 233 ::std::transform( pMixedArray, pMixedArray + nSize, 234 pResultArray, 235 CommonFunctors::makeAny< OUString >() ); 236 } 237 238 return aResult; 239 } 240 241 // ================================================================================ 242 243 Sequence< OUString > CachedDataSequence::getSupportedServiceNames_Static() 244 { 245 Sequence< OUString > aServices( 4 ); 246 aServices[ 0 ] = lcl_aServiceName; 247 aServices[ 1 ] = C2U( "com.sun.star.chart2.data.DataSequence" ); 248 aServices[ 2 ] = C2U( "com.sun.star.chart2.data.NumericalDataSequence" ); 249 aServices[ 3 ] = C2U( "com.sun.star.chart2.data.TextualDataSequence" ); 250 return aServices; 251 } 252 253 IMPLEMENT_FORWARD_XINTERFACE2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer ) 254 IMPLEMENT_FORWARD_XTYPEPROVIDER2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer ) 255 256 // ____ XPropertySet ____ 257 Reference< beans::XPropertySetInfo > SAL_CALL CachedDataSequence::getPropertySetInfo() 258 throw(uno::RuntimeException) 259 { 260 return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) ); 261 } 262 263 // ____ ::comphelper::OPropertySetHelper ____ 264 // __________________________________________ 265 ::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper() 266 { 267 return *getArrayHelper(); 268 } 269 270 // ____ ::comphelper::OPropertyArrayHelper ____ 271 // ____________________________________________ 272 ::cppu::IPropertyArrayHelper* CachedDataSequence::createArrayHelper() const 273 { 274 Sequence< beans::Property > aProps; 275 // describes all properties which have been registered in the ctor 276 describeProperties( aProps ); 277 278 return new ::cppu::OPropertyArrayHelper( aProps ); 279 } 280 281 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static 282 APPHELPER_XSERVICEINFO_IMPL( CachedDataSequence, lcl_aServiceName ) 283 284 // ================================================================================ 285 286 // ________ XNumericalDataSequence ________ 287 Sequence< double > SAL_CALL CachedDataSequence::getNumericalData() 288 throw (uno::RuntimeException) 289 { 290 // /-- 291 MutexGuard aGuard( GetMutex() ); 292 293 if( m_eCurrentDataType == NUMERICAL ) 294 return m_aNumericalSequence; 295 else 296 return Impl_getNumericalData(); 297 // \-- 298 } 299 300 // ________ XTextualDataSequence ________ 301 Sequence< OUString > SAL_CALL CachedDataSequence::getTextualData() 302 throw (uno::RuntimeException) 303 { 304 // /-- 305 MutexGuard aGuard( GetMutex() ); 306 307 if( m_eCurrentDataType == TEXTUAL ) 308 return m_aTextualSequence; 309 else 310 return Impl_getTextualData(); 311 // \-- 312 } 313 314 // void SAL_CALL CachedDataSequence::setTextualData( const Sequence< OUString >& aData ) 315 // throw (uno::RuntimeException) 316 // { 317 // // /-- 318 // MutexGuard aGuard( GetMutex() ); 319 // Impl_setTextualData( aData ); 320 // // \-- 321 // } 322 323 // ________ XDataSequence ________ 324 Sequence< Any > SAL_CALL CachedDataSequence::getData() 325 throw (uno::RuntimeException) 326 { 327 // /-- 328 MutexGuard aGuard( GetMutex() ); 329 return Impl_getMixedData(); 330 // \-- 331 } 332 333 OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation() 334 throw (uno::RuntimeException) 335 { 336 return m_sRole; 337 } 338 339 Sequence< OUString > SAL_CALL CachedDataSequence::generateLabel( chart2::data::LabelOrigin /*eLabelOrigin*/ ) 340 throw (uno::RuntimeException) 341 { 342 // return empty label, as we have no range representaions to determine something useful 343 return Sequence< OUString >(); 344 } 345 346 ::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) 347 throw (lang::IndexOutOfBoundsException, 348 uno::RuntimeException) 349 { 350 return 0; 351 } 352 353 Reference< util::XCloneable > SAL_CALL CachedDataSequence::createClone() 354 throw (uno::RuntimeException) 355 { 356 CachedDataSequence * pNewSeq = new CachedDataSequence( *this ); 357 358 return Reference< util::XCloneable >( pNewSeq ); 359 } 360 361 void SAL_CALL CachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener ) 362 throw (uno::RuntimeException) 363 { 364 try 365 { 366 Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); 367 xBroadcaster->addModifyListener( aListener ); 368 } 369 catch( const uno::Exception & ex ) 370 { 371 ASSERT_EXCEPTION( ex ); 372 } 373 } 374 375 void SAL_CALL CachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) 376 throw (uno::RuntimeException) 377 { 378 try 379 { 380 Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); 381 xBroadcaster->removeModifyListener( aListener ); 382 } 383 catch( const uno::Exception & ex ) 384 { 385 ASSERT_EXCEPTION( ex ); 386 } 387 } 388 389 // lang::XInitialization: 390 void SAL_CALL CachedDataSequence::initialize(const uno::Sequence< uno::Any > & _aArguments) throw (uno::RuntimeException, uno::Exception) 391 { 392 ::comphelper::SequenceAsHashMap aMap(_aArguments); 393 m_aNumericalSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aNumericalSequence); 394 if ( m_aNumericalSequence.getLength() ) 395 m_eCurrentDataType = NUMERICAL; 396 else 397 { 398 m_aTextualSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aTextualSequence); 399 if ( m_aTextualSequence.getLength() ) 400 m_eCurrentDataType = TEXTUAL; 401 else 402 { 403 m_aMixedSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aMixedSequence); 404 if ( m_aMixedSequence.getLength() ) 405 m_eCurrentDataType = MIXED; 406 } 407 } 408 } 409 } // namespace chart 410