diff options
202 files changed, 7653 insertions, 7541 deletions
diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx index ba54fabd3a3c..1e278bf583a7 100644..100755 --- a/basic/source/classes/sbunoobj.cxx +++ b/basic/source/classes/sbunoobj.cxx @@ -103,6 +103,7 @@ TYPEINIT1(SbUnoObject,SbxObject) TYPEINIT1(SbUnoClass,SbxObject) TYPEINIT1(SbUnoService,SbxObject) TYPEINIT1(SbUnoServiceCtor,SbxMethod) +TYPEINIT1(SbUnoSingleton,SbxObject) typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper; @@ -3299,6 +3300,18 @@ SbxVariable* SbUnoClass::Find( const XubString& rName, SbxClassType t ) pRes->PutObject( xWrapper ); } } + + // An UNO singleton? + if( !pRes ) + { + SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName ); + if( pUnoSingleton ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton; + pRes->PutObject( xWrapper ); + } + } } } @@ -3579,6 +3592,90 @@ SbxInfo* SbUnoServiceCtor::GetInfo() } +SbUnoSingleton* findUnoSingleton( const String& rName ) +{ + SbUnoSingleton* pSbUnoSingleton = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_SINGLETON ) + { + Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY ); + if( xSingletonTypeDesc.is() ) + pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc ); + } + } + } + return pSbUnoSingleton; +} + +SbUnoSingleton::SbUnoSingleton( const String& aName_, + const Reference< XSingletonTypeDescription >& xSingletonTypeDesc ) + : SbxObject( aName_ ) + , m_xSingletonTypeDesc( xSingletonTypeDesc ) +{ + SbxVariableRef xGetMethodRef = + new SbxMethod( String( RTL_CONSTASCII_USTRINGPARAM( "get" ) ), SbxOBJECT ); + QuickInsert( (SbxVariable*)xGetMethodRef ); +} + +void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pParams = pVar->GetParameters(); + UINT32 nParamCount = pParams ? ((UINT32)pParams->Count() - 1) : 0; + UINT32 nAllowedParamCount = 1; + + Reference < XComponentContext > xContextToUse; + if( nParamCount > 0 ) + { + // Check if first parameter is a context and use it then + Reference < XComponentContext > xFirstParamContext; + Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) ); + if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() ) + xContextToUse = xFirstParamContext; + } + + if( !xContextToUse.is() ) + { + Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); + xContextToUse.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW ); + --nAllowedParamCount; + } + + if( nParamCount > nAllowedParamCount ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + Any aRetAny; + if( xContextToUse.is() ) + { + String aSingletonName( RTL_CONSTASCII_USTRINGPARAM("/singletons/") ); + aSingletonName += GetName(); + Reference < XInterface > xRet; + xContextToUse->getValueByName( aSingletonName ) >>= xRet; + aRetAny <<= xRet; + } + unoToSbxValue( pVar, aRetAny ); + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); +} + //======================================================================== //======================================================================== diff --git a/basic/source/inc/sbunoobj.hxx b/basic/source/inc/sbunoobj.hxx index d96edd1bc298..2d9836e3530e 100644 --- a/basic/source/inc/sbunoobj.hxx +++ b/basic/source/inc/sbunoobj.hxx @@ -41,6 +41,7 @@ #include <com/sun/star/script/XInvocation.hpp> #include <com/sun/star/reflection/XIdlClass.hpp> #include <com/sun/star/reflection/XServiceTypeDescription2.hpp> +#include <com/sun/star/reflection/XSingletonTypeDescription.hpp> #include <rtl/ustring.hxx> class SbUnoObject: public SbxObject @@ -226,6 +227,23 @@ public: }; +// Wrapper for UNO Singleton +class SbUnoSingleton : public SbxObject +{ + const ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XSingletonTypeDescription > m_xSingletonTypeDesc; + +public: + TYPEINFO(); + SbUnoSingleton( const String& aName_, + const ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XSingletonTypeDescription >& xSingletonTypeDesc ); + + void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); +}; +SV_DECL_IMPL_REF(SbUnoSingleton); + +SbUnoSingleton* findUnoSingleton( const String& rName ); + + // #105565 Special Object to wrap a strongly typed Uno Any class SbUnoAnyObject: public SbxObject { diff --git a/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx index 375119ce521f..253699f4595c 100644 --- a/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx @@ -61,59 +61,18 @@ using namespace ::com::sun::star; using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; using ::osl::MutexGuard; +using ::com::sun::star::chart::XComplexDescriptionAccess; +using ::com::sun::star::chart::XChartData; +using ::com::sun::star::chart::XChartDataArray; namespace { static const ::rtl::OUString lcl_aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.ChartData" )); -struct lcl_DataSequenceToDoubleSeq : public ::std::unary_function< - uno::Reference< chart2::data::XDataSequence >, - uno::Sequence< double > > -{ - uno::Sequence< double > operator() ( const uno::Reference< chart2::data::XDataSequence > & xSeq ) - { - uno::Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY ); - if( xNumSeq.is()) - { - return xNumSeq->getNumericalData(); - } - else if( xSeq.is()) - { - uno::Sequence< uno::Any > aValues = xSeq->getData(); - uno::Sequence< double > aResult( aValues.getLength()); - const sal_Int32 nLength = aValues.getLength(); - for( sal_Int32 i = 0; i < nLength; ++i ) - { - if( ! ( aValues[ i ] >>= aResult[ i ]) ) - { - aResult[ i ] = DBL_MIN; - } - double& rValue = aResult[ i ]; - if( ::rtl::math::isNan( rValue ) ) - rValue = DBL_MIN; - } - return aResult; - } - return uno::Sequence< double >(); - } -}; - -void lcl_AddSequences( uno::Reference< chart2::data::XLabeledDataSequence > xLSeq, - ::std::vector< uno::Reference< chart2::data::XDataSequence > > & rOutSeqVector, - ::std::vector< ::rtl::OUString > & rOutLabelVector ) -{ - if( xLSeq.is() ) - { - uno::Reference< chart2::data::XDataSequence > xSeq( xLSeq->getValues() ); - rOutSeqVector.push_back( xSeq ); - - ::rtl::OUString aLabel( ::chart::DataSeriesHelper::getLabelForLabeledDataSequence( xLSeq ) ); - rOutLabelVector.push_back( aLabel ); - } -} - uno::Sequence< uno::Sequence< double > > lcl_getNANInsteadDBL_MIN( const uno::Sequence< uno::Sequence< double > >& rData ) { uno::Sequence< uno::Sequence< double > > aRet; @@ -163,11 +122,197 @@ namespace chart namespace wrapper { +//-------------------------------------------------------------------------------------- + +struct lcl_Operator +{ + lcl_Operator() + { + } + virtual ~lcl_Operator() + { + } + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) = 0; + + virtual bool setsCategories( bool /*bDataInColumns*/ ) + { + return false; + } +}; + +//-------------------------------------------------------------------------- + +struct lcl_AllOperator : public lcl_Operator +{ + lcl_AllOperator( const Reference< XChartData >& xDataToApply ) + : lcl_Operator() + , m_xDataToApply( xDataToApply ) + { + } + + virtual bool setsCategories( bool /*bDataInColumns*/ ) + { + return true; + } + + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) + { + if( !xDataAccess.is() ) + return; + + Reference< XComplexDescriptionAccess > xNewComplex( m_xDataToApply, uno::UNO_QUERY ); + if( xNewComplex.is() ) + { + xDataAccess->setData( xNewComplex->getData() ); + xDataAccess->setComplexRowDescriptions( xNewComplex->getComplexRowDescriptions() ); + xDataAccess->setComplexColumnDescriptions( xNewComplex->getComplexColumnDescriptions() ); + } + else + { + Reference< XChartDataArray > xNew( m_xDataToApply, uno::UNO_QUERY ); + if( xNew.is() ) + { + xDataAccess->setData( xNew->getData() ); + xDataAccess->setRowDescriptions( xNew->getRowDescriptions() ); + xDataAccess->setColumnDescriptions( xNew->getColumnDescriptions() ); + } + } + } + + Reference< XChartData > m_xDataToApply; +}; + +//-------------------------------------------------------------------------- + +struct lcl_DataOperator : public lcl_Operator +{ + lcl_DataOperator( const Sequence< Sequence< double > >& rData ) + : lcl_Operator() + , m_rData( rData ) + { + } + + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) + { + if( xDataAccess.is() ) + xDataAccess->setData( lcl_getNANInsteadDBL_MIN( m_rData ) ); + } + + const Sequence< Sequence< double > >& m_rData; +}; + +//-------------------------------------------------------------------------- + +struct lcl_RowDescriptionsOperator : public lcl_Operator +{ + lcl_RowDescriptionsOperator( const Sequence< OUString >& rRowDescriptions ) + : lcl_Operator() + , m_rRowDescriptions( rRowDescriptions ) + { + } + + virtual bool setsCategories( bool bDataInColumns ) + { + return bDataInColumns; + } + + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) + { + if( xDataAccess.is() ) + xDataAccess->setRowDescriptions( m_rRowDescriptions ); + } + + const Sequence< OUString >& m_rRowDescriptions; +}; + +//-------------------------------------------------------------------------- + +struct lcl_ComplexRowDescriptionsOperator : public lcl_Operator +{ + lcl_ComplexRowDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexRowDescriptions ) + : lcl_Operator() + , m_rComplexRowDescriptions( rComplexRowDescriptions ) + { + } + + virtual bool setsCategories( bool bDataInColumns ) + { + return !bDataInColumns; + } + + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) + { + if( xDataAccess.is() ) + xDataAccess->setComplexRowDescriptions( m_rComplexRowDescriptions ); + } + + const Sequence< Sequence< OUString > >& m_rComplexRowDescriptions; +}; + +//-------------------------------------------------------------------------- + +struct lcl_ColumnDescriptionsOperator : public lcl_Operator +{ + lcl_ColumnDescriptionsOperator( const Sequence< OUString >& rColumnDescriptions ) + : lcl_Operator() + , m_rColumnDescriptions( rColumnDescriptions ) + { + } + + virtual bool setsCategories( bool bDataInColumns ) + { + return !bDataInColumns; + } + + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) + { + if( xDataAccess.is() ) + xDataAccess->setColumnDescriptions( m_rColumnDescriptions ); + } + + const Sequence< OUString >& m_rColumnDescriptions; +}; + +//-------------------------------------------------------------------------- + +struct lcl_ComplexColumnDescriptionsOperator : public lcl_Operator +{ + lcl_ComplexColumnDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexColumnDescriptions ) + : lcl_Operator() + , m_rComplexColumnDescriptions( rComplexColumnDescriptions ) + { + } + + virtual bool setsCategories( bool bDataInColumns ) + { + return !bDataInColumns; + } + + virtual void apply( const Reference< XComplexDescriptionAccess >& xDataAccess ) + { + if( xDataAccess.is() ) + xDataAccess->setComplexColumnDescriptions( m_rComplexColumnDescriptions ); + } + + const Sequence< Sequence< OUString > >& m_rComplexColumnDescriptions; +}; + +//-------------------------------------------------------------------------- + ChartDataWrapper::ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ) : m_spChart2ModelContact( spChart2ModelContact ), m_aEventListenerContainer( m_aMutex ) { - refreshData(); + initDataAccess(); +} + +ChartDataWrapper::ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact, + const Reference< XChartData >& xNewData ) : + m_spChart2ModelContact( spChart2ModelContact ), + m_aEventListenerContainer( m_aMutex ) +{ + lcl_AllOperator aOperator( xNewData ); + applyData( aOperator ); } ChartDataWrapper::~ChartDataWrapper() @@ -179,87 +324,80 @@ ChartDataWrapper::~ChartDataWrapper() // m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); } -// ____ XChartDataArray ____ -uno::Sequence< uno::Sequence< double > > SAL_CALL ChartDataWrapper::getData() +// ____ XChartDataArray (read)____ +Sequence< Sequence< double > > SAL_CALL ChartDataWrapper::getData() throw (uno::RuntimeException) { - // until we have a data change notification mechanism we always have to - // update the data here - refreshData(); - // /-- - MutexGuard aGuard( GetMutex()); - return m_aData; - // \-- + initDataAccess(); + if( m_xDataAccess.is() ) + return lcl_getDBL_MINInsteadNAN( m_xDataAccess->getData() ); + return Sequence< Sequence< double > >(); } - -void SAL_CALL ChartDataWrapper::setData( - const uno::Sequence< uno::Sequence< double > >& aData ) +Sequence< OUString > SAL_CALL ChartDataWrapper::getRowDescriptions() throw (uno::RuntimeException) { - refreshData(); - { - // /-- - MutexGuard aGuard( GetMutex()); - m_aData = aData; - // \-- - } - applyData( true, false, false ); + initDataAccess(); + if( m_xDataAccess.is() ) + return m_xDataAccess->getRowDescriptions(); + return Sequence< OUString >(); } - -uno::Sequence< ::rtl::OUString > SAL_CALL ChartDataWrapper::getRowDescriptions() +Sequence< OUString > SAL_CALL ChartDataWrapper::getColumnDescriptions() throw (uno::RuntimeException) { - // until we have a data change notification mechanism we always have to - // update the data here - refreshData(); - - // /-- - MutexGuard aGuard( GetMutex()); - return m_aRowDescriptions; - // \-- + initDataAccess(); + if( m_xDataAccess.is() ) + return m_xDataAccess->getColumnDescriptions(); + return Sequence< OUString > (); +} +// ____ XComplexDescriptionAccess (read) ____ +Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexRowDescriptions() throw (uno::RuntimeException) +{ + initDataAccess(); + if( m_xDataAccess.is() ) + return m_xDataAccess->getComplexRowDescriptions(); + return Sequence< Sequence< OUString > >(); +} +Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexColumnDescriptions() throw (uno::RuntimeException) +{ + initDataAccess(); + if( m_xDataAccess.is() ) + return m_xDataAccess->getComplexColumnDescriptions(); + return Sequence< Sequence< OUString > >(); } -void SAL_CALL ChartDataWrapper::setRowDescriptions( - const uno::Sequence< ::rtl::OUString >& aRowDescriptions ) +// ____ XChartDataArray (write)____ +void SAL_CALL ChartDataWrapper::setData( const Sequence< Sequence< double > >& rData ) throw (uno::RuntimeException) { - refreshData(); - { - // /-- - MutexGuard aGuard( GetMutex()); - m_aRowDescriptions = aRowDescriptions; - // \-- - } - applyData( false, true, false ); + lcl_DataOperator aOperator( rData ); + applyData( aOperator ); } - -uno::Sequence< - ::rtl::OUString > SAL_CALL ChartDataWrapper::getColumnDescriptions() +void SAL_CALL ChartDataWrapper::setRowDescriptions( const Sequence< OUString >& rRowDescriptions ) throw (uno::RuntimeException) { - // until we have a data change notification mechanism we always have to - // update the data here - refreshData(); - // /-- - MutexGuard aGuard( GetMutex()); - return m_aColumnDescriptions; - // \-- + lcl_RowDescriptionsOperator aOperator( rRowDescriptions ); + applyData( aOperator ); } - -void SAL_CALL ChartDataWrapper::setColumnDescriptions( - const uno::Sequence< ::rtl::OUString >& aColumnDescriptions ) +void SAL_CALL ChartDataWrapper::setColumnDescriptions( const Sequence< OUString >& rColumnDescriptions ) throw (uno::RuntimeException) { - refreshData(); - { - // /-- - MutexGuard aGuard( GetMutex()); - m_aColumnDescriptions = aColumnDescriptions; - // \-- - } - applyData( false, false, true ); + lcl_ColumnDescriptionsOperator aOperator( rColumnDescriptions ); + applyData( aOperator ); +} + +// ____ XComplexDescriptionAccess (write) ____ +void SAL_CALL ChartDataWrapper::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& rRowDescriptions ) throw (uno::RuntimeException) +{ + lcl_ComplexRowDescriptionsOperator aOperator( rRowDescriptions ); + applyData( aOperator ); +} +void SAL_CALL ChartDataWrapper::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& rColumnDescriptions ) throw (uno::RuntimeException) +{ + lcl_ComplexColumnDescriptionsOperator aOperator( rColumnDescriptions ); + applyData( aOperator ); } +//-------------------------------------------------------------------------------------- // ____ XChartData (base of XChartDataArray) ____ void SAL_CALL ChartDataWrapper::addChartDataChangeEventListener( @@ -297,13 +435,7 @@ void SAL_CALL ChartDataWrapper::dispose() throw (uno::RuntimeException) { m_aEventListenerContainer.disposeAndClear( lang::EventObject( static_cast< ::cppu::OWeakObject* >( this ))); - - // /-- - MutexGuard aGuard( GetMutex()); - m_aData.realloc( 0 ); - m_aColumnDescriptions.realloc( 0 ); - m_aRowDescriptions.realloc( 0 ); - // \-- + m_xDataAccess=0; } void SAL_CALL ChartDataWrapper::addEventListener( @@ -354,160 +486,39 @@ void ChartDataWrapper::fireChartDataChangeEvent( } } -void ChartDataWrapper::refreshData() +// -------------------------------------------------------------------------------- + +void ChartDataWrapper::switchToInternalDataProvider() +{ + //create an internal data provider that is connected to the model + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + if( xChartDoc.is() ) + xChartDoc->createInternalDataProvider( true /*bCloneExistingData*/ ); + initDataAccess(); +} + +void ChartDataWrapper::initDataAccess() { - //todo mutex... Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); if( !xChartDoc.is() ) return; - if( xChartDoc->hasInternalDataProvider()) - { - try { - uno::Reference< ::com::sun::star::chart::XChartDataArray > xInternalData( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW ); - m_aColumnDescriptions = xInternalData->getColumnDescriptions(); - m_aRowDescriptions = xInternalData->getRowDescriptions(); - m_aData = lcl_getDBL_MINInsteadNAN( xInternalData->getData() ); - } - catch( const uno::Exception & ex ) { - ASSERT_EXCEPTION( ex ); - } - } + if( xChartDoc->hasInternalDataProvider() ) + m_xDataAccess = Reference< XComplexDescriptionAccess >( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW ); else { - uno::Reference< chart2::XDiagram > xDia( - xChartDoc->getFirstDiagram() ); - if( ! xDia.is()) - return; - - // get information about the segmentation of the assumed "rectangular" data - // range - ::rtl::OUString aRangeString; - bool bUseColumns = true; - bool bFirstCellAsLabel = true; - bool bHasCategories = true; - uno::Sequence< sal_Int32 > aSequenceMapping; - - DataSourceHelper::detectRangeSegmentation( - uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ), - aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ); - - - // get data values from data series - // -------------------------------- - uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledSequences; - uno::Reference< chart2::data::XDataSource > xRectangularDataSource( - DataSourceHelper::pressUsedDataIntoRectangularFormat( xChartDoc, false /*bWithCategories*/ ) ); - if( xRectangularDataSource.is() ) - { - aLabeledSequences = xRectangularDataSource->getDataSequences(); - } - - ::std::vector< uno::Reference< chart2::data::XDataSequence > > aSequenceVector; - ::std::vector< ::rtl::OUString > aLabelVector; - for( sal_Int32 nN=0; nN<aLabeledSequences.getLength(); nN++ ) - lcl_AddSequences( aLabeledSequences[nN], aSequenceVector, aLabelVector ); - - if( aSequenceMapping.getLength() ) - { - //aSequenceVector and aLabelVector contain changed positions; resort them to the original position - ::std::vector< uno::Reference< chart2::data::XDataSequence > > aBackSortedSequences; - ::std::vector< ::rtl::OUString > aBackSortedLabels; - - std::map< sal_Int32, sal_Int32 > aReverseMap; - { - sal_Int32 nNewIndex, nOldIndex; - for( sal_Int32 nS=0; nS <aSequenceMapping.getLength(); nS++ ) - { - nOldIndex = aSequenceMapping[nS]; - nNewIndex = nS; - if( bHasCategories ) - nNewIndex--; - if( nOldIndex >= 0 && nNewIndex >= 0 ) - aReverseMap[nOldIndex] = nNewIndex; - } - } - - std::map< sal_Int32, sal_Int32 >::iterator aMapIt = aReverseMap.begin(); - std::map< sal_Int32, sal_Int32 >::const_iterator aMapEnd = aReverseMap.end(); - - for( ; aMapIt != aMapEnd; ++aMapIt ) - { - size_t nNewIndex = static_cast< size_t >( aMapIt->second ); - if( nNewIndex < aSequenceVector.size() ) - aBackSortedSequences.push_back( aSequenceVector[nNewIndex] ); - if( nNewIndex < aLabelVector.size() ) - aBackSortedLabels.push_back( aLabelVector[nNewIndex] ); - } - - // note: assign( beg, end ) doesn't work on solaris - aSequenceVector.clear(); - aSequenceVector.insert( - aSequenceVector.begin(), aBackSortedSequences.begin(), aBackSortedSequences.end() ); - aLabelVector.clear(); - aLabelVector.insert( - aLabelVector.begin(), aBackSortedLabels.begin(), aBackSortedLabels.end() ); - } - - if( bUseColumns ) - { - const sal_Int32 nInnerSize = aSequenceVector.size(); - if( nInnerSize > 0 && aSequenceVector[0].is() ) - { - // take the length of the first data series also as length for all - // other series - const sal_Int32 nOuterSize = aSequenceVector[0]->getData().getLength(); - - m_aData.realloc( nOuterSize ); - for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter ) - m_aData[nOuter].realloc( nInnerSize ); - - for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner ) - { - uno::Sequence< double > aValues = uno::Sequence< double > ( - lcl_DataSequenceToDoubleSeq() (aSequenceVector[nInner] )); - sal_Int32 nMax = ::std::min( nOuterSize, aValues.getLength()); - for( sal_Int32 nOuter=0; nOuter<nMax; ++nOuter ) - m_aData[nOuter][nInner] = aValues[nOuter]; - } - } - } - else - { - m_aData.realloc( static_cast< sal_Int32 >( aSequenceVector.size())); - ::std::transform( aSequenceVector.begin(), aSequenceVector.end(), - m_aData.getArray(), - lcl_DataSequenceToDoubleSeq() ); - } - - // labels (values already filled during parsing of data values) - if( bUseColumns ) - m_aColumnDescriptions = ::chart::ContainerHelper::ContainerToSequence( aLabelVector ); - else - m_aRowDescriptions = ::chart::ContainerHelper::ContainerToSequence( aLabelVector ); - - // get row-/column descriptions - // ---------------------------- - // categories - uno::Sequence< ::rtl::OUString > & rSequence = - bUseColumns ? m_aRowDescriptions : m_aColumnDescriptions; - rSequence = DiagramHelper::generateAutomaticCategories( xChartDoc ); + //create a separate "internal data provider" that is not connected to the model + m_xDataAccess = Reference< XComplexDescriptionAccess >( ChartModelHelper::createInternalDataProvider( + xChartDoc, false /*bConnectToModel*/ ), uno::UNO_QUERY_THROW ); } } -void ChartDataWrapper::applyData( bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions ) +void ChartDataWrapper::applyData( lcl_Operator& rDataOperator ) { + //bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); if( !xChartDoc.is() ) return; - // /-- locked controllers - ControllerLockGuard aCtrlLockGuard( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY )); - // should do nothing if we already have an internal data provider - xChartDoc->createInternalDataProvider( sal_True /* bCloneExistingData */ ); - - uno::Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider()); - uno::Reference< XChartDataArray > xDocDataArray( xDataProvider, uno::UNO_QUERY ); - // remember some diagram properties to reset later sal_Bool bStacked = sal_False; sal_Bool bPercent = sal_False; @@ -533,71 +544,24 @@ void ChartDataWrapper::applyData( bool bSetValues, bool bSetRowDescriptions, boo uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ), aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ); - if( !bFirstCellAsLabel ) - { - if( bSetRowDescriptions && !bUseColumns ) - bFirstCellAsLabel = true; - else if( bSetColumnDescriptions && bUseColumns ) - bFirstCellAsLabel = true; - } - if( !bHasCategories ) - { - if( bSetColumnDescriptions && bUseColumns ) - bHasCategories = true; - else if( bSetRowDescriptions && !bUseColumns ) - bHasCategories = true; - } + if( !bHasCategories && rDataOperator.setsCategories( bUseColumns ) ) + bHasCategories = true; - aRangeString = C2U("all"); uno::Sequence< beans::PropertyValue > aArguments( DataSourceHelper::createArguments( aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ) ); - // create and attach new data source - uno::Reference< chart2::data::XDataSource > xSource; - if( xDocDataArray.is() ) - { - // we have an internal data provider that supports the XChartDataArray - // interface - if( bSetValues ) - xDocDataArray->setData( lcl_getNANInsteadDBL_MIN( m_aData ) ); - if( bSetRowDescriptions ) - xDocDataArray->setRowDescriptions( m_aRowDescriptions ); - if( bSetColumnDescriptions ) - xDocDataArray->setColumnDescriptions( m_aColumnDescriptions ); - - xSource.set( xDataProvider->createDataSource( aArguments )); - } - else - { - uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); - OSL_ASSERT( xChartDoc.is()); - OSL_ASSERT( xReceiver.is()); - if( ! (xChartDoc.is() && xReceiver.is())) - return; - // create a data provider containing the new data - uno::Reference< chart2::data::XDataProvider > xTempDataProvider( - ChartModelHelper::createInternalDataProvider() ); - if( ! xTempDataProvider.is()) - throw uno::RuntimeException( C2U("Couldn't create temporary data provider"), - static_cast< ::cppu::OWeakObject * >( this )); + // /-- locked controllers + ControllerLockGuard aCtrlLockGuard( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY )); - uno::Reference< ::com::sun::star::chart::XChartDataArray > xDataArray( xTempDataProvider, uno::UNO_QUERY ); - OSL_ASSERT( xDataArray.is()); - if( xDataArray.is()) - { - if( bSetValues ) - xDataArray->setData( lcl_getNANInsteadDBL_MIN( m_aData ) ); - if( bSetRowDescriptions ) - xDataArray->setRowDescriptions( m_aRowDescriptions ); - if( bSetColumnDescriptions ) - xDataArray->setColumnDescriptions( m_aColumnDescriptions ); - - // removes existing data provider and attaches the new one - xReceiver->attachDataProvider( xTempDataProvider ); - xSource.set( xTempDataProvider->createDataSource( aArguments)); - } - } + // create and attach new data source + switchToInternalDataProvider(); + rDataOperator.apply(m_xDataAccess); + uno::Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() ); + OSL_ASSERT( xDataProvider.is() ); + if( !xDataProvider.is() ) + return; + uno::Reference< chart2::data::XDataSource > xSource( xDataProvider->createDataSource( aArguments ) ); // determine a template uno::Reference< lang::XMultiServiceFactory > xFact( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); @@ -621,8 +585,7 @@ void ChartDataWrapper::applyData( bool bSetValues, bool bSetRowDescriptions, boo // argument detection works with internal knowledge of the // ArrayDataProvider OSL_ASSERT( xDia.is()); - xTemplate->changeDiagramData( - xDia, xSource, aArguments ); + xTemplate->changeDiagramData( xDia, xSource, aArguments ); } //correct stacking mode diff --git a/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx index 6bdae0350184..d56397953d79 100644 --- a/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx +++ b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx @@ -31,7 +31,7 @@ #include "MutexContainer.hxx" #include <cppuhelper/implbase4.hxx> #include <cppuhelper/interfacecontainer.hxx> -#include <com/sun/star/chart/XChartDataArray.hpp> +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> @@ -45,23 +45,40 @@ namespace wrapper { class Chart2ModelContact; +struct lcl_Operator; class ChartDataWrapper : public MutexContainer, public ::cppu::WeakImplHelper4< - com::sun::star::chart::XChartDataArray, + com::sun::star::chart::XComplexDescriptionAccess, com::sun::star::lang::XServiceInfo, com::sun::star::lang::XEventListener, com::sun::star::lang::XComponent > { public: ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ); + ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact + , const ::com::sun::star::uno::Reference< ::com::sun::star::chart::XChartData >& xNewData ); virtual ~ChartDataWrapper(); /// XServiceInfo declarations APPHELPER_XSERVICEINFO_DECL() protected: - // ____ XChartDataArray ____ + // ____ XComplexDescriptionAccess ____ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > > SAL_CALL + getComplexRowDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setComplexRowDescriptions( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< ::rtl::OUString > >& aRowDescriptions ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > > SAL_CALL + getComplexColumnDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setComplexColumnDescriptions( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< ::rtl::OUString > >& aColumnDescriptions ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XChartDataArray (base of XComplexDescriptionAccess) ____ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > > SAL_CALL getData() @@ -112,20 +129,17 @@ protected: void fireChartDataChangeEvent( ::com::sun::star::chart::ChartDataChangeEvent& aEvent ); -private: - ::boost::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; - ::cppu::OInterfaceContainerHelper m_aEventListenerContainer; - - ::com::sun::star::uno::Sequence< - ::com::sun::star::uno::Sequence< double > > m_aData; - ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aColumnDescriptions; - ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aRowDescriptions; +private: //methods + void switchToInternalDataProvider(); + void initDataAccess(); + void applyData( lcl_Operator& rDataOperator ); - /// re-reads the data from the model - void refreshData(); +private: //member + ::com::sun::star::uno::Reference< + ::com::sun::star::chart::XComplexDescriptionAccess > m_xDataAccess; - /// applies changed data to model - void applyData( bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions ); + ::boost::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::cppu::OInterfaceContainerHelper m_aEventListenerContainer; }; } // namespace wrapper diff --git a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx index da0c9b4e8167..67f537c49b98 100644 --- a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx @@ -58,7 +58,7 @@ #include <com/sun/star/chart2/XTitled.hpp> #include <com/sun/star/chart2/data/XDataReceiver.hpp> #include <com/sun/star/chart/ChartDataRowSource.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> #include <comphelper/InlineContainer.hxx> // header for function SvxShapeCollection_NewInstance #include <svx/unoshcol.hxx> @@ -77,6 +77,7 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::chart; +using ::com::sun::star::chart::XComplexDescriptionAccess; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; @@ -830,7 +831,7 @@ void SAL_CALL ChartDocumentWrapper::setDiagram( const Reference< XDiagram >& xDi Reference< XChartData > SAL_CALL ChartDocumentWrapper::getData() throw (uno::RuntimeException) { - if( ! m_xChartData.is()) + if( !m_xChartData.is() ) { m_xChartData.set( new ChartDataWrapper( m_spChart2ModelContact ) ); } @@ -839,128 +840,15 @@ Reference< XChartData > SAL_CALL ChartDocumentWrapper::getData() return m_xChartData; } -void SAL_CALL ChartDocumentWrapper::attachData( const Reference< XChartData >& xData ) +void SAL_CALL ChartDocumentWrapper::attachData( const Reference< XChartData >& xNewData ) throw (uno::RuntimeException) { - if( !xData.is()) + if( !xNewData.is() ) return; - Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); - if( !xChartDoc.is() ) - return; - - uno::Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider()); - uno::Reference< XChartDataArray > xDocDataArray( xDataProvider, uno::UNO_QUERY ); - uno::Reference< XChartDataArray > xDataArray( xData, uno::UNO_QUERY ); - OSL_ASSERT( xDataArray.is()); - if( ! xDataArray.is() || - xDocDataArray == xDataArray ) - return; - - // remember some diagram properties to reset later - ChartDataRowSource eSeriesSource = ChartDataRowSource_ROWS; - sal_Bool bStacked = sal_False; - sal_Bool bPercent = sal_False; - sal_Bool bDeep = sal_False; - Reference< beans::XPropertySet > xDiaProp( getDiagram(), uno::UNO_QUERY ); - if( xDiaProp.is()) - { - xDiaProp->getPropertyValue( C2U("DataRowSource")) >>= eSeriesSource; - xDiaProp->getPropertyValue( C2U("Stacked")) >>= bStacked; - xDiaProp->getPropertyValue( C2U("Percent")) >>= bPercent; - xDiaProp->getPropertyValue( C2U("Deep")) >>= bDeep; - } - - // create and attach new data source - uno::Reference< chart2::data::XDataSource > xSource; - Sequence< beans::PropertyValue > aArguments( 4 ); - aArguments[0] = beans::PropertyValue( - C2U("CellRangeRepresentation"), -1, uno::makeAny( C2U("all") ), - beans::PropertyState_DIRECT_VALUE ); - aArguments[1] = beans::PropertyValue( - C2U("DataRowSource"), -1, uno::makeAny( eSeriesSource ), - beans::PropertyState_DIRECT_VALUE ); - aArguments[2] = beans::PropertyValue( - C2U("FirstCellAsLabel"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); - aArguments[3] = beans::PropertyValue( - C2U("HasCategories"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); - // /-- locked controllers - ControllerLockGuard aCtrlLockGuard( Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY )); - if( xDocDataArray.is()) - { - // we have an internal data provider that supports the XChartDataArray - // interface - xDocDataArray->setData( xDataArray->getData()); - xDocDataArray->setRowDescriptions( xDataArray->getRowDescriptions()); - xDocDataArray->setColumnDescriptions( xDataArray->getColumnDescriptions()); - - xSource.set( xDataProvider->createDataSource( aArguments )); - } - else - { - uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); - OSL_ASSERT( xChartDoc.is()); - OSL_ASSERT( xReceiver.is()); - OSL_ASSERT( xDataArray.is()); - if( ! (xChartDoc.is() && - xReceiver.is())) - return; - - // create a data provider containing the new data - Reference< chart2::data::XDataProvider > xTempDataProvider( - ChartModelHelper::createInternalDataProvider( xDataArray )); - - if( ! xTempDataProvider.is()) - throw uno::RuntimeException( C2U("Couldn't create temporary data provider"), - static_cast< ::cppu::OWeakObject * >( this )); - - // removes existing data provider and attaches the new one - xReceiver->attachDataProvider( xTempDataProvider ); - xSource.set( xTempDataProvider->createDataSource( aArguments)); - } - - // determine a template - Reference< lang::XMultiServiceFactory > xFact( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); - Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram()); - DiagramHelper::tTemplateWithServiceName aTemplateAndService = - DiagramHelper::getTemplateForDiagram( xDia, xFact ); - OUString aServiceName( aTemplateAndService.second ); - Reference< chart2::XChartTypeTemplate > xTemplate = aTemplateAndService.first; - - // (fall-back) - if( ! xTemplate.is()) - { - if( aServiceName.getLength() == 0 ) - aServiceName = C2U("com.sun.star.chart2.template.Column"); - xTemplate.set( xFact->createInstance( aServiceName ), uno::UNO_QUERY ); - } - OSL_ASSERT( xTemplate.is()); - - if( xTemplate.is() && xSource.is()) - { - // argument detection works with internal knowledge of the - // ArrayDataProvider - OSL_ASSERT( xDia.is()); - xTemplate->changeDiagramData( - xDia, xSource, aArguments ); - } - - // should do nothing if we already have an internal data provider - xChartDoc->createInternalDataProvider( sal_True /* bCloneExistingData */ ); - - //correct stacking mode - if( bStacked || bPercent || bDeep ) - { - StackMode eStackMode = StackMode_Y_STACKED; - if( bDeep ) - eStackMode = StackMode_Z_STACKED; - else if( bPercent ) - eStackMode = StackMode_Y_STACKED_PERCENT; - DiagramHelper::setStackMode( xDia, eStackMode ); - } - - m_xChartData = xData; + ControllerLockGuard aCtrlLockGuard( Reference< frame::XModel >( m_spChart2ModelContact->getChart2Document(), uno::UNO_QUERY )); + m_xChartData.set( new ChartDataWrapper( m_spChart2ModelContact, xNewData ) ); // \-- locked controllers } diff --git a/chart2/source/controller/dialogs/DataBrowser.cxx b/chart2/source/controller/dialogs/DataBrowser.cxx index 1265f4412f2a..67930fc6f7a7 100644 --- a/chart2/source/controller/dialogs/DataBrowser.cxx +++ b/chart2/source/controller/dialogs/DataBrowser.cxx @@ -45,6 +45,8 @@ #include "DataSeriesHelper.hxx" #include "DiagramHelper.hxx" #include "ChartModelHelper.hxx" +#include "CommonConverters.hxx" +#include "macros.hxx" #include "chartview/NumberFormatterWrapper.hxx" #include "servicenames_charttypes.hxx" #include "ResId.hxx" @@ -187,6 +189,8 @@ public: sal_Int32 GetStartColumn() const; sal_Int32 GetEndColumn() const; + static sal_Int32 GetRelativeAppFontXPosForNameField(); + void Show(); /** call this before destroying the class. This notifies the listeners to @@ -262,23 +266,30 @@ void SeriesHeader::SetColor( const Color & rCol ) m_spColorBar->SetControlBackground( rCol ); } +const sal_Int32 nSymbolHeight = 10; +const sal_Int32 nSymbolDistance = 2; + +sal_Int32 SeriesHeader::GetRelativeAppFontXPosForNameField() +{ + return nSymbolHeight + nSymbolDistance; +} + void SeriesHeader::SetPos( const Point & rPos ) { m_aPos = rPos; // chart type symbol - sal_Int32 nHeight = 10; Point aPos( rPos ); - aPos.setY( aPos.getY() + 2 ); - Size aSize( nHeight, nHeight ); + aPos.setY( aPos.getY() + nSymbolDistance ); + Size aSize( nSymbolHeight, nSymbolHeight ); m_spSymbol->SetPosPixel( m_pDevice->LogicToPixel( aPos, MAP_APPFONT )); m_spSymbol->SetSizePixel( m_pDevice->LogicToPixel( aSize, MAP_APPFONT )); - aPos.setY( aPos.getY() - 2 ); + aPos.setY( aPos.getY() - nSymbolDistance ); // series name edit field - aPos.setX( aPos.getX() + nHeight + 2 ); - aSize.setWidth( m_nWidth - nHeight - 2 ); - nHeight = 12; + aPos.setX( aPos.getX() + nSymbolHeight + nSymbolDistance ); + aSize.setWidth( m_nWidth - nSymbolHeight - nSymbolDistance ); + sal_Int32 nHeight = 12; aSize.setHeight( nHeight ); m_spSeriesName->SetPosPixel( m_pDevice->LogicToPixel( aPos, MAP_APPFONT )); m_spSeriesName->SetSizePixel( m_pDevice->LogicToPixel( aSize, MAP_APPFONT )); @@ -553,25 +564,14 @@ bool DataBrowser::MaySwapColumns() const return (static_cast< sal_uInt32 >( nColIndex ) < (m_aSeriesHeaders.size() - 1)); } + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); return ! IsReadOnly() - && ( GetCurColumnId() > 1 ) - && ( GetCurColumnId() < ColCount() - 1 ); + && ( nColIdx > 0 ) + && ( nColIdx < ColCount()-2 ) + && m_apDataBrowserModel.get() + && !m_apDataBrowserModel->isCategoriesColumn( nColIdx ); } -// bool DataBrowser::MaySortRow() const -// { -// // not implemented -// return false; -// // return ! IsReadOnly() && ( GetCurRow() >= 0 ); -// } - -// bool DataBrowser::MaySortColumn() const -// { -// // not implemented -// return false; -// // return ! IsReadOnly() && ( GetCurColumnId() > 1 ); -// } - void DataBrowser::clearHeaders() { ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor()); @@ -601,9 +601,10 @@ void DataBrowser::RenewTable() InsertHandleColumn( static_cast< sal_uInt16 >( GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() )); - const sal_Int32 nDefaultColumnWidth = 94; - - sal_Int32 nColumnWidth( GetDataWindow().LogicToPixel( Size( nDefaultColumnWidth, 0 )).getWidth()); + OUString aDefaultSeriesName( ::chart::SchResId::getResString( STR_COLUMN_LABEL )); + replaceParamterInString( aDefaultSeriesName, C2U("%COLUMNNUMBER"), OUString::valueOf( sal_Int32(24) ) ); + sal_Int32 nColumnWidth = GetDataWindow().GetTextWidth( aDefaultSeriesName ) + + GetDataWindow().LogicToPixel( Point( 4 + impl::SeriesHeader::GetRelativeAppFontXPosForNameField(), 0 ), MAP_APPFONT ).X(); sal_Int32 nColumnCount = m_apDataBrowserModel->getColumnCount(); // nRowCount is a member of a base class sal_Int32 nRowCountLocal = m_apDataBrowserModel->getMaxRowCount(); @@ -882,6 +883,22 @@ void DataBrowser::InsertColumn() } } +void DataBrowser::InsertTextColumn() +{ + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + + if( nColIdx >= 0 && + m_apDataBrowserModel.get()) + { + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->insertComplexCategoryLevel( nColIdx ); + RenewTable(); + } +} + void DataBrowser::RemoveColumn() { sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); @@ -894,7 +911,7 @@ void DataBrowser::RemoveColumn() SaveModified(); m_bDataValid = true; - m_apDataBrowserModel->removeDataSeries( nColIdx ); + m_apDataBrowserModel->removeDataSeriesOrComplexCategoryLevel( nColIdx ); RenewTable(); } } diff --git a/chart2/source/controller/dialogs/DataBrowser.hxx b/chart2/source/controller/dialogs/DataBrowser.hxx index 97c952c2cee9..3583db2770c0 100644 --- a/chart2/source/controller/dialogs/DataBrowser.hxx +++ b/chart2/source/controller/dialogs/DataBrowser.hxx @@ -121,12 +121,10 @@ public: bool MaySwapRows() const; bool MaySwapColumns() const; -// bool MaySortRow() const; -// bool MaySortColumn() const; - // mutators mutating data void InsertRow(); void InsertColumn(); + void InsertTextColumn(); void RemoveRow(); void RemoveColumn(); diff --git a/chart2/source/controller/dialogs/DataBrowserModel.cxx b/chart2/source/controller/dialogs/DataBrowserModel.cxx index decdda0f8793..c0b865536686 100644 --- a/chart2/source/controller/dialogs/DataBrowserModel.cxx +++ b/chart2/source/controller/dialogs/DataBrowserModel.cxx @@ -40,6 +40,7 @@ #include "ContainerHelper.hxx" #include "ChartTypeHelper.hxx" #include "chartview/ExplicitValueProvider.hxx" +#include "ExplicitCategoriesProvider.hxx" #include <com/sun/star/container/XIndexReplace.hpp> #include <com/sun/star/chart2/XDataSeriesContainer.hpp> @@ -51,6 +52,7 @@ #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> #include <com/sun/star/chart2/data/XTextualDataSequence.hpp> +#include <com/sun/star/util/XModifiable.hpp> #include <rtl/math.hxx> @@ -322,6 +324,9 @@ void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); if( xDataProvider.is()) { + if( isCategoriesColumn(nAfterColumnIndex) ) + nAfterColumnIndex = getCategoryColumnCount()-1; + sal_Int32 nStartCol = 0; Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument )); Reference< chart2::XChartType > xChartType; @@ -353,7 +358,7 @@ void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) { sal_Int32 nOffset = 0; if( xDiagram.is() && lcl_ShowCategories( xDiagram )) - ++nOffset; + nOffset=getCategoryColumnCount(); // get shared sequences of current series Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY ); lcl_tSharedSeqVec aSharedSequences; @@ -423,7 +428,31 @@ void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) } } -void DataBrowserModel::removeDataSeries( sal_Int32 nAtColumnIndex ) +void DataBrowserModel::insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex ) +{ + //create a new text column for complex categories + + OSL_ASSERT( m_apDialogModel.get()); + Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + if( xDataProvider.is() ) + { + if( !isCategoriesColumn(nAfterColumnIndex) ) + nAfterColumnIndex = getCategoryColumnCount()-1; + + if(nAfterColumnIndex<0) + { + OSL_ENSURE( false, "wrong index for category level insertion" ); + return; + } + + m_apDialogModel->startControllerLockTimer(); + ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); + xDataProvider->insertComplexCategoryLevel( nAfterColumnIndex+1 ); + updateFromModel(); + } +} + +void DataBrowserModel::removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex ) { OSL_ASSERT( m_apDialogModel.get()); if( static_cast< tDataColumnVector::size_type >( nAtColumnIndex ) < m_aColumns.size()) @@ -474,6 +503,20 @@ void DataBrowserModel::removeDataSeries( sal_Int32 nAtColumnIndex ) } updateFromModel(); } + else + { + //delete a category column if there is more than one level (in case of a single column we do not get here) + OSL_ENSURE(nAtColumnIndex>0, "wrong index for categories deletion" ); + + Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + if( xDataProvider.is() ) + { + m_apDialogModel->startControllerLockTimer(); + ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); + xDataProvider->deleteComplexCategoryLevel( nAtColumnIndex ); + updateFromModel(); + } + } } } @@ -614,6 +657,8 @@ bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const bResult = true; try { + ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); + // label if( nAtRow == -1 ) { @@ -627,6 +672,12 @@ bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY_THROW ); xIndexReplace->replaceByIndex( nAtRow, rValue ); } + + m_apDialogModel->startControllerLockTimer(); + //notify change directly to the model (this is necessary here as sequences for complex categories not known directly to the chart model so they do not notify their changes) (for complex categories see issue #i82971#) + Reference< util::XModifiable > xModifiable( m_xChartDocument, uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->setModified(true); } catch( const uno::Exception & ex ) { @@ -683,11 +734,26 @@ OUString DataBrowserModel::getRoleOfColumn( sal_Int32 nColumnIndex ) const return OUString(); } -Reference< chart2::data::XLabeledDataSequence > - DataBrowserModel::getCategories() const throw() +bool DataBrowserModel::isCategoriesColumn( sal_Int32 nColumnIndex ) const { - OSL_ASSERT( m_apDialogModel.get()); - return m_apDialogModel->getCategories(); + bool bIsCategories = false; + if( nColumnIndex>=0 && nColumnIndex<static_cast< sal_Int32 >(m_aColumns.size()) ) + bIsCategories = !m_aColumns[ nColumnIndex ].m_xDataSeries.is(); + return bIsCategories; +} + +sal_Int32 DataBrowserModel::getCategoryColumnCount() +{ + sal_Int32 nLastTextColumnIndex = -1; + tDataColumnVector::const_iterator aIt = m_aColumns.begin(); + for( ; aIt != m_aColumns.end(); ++aIt ) + { + if( !aIt->m_xDataSeries.is() ) + nLastTextColumnIndex++; + else + break; + } + return nLastTextColumnIndex+1; } const DataBrowserModel::tDataHeaderVector& DataBrowserModel::getDataHeaders() const @@ -717,16 +783,27 @@ void DataBrowserModel::updateFromModel() sal_Int32 nHeaderEnd = 0; if( lcl_ShowCategories( xDiagram )) { - Reference< chart2::data::XLabeledDataSequence > xCategories( this->getCategories()); - tDataColumn aCategories; - aCategories.m_xLabeledDataSequence.set( xCategories ); - if( lcl_ShowCategoriesAsDataLabel( xDiagram )) - aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel(); - else - aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories ); - aCategories.m_eCellType = TEXT; - m_aColumns.push_back( aCategories ); - ++nHeaderStart; + Reference< frame::XModel > xChartModel( m_xChartDocument, uno::UNO_QUERY ); + ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), xChartModel ); + + const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() ); + sal_Int32 nLevelCount = rSplitCategoriesList.getLength(); + for( sal_Int32 nL = 0; nL<nLevelCount; nL++ ) + { + Reference< chart2::data::XLabeledDataSequence > xCategories( rSplitCategoriesList[nL] ); + if( !xCategories.is() ) + continue; + + tDataColumn aCategories; + aCategories.m_xLabeledDataSequence.set( xCategories ); + if( lcl_ShowCategoriesAsDataLabel( xDiagram )) + aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel(); + else + aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories ); + aCategories.m_eCellType = TEXT; + m_aColumns.push_back( aCategories ); + ++nHeaderStart; + } } Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); diff --git a/chart2/source/controller/dialogs/DataBrowserModel.hxx b/chart2/source/controller/dialogs/DataBrowserModel.hxx index 5b6a6e41c01b..a4378972f70f 100644 --- a/chart2/source/controller/dialogs/DataBrowserModel.hxx +++ b/chart2/source/controller/dialogs/DataBrowserModel.hxx @@ -60,10 +60,14 @@ public: */ void insertDataSeries( sal_Int32 nAfterColumnIndex ); + /** Inserts a new text column for complex categories. + */ + void insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex ); + /** Removes a data series to which the data column with index nAtColumnIndex belongs. */ - void removeDataSeries( sal_Int32 nAtColumnIndex ); + void removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex ); /** Swaps the series to which the data column with index nFirstIndex belongs with the next series (which starts at an index >= nFirstIndex + 1) @@ -97,6 +101,7 @@ public: // returns the UI string of the corresponding role ::rtl::OUString getRoleOfColumn( sal_Int32 nColumnIndex ) const; + bool isCategoriesColumn( sal_Int32 nColumnIndex ) const; struct tDataHeader { @@ -153,9 +158,7 @@ private: sal_Int32 & rInOutSequenceIndex, sal_Int32 & rInOutHeaderEnd ); - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XLabeledDataSequence > - getCategories() const throw(); + sal_Int32 getCategoryColumnCount(); ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > m_xChartDocument; diff --git a/chart2/source/controller/dialogs/DialogModel.cxx b/chart2/source/controller/dialogs/DialogModel.cxx index a8d9288e381f..f104045727bb 100644 --- a/chart2/source/controller/dialogs/DialogModel.cxx +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -827,8 +827,6 @@ void DialogModel::applyInterpretedData( DialogModel::setCategories(rNewData.Categories); } - - OSL_ASSERT( ! rNewData.UnusedData.hasElements()); } sal_Int32 DialogModel::countSeries() const diff --git a/chart2/source/controller/dialogs/ObjectNameProvider.cxx b/chart2/source/controller/dialogs/ObjectNameProvider.cxx index a29e91457c93..0836ab9ca93a 100644 --- a/chart2/source/controller/dialogs/ObjectNameProvider.cxx +++ b/chart2/source/controller/dialogs/ObjectNameProvider.cxx @@ -46,8 +46,6 @@ #include <tools/debug.hxx> #include <tools/string.hxx> -// #include <unotools/syslocale.hxx> - #include <com/sun/star/chart2/XTitle.hpp> #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> @@ -197,7 +195,7 @@ OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal replaceParamterInString( aCategory , C2U("%CATEGORYVALUE") - , ExplicitCategoriesProvider::getCategoryByIndex( xCooSys, nPointIndex ) + , ExplicitCategoriesProvider::getCategoryByIndex( xCooSys, xChartModel, nPointIndex ) ); aRet = aCategory; diff --git a/chart2/source/controller/dialogs/dlg_DataEditor.cxx b/chart2/source/controller/dialogs/dlg_DataEditor.cxx index 41539df061b9..f1d441921a6a 100644 --- a/chart2/source/controller/dialogs/dlg_DataEditor.cxx +++ b/chart2/source/controller/dialogs/dlg_DataEditor.cxx @@ -144,34 +144,22 @@ IMPL_LINK( DataEditor, ToolboxHdl, void *, EMPTYARG ) break; case TBI_DATA_INSERT_COL: m_apBrwData->InsertColumn(); -// ImplAdjustHeaderControls( true /* bRefreshFromModel */ ); + break; + case TBI_DATA_INSERT_TEXT_COL: + m_apBrwData->InsertTextColumn(); break; case TBI_DATA_DELETE_ROW: m_apBrwData->RemoveRow(); break; case TBI_DATA_DELETE_COL: m_apBrwData->RemoveColumn(); -// ImplAdjustHeaderControls( true /* bRefreshFromModel */ ); break; case TBI_DATA_SWAP_COL : m_apBrwData->SwapColumn (); -// ImplAdjustHeaderControls( true /* bRefreshFromModel */ ); break; case TBI_DATA_SWAP_ROW : m_apBrwData->SwapRow (); break; -// case TBI_DATA_SORT_COL : -// m_apBrwData->QuickSortCol(); -// break; -// case TBI_DATA_SORT_ROW : -// m_apBrwData->QuickSortRow(); -// break; -// case TBI_DATA_SORT_TABLE_COL : -// m_apBrwData->QuickSortTableCols (); -// break; -// case TBI_DATA_SORT_TABLE_ROW : -// m_apBrwData->QuickSortTableRows (); -// break; } return 0; @@ -183,27 +171,16 @@ IMPL_LINK( DataEditor, BrowserCursorMovedHdl, void *, EMPTYARG ) if( m_bReadOnly ) return 0; - if( m_apBrwData->IsEnableItem() ) - { - m_aTbxData.EnableItem( TBI_DATA_INSERT_ROW, m_apBrwData->MayInsertRow() ); - m_aTbxData.EnableItem( TBI_DATA_INSERT_COL, m_apBrwData->MayInsertColumn() ); - m_aTbxData.EnableItem( TBI_DATA_DELETE_ROW, m_apBrwData->MayDeleteRow() ); - m_aTbxData.EnableItem( TBI_DATA_DELETE_COL, m_apBrwData->MayDeleteColumn() ); + bool bIsDataValid = m_apBrwData->IsEnableItem(); - m_aTbxData.EnableItem( TBI_DATA_SWAP_COL, m_apBrwData->MaySwapColumns() ); - m_aTbxData.EnableItem( TBI_DATA_SWAP_ROW, m_apBrwData->MaySwapRows() ); - } - else - { - m_aTbxData.EnableItem( TBI_DATA_INSERT_ROW, FALSE ); - m_aTbxData.EnableItem( TBI_DATA_INSERT_COL, FALSE ); - m_aTbxData.EnableItem( TBI_DATA_SWAP_COL, FALSE ); - m_aTbxData.EnableItem( TBI_DATA_SWAP_ROW, FALSE ); - } -// m_aTbxData.EnableItem( TBI_DATA_SORT_COL, m_apBrwData->MaySortColumn() ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_ROW, m_apBrwData->MaySortRow() ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_TABLE_COL, m_apBrwData->MaySortColumn() ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_TABLE_ROW, m_apBrwData->MaySortRow() ); + m_aTbxData.EnableItem( TBI_DATA_INSERT_ROW, bIsDataValid && m_apBrwData->MayInsertRow() ); + m_aTbxData.EnableItem( TBI_DATA_INSERT_COL, bIsDataValid && m_apBrwData->MayInsertColumn() ); + m_aTbxData.EnableItem( TBI_DATA_INSERT_TEXT_COL, bIsDataValid && m_apBrwData->MayInsertColumn() ); + m_aTbxData.EnableItem( TBI_DATA_DELETE_ROW, m_apBrwData->MayDeleteRow() ); + m_aTbxData.EnableItem( TBI_DATA_DELETE_COL, m_apBrwData->MayDeleteColumn() ); + + m_aTbxData.EnableItem( TBI_DATA_SWAP_COL, bIsDataValid && m_apBrwData->MaySwapColumns() ); + m_aTbxData.EnableItem( TBI_DATA_SWAP_ROW, bIsDataValid && m_apBrwData->MaySwapRows() ); return 0; } @@ -216,14 +193,11 @@ void DataEditor::SetReadOnly( bool bReadOnly ) { m_aTbxData.EnableItem( TBI_DATA_INSERT_ROW, FALSE ); m_aTbxData.EnableItem( TBI_DATA_INSERT_COL, FALSE ); + m_aTbxData.EnableItem( TBI_DATA_INSERT_TEXT_COL, FALSE ); m_aTbxData.EnableItem( TBI_DATA_DELETE_ROW, FALSE ); m_aTbxData.EnableItem( TBI_DATA_DELETE_COL, FALSE ); m_aTbxData.EnableItem( TBI_DATA_SWAP_COL, FALSE ); m_aTbxData.EnableItem( TBI_DATA_SWAP_ROW, FALSE ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_COL, FALSE ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_ROW, FALSE ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_TABLE_ROW, FALSE ); -// m_aTbxData.EnableItem( TBI_DATA_SORT_TABLE_COL, FALSE ); } m_apBrwData->SetReadOnly( m_bReadOnly ); diff --git a/chart2/source/controller/dialogs/dlg_DataEditor.hrc b/chart2/source/controller/dialogs/dlg_DataEditor.hrc index 8673f5e8cf80..d2675c5bb29e 100644 --- a/chart2/source/controller/dialogs/dlg_DataEditor.hrc +++ b/chart2/source/controller/dialogs/dlg_DataEditor.hrc @@ -33,19 +33,14 @@ #define CTL_DATA 1 // images for toolbox image list +//the numbers correspond to the icon names: default_images\chart2\res\dataeditor_icon_xy #define TBI_DATA_INSERT_ROW 1 #define TBI_DATA_INSERT_COL 2 #define TBI_DATA_DELETE_ROW 3 #define TBI_DATA_DELETE_COL 4 #define TBI_DATA_SWAP_COL 5 #define TBI_DATA_SWAP_ROW 6 -#define TBI_DATA_TRANSFER 7 - -// #define TBI_DATA_SORT_ROW 7 -// #define TBI_DATA_SORT_COL 8 -// #define TBI_DATA_SORT_TABLE_ROW 9 -// #define TBI_DATA_SORT_TABLE_COL 10 -// #define TBI_DATA_TRANSFER 11 +#define TBI_DATA_INSERT_TEXT_COL 7 // image lists (normal and high-contrast) for toolbox #define IL_DIAGRAM_DATA 1 diff --git a/chart2/source/controller/dialogs/dlg_DataEditor.src b/chart2/source/controller/dialogs/dlg_DataEditor.src index ce774e8f5bd2..dadd1ac3098d 100644 --- a/chart2/source/controller/dialogs/dlg_DataEditor.src +++ b/chart2/source/controller/dialogs/dlg_DataEditor.src @@ -80,6 +80,12 @@ ModalDialog DLG_DIAGRAM_DATA }; ToolBoxItem { + HelpID = HID_SCH_TBI_DATA_INSERT_TEXT_COL ; + Identifier = TBI_DATA_INSERT_TEXT_COL ; + Text [ en-US ] = "Insert Text Column" ; + }; + ToolBoxItem + { HelpID = HID_SCH_TBI_DATA_DELETE_ROW ; Identifier = TBI_DATA_DELETE_ROW ; Text [ en-US ] = "Delete Row" ; @@ -118,11 +124,11 @@ ModalDialog DLG_DIAGRAM_DATA { \ TBI_DATA_INSERT_ROW; \ TBI_DATA_INSERT_COL; \ + TBI_DATA_INSERT_TEXT_COL; \ TBI_DATA_DELETE_ROW; \ TBI_DATA_DELETE_COL; \ TBI_DATA_SWAP_COL; \ TBI_DATA_SWAP_ROW; \ - TBI_DATA_TRANSFER; \ }; \ IdCount = { 7; } diff --git a/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx index 285464dc90ff..2a41d35313e8 100644 --- a/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx +++ b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx @@ -204,7 +204,7 @@ void ObjectPropertiesDialogParameter::init( const uno::Reference< frame::XModel ScaleData aScale( xCrossingMainAxis->getScaleData() ); m_bIsCrossingAxisIsCategoryAxis = ( chart2::AxisType::CATEGORY == aScale.AxisType ); if( m_bIsCrossingAxisIsCategoryAxis ) - m_aCategories = DiagramHelper::generateAutomaticCategories( Reference< chart2::XChartDocument >( xChartModel, uno::UNO_QUERY) ); + m_aCategories = DiagramHelper::getExplicitSimpleCategories( Reference< chart2::XChartDocument >( xChartModel, uno::UNO_QUERY) ); } } } diff --git a/chart2/source/controller/inc/HelpIds.hrc b/chart2/source/controller/inc/HelpIds.hrc index 88cd1619bab8..1052b7ea962f 100644 --- a/chart2/source/controller/inc/HelpIds.hrc +++ b/chart2/source/controller/inc/HelpIds.hrc @@ -29,6 +29,7 @@ #include <svl/solar.hrc> //next is 120 +//free: 20, 21, 22, 30, 31, 32, 33 //see old chart: schhids.h @@ -61,21 +62,13 @@ //#define HID_SCH_CT_INDICATE2 (HID_SCH_START + 18) //#define HID_SCH_CT_REGRESS2 (HID_SCH_START + 19) -//#define HID_SCH_TBI_EDIT_CANCEL (HID_SCH_START + 20) -//#define HID_SCH_TBI_EDIT_ACCEPT (HID_SCH_START + 21) -#define HID_SCH_TBI_DATA_TRANSFER (HID_SCH_START + 22) #define HID_SCH_TBI_DATA_INSERT_ROW (HID_SCH_START + 23) #define HID_SCH_TBI_DATA_INSERT_COL (HID_SCH_START + 24) #define HID_SCH_TBI_DATA_DELETE_ROW (HID_SCH_START + 25) #define HID_SCH_TBI_DATA_DELETE_COL (HID_SCH_START + 26) #define HID_SCH_TBI_DATA_SWAP_COL (HID_SCH_START + 27) #define HID_SCH_TBI_DATA_SWAP_ROW (HID_SCH_START + 28) -//#define HID_SCH_TBI_DATA_SORT_ROW (HID_SCH_START + 29) -//#define HID_SCH_TBI_DATA_SORT_COL (HID_SCH_START + 30) -//#define HID_SCH_TBI_DATA_SORT_TABLE_ROW (HID_SCH_START + 31) -//#define HID_SCH_TBI_DATA_SORT_TABLE_COL (HID_SCH_START + 32) - -// #define HID_SCH_TBX_EDIT (HID_SCH_START + 33) +#define HID_SCH_TBI_DATA_INSERT_TEXT_COL (HID_SCH_START + 29) #define HID_SCH_TBX_DATA (HID_SCH_START + 34) #define HID_SCH_ALIGNMENT_CTR_DIAL (HID_SCH_START + 35) diff --git a/chart2/source/controller/main/ImplUndoManager.cxx b/chart2/source/controller/main/ImplUndoManager.cxx index 5af76f2bd781..57e8e7315334 100644 --- a/chart2/source/controller/main/ImplUndoManager.cxx +++ b/chart2/source/controller/main/ImplUndoManager.cxx @@ -36,7 +36,7 @@ #include "DataSourceHelper.hxx" #include "ChartModelHelper.hxx" -#include <com/sun/star/chart/XChartDataArray.hpp> +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/XInternalDataProvider.hpp> #include <com/sun/star/chart2/XTitled.hpp> @@ -52,7 +52,7 @@ using namespace ::com::sun::star; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::rtl::OUString; -using ::com::sun::star::chart::XChartDataArray; +using ::com::sun::star::chart::XComplexDescriptionAccess; namespace chart { @@ -69,13 +69,13 @@ void ImplApplyDataToModel( // copy data from stored internal data provider if( xDoc.is() && xDoc->hasInternalDataProvider()) { - Reference< XChartDataArray > xCurrentData( xDoc->getDataProvider(), uno::UNO_QUERY ); - Reference< XChartDataArray > xSavedData( xData, uno::UNO_QUERY ); + Reference< XComplexDescriptionAccess > xCurrentData( xDoc->getDataProvider(), uno::UNO_QUERY ); + Reference< XComplexDescriptionAccess > xSavedData( xData, uno::UNO_QUERY ); if( xCurrentData.is() && xSavedData.is()) { xCurrentData->setData( xSavedData->getData()); - xCurrentData->setRowDescriptions( xSavedData->getRowDescriptions()); - xCurrentData->setColumnDescriptions( xSavedData->getColumnDescriptions()); + xCurrentData->setComplexRowDescriptions( xSavedData->getComplexRowDescriptions()); + xCurrentData->setComplexColumnDescriptions( xSavedData->getComplexColumnDescriptions()); } } } diff --git a/chart2/source/inc/ChartModelHelper.hxx b/chart2/source/inc/ChartModelHelper.hxx index bdeab6736044..7cd205b83fb5 100644 --- a/chart2/source/inc/ChartModelHelper.hxx +++ b/chart2/source/inc/ChartModelHelper.hxx @@ -34,7 +34,6 @@ #include <com/sun/star/chart2/XUndoManager.hpp> #include <com/sun/star/chart2/data/XDataProvider.hpp> #include <com/sun/star/chart2/data/XRangeHighlighter.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> #include <com/sun/star/view/XSelectionSupplier.hpp> #include <com/sun/star/awt/Size.hpp> @@ -58,13 +57,8 @@ public: static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XRangeHighlighter > createRangeHighlighter( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionSupplier >& xSelectionSupplier ); - static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > createInternalDataProvider(); - - static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > createInternalDataProvider( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart::XChartDataArray >& xDataToCopy ); - static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > createInternalDataProvider( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDoc ); + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDoc, bool bConnectToModel ); static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDiagram > @@ -74,6 +68,10 @@ public: ::com::sun::star::chart2::XDiagram > findDiagram( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDoc ); + static ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XCoordinateSystem > + getFirstCoordinateSystem( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel ); + SAL_DLLPRIVATE static ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries > > getDataSeries( const ::com::sun::star::uno::Reference< diff --git a/chart2/source/inc/CloneHelper.hxx b/chart2/source/inc/CloneHelper.hxx index c78abe32da59..6747bd614d84 100644 --- a/chart2/source/inc/CloneHelper.hxx +++ b/chart2/source/inc/CloneHelper.hxx @@ -29,6 +29,7 @@ #include <com/sun/star/util/XCloneable.hpp> +#include <map> #include <functional> #include <algorithm> diff --git a/chart2/source/inc/DataSourceHelper.hxx b/chart2/source/inc/DataSourceHelper.hxx index efb69df7f2b5..06888fe858d6 100644 --- a/chart2/source/inc/DataSourceHelper.hxx +++ b/chart2/source/inc/DataSourceHelper.hxx @@ -111,14 +111,12 @@ public: static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > getUsedData( const ::com::sun::star::uno::Reference< - ::com::sun::star::frame::XModel >& xChartModel, - bool bIncludeUnusedData = false ); + ::com::sun::star::frame::XModel >& xChartModel ); static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > getUsedData( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XChartDocument >& xChartDoc, - bool bIncludeUnusedData = false ); + ::com::sun::star::chart2::XChartDocument >& xChartDoc ); static bool detectRangeSegmentation( const ::com::sun::star::uno::Reference< @@ -127,8 +125,7 @@ public: , ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping , bool& rOutUseColumns , bool& rOutFirstCellAsLabel - , bool& rOutHasCategories - , bool bIncludeUnusedData = false ); + , bool& rOutHasCategories ); static void setRangeSegmentation( const ::com::sun::star::uno::Reference< @@ -152,6 +149,10 @@ public: const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XLabeledDataSequence > & xLSeq ); + SAL_DLLPRIVATE static ::rtl::OUString getRangeFromValues( + const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence > & xLSeq ); + SAL_DLLPRIVATE static ::com::sun::star::uno::Sequence< ::rtl::OUString > getRangesFromDataSource( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > & xSource ); diff --git a/chart2/source/inc/DiagramHelper.hxx b/chart2/source/inc/DiagramHelper.hxx index fe412366606b..c685b99b974f 100644 --- a/chart2/source/inc/DiagramHelper.hxx +++ b/chart2/source/inc/DiagramHelper.hxx @@ -223,19 +223,15 @@ public: ::com::sun::star::chart2::XDiagram > & xDiagram ); static ::com::sun::star::uno::Sequence< rtl::OUString > - generateAutomaticCategories( + getExplicitSimpleCategories( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > & xChartDoc ); SAL_DLLPRIVATE static ::com::sun::star::uno::Sequence< rtl::OUString > - generateAutomaticCategories( + generateAutomaticCategoriesFromCooSys( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XCoordinateSystem > & xCooSys ); - SAL_DLLPRIVATE static void generateAutomaticCategoriesFromChartType( - ::com::sun::star::uno::Sequence< rtl::OUString >& rRet, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType ); - static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType > getChartTypeByIndex( const ::com::sun::star::uno::Reference< diff --git a/chart2/source/inc/ExplicitCategoriesProvider.hxx b/chart2/source/inc/ExplicitCategoriesProvider.hxx index 8195ae0d92f2..18d54eb6e2ad 100644 --- a/chart2/source/inc/ExplicitCategoriesProvider.hxx +++ b/chart2/source/inc/ExplicitCategoriesProvider.hxx @@ -35,36 +35,71 @@ #include <com/sun/star/frame/XModel.hpp> #include "charttoolsdllapi.hxx" +#include <vector> + namespace chart { -class OOO_DLLPUBLIC_CHARTTOOLS ExplicitCategoriesProvider : - public ::cppu::WeakImplHelper1< - ::com::sun::star::chart2::data::XTextualDataSequence - > +struct OOO_DLLPUBLIC_CHARTTOOLS ComplexCategory +{ + rtl::OUString Text; + sal_Int32 Count; + + ComplexCategory( const rtl::OUString& rText, sal_Int32 nCount ) : Text( rText ), Count (nCount) + {} +}; + +class OOO_DLLPUBLIC_CHARTTOOLS SplitCategoriesProvider +{ +public: + virtual ~SplitCategoriesProvider(); + + virtual sal_Int32 getLevelCount() const = 0; + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const = 0; +}; + +class OOO_DLLPUBLIC_CHARTTOOLS ExplicitCategoriesProvider { public: ExplicitCategoriesProvider( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XCoordinateSystem >& xCooSysModel ); - SAL_DLLPRIVATE virtual ~ExplicitCategoriesProvider(); + ::com::sun::star::chart2::XCoordinateSystem >& xCooSysModel + , const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel >& xChartModel + ); + virtual ~ExplicitCategoriesProvider(); + + void init(); - //XTextualDataSequence - SAL_DLLPRIVATE virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getTextualData() - throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< ::rtl::OUString > getSimpleCategories(); + ::std::vector< ComplexCategory > getCategoriesByLevel( sal_Int32 nLevel ); static ::rtl::OUString getCategoryByIndex( - const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XCoordinateSystem >& xCooSysModel, - sal_Int32 nIndex ); + const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XCoordinateSystem >& xCooSysModel + , const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel >& xChartModel + , sal_Int32 nIndex ); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getExplicitSimpleCategories( + const SplitCategoriesProvider& rSplitCategoriesProvider ); + + bool hasComplexCategories() const; + sal_Int32 getCategoryLevelCount() const; + + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence> >& getSplitCategoriesList(); private: //member - ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aExplicitCategories; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aExplicitCategories; + ::std::vector< ::std::vector< ComplexCategory > > m_aComplexCats; bool volatile m_bDirty; ::com::sun::star::uno::WeakReference< ::com::sun::star::chart2::XCoordinateSystem > m_xCooSysModel; ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XLabeledDataSequence> m_xCategories; + ::com::sun::star::chart2::data::XLabeledDataSequence> m_xOriginalCategories; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence> > m_aSplitCategoriesList; }; } // namespace chart diff --git a/chart2/source/inc/InternalData.hxx b/chart2/source/inc/InternalData.hxx new file mode 100755 index 000000000000..6b6590cffdac --- /dev/null +++ b/chart2/source/inc/InternalData.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_INTERNALDATA_HXX +#define CHART2_INTERNALDATA_HXX + +#include <com/sun/star/uno/Sequence.hxx> + +#include <vector> +#include <valarray> + +namespace chart +{ + +class InternalData +{ +public: + InternalData(); + + void createDefaultData(); + + void setData( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< double > > & rDataInRows ); + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< double > > getData() const; + + ::com::sun::star::uno::Sequence< double > getColumnValues( sal_Int32 nColumnIndex ) const; + ::com::sun::star::uno::Sequence< double > getRowValues( sal_Int32 nRowIndex ) const; + + void setColumnValues( sal_Int32 nColumnIndex, const ::std::vector< double > & rNewData ); + void setRowValues( sal_Int32 nRowIndex, const ::std::vector< double > & rNewData ); + + void setComplexColumnLabel( sal_Int32 nColumnIndex, const ::std::vector< ::rtl::OUString >& rComplexLabel ); + void setComplexRowLabel( sal_Int32 nRowIndex, const ::std::vector< ::rtl::OUString >& rComplexLabel ); + + ::std::vector< ::rtl::OUString > getComplexColumnLabel( sal_Int32 nColumnIndex ) const; + ::std::vector< ::rtl::OUString > getComplexRowLabel( sal_Int32 nRowIndex ) const; + + void swapRowWithNext( sal_Int32 nRowIndex ); + void swapColumnWithNext( sal_Int32 nColumnIndex ); + + void insertColumn( sal_Int32 nAfterIndex ); + void insertRow( sal_Int32 nAfterIndex ); + void deleteColumn( sal_Int32 nAtIndex ); + void deleteRow( sal_Int32 nAtIndex ); + + /// @return the index of the newly appended column + sal_Int32 appendColumn(); + /// @return the index of the newly appended row + sal_Int32 appendRow(); + + sal_Int32 getRowCount() const; + sal_Int32 getColumnCount() const; + + typedef ::std::valarray< double > tDataType; + typedef ::std::vector< ::std::vector< ::rtl::OUString > > tVecVecString; //inner index is hierarchical level + + void setComplexRowLabels( const tVecVecString& rNewRowLabels ); + tVecVecString getComplexRowLabels() const; + void setComplexColumnLabels( const tVecVecString& rNewColumnLabels ); + tVecVecString getComplexColumnLabels() const; + +#if OSL_DEBUG_LEVEL > 2 + void traceData() const; +#endif + +private: //methods + /** resizes the data if at least one of the given dimensions is larger than + before. The data is never becoming smaller only larger. + + @return </TRUE>, if the data was enlarged + */ + bool enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ); + +private: + sal_Int32 m_nColumnCount; + sal_Int32 m_nRowCount; + + tDataType m_aData; + tVecVecString m_aRowLabels;//outer index is row index, inner index is category level + tVecVecString m_aColumnLabels;//outer index is column index +}; + +#endif + +} // namespace chart diff --git a/chart2/source/inc/InternalDataProvider.hxx b/chart2/source/inc/InternalDataProvider.hxx index 9100b32d5859..f5e12f87f505 100644 --- a/chart2/source/inc/InternalDataProvider.hxx +++ b/chart2/source/inc/InternalDataProvider.hxx @@ -27,8 +27,10 @@ #ifndef CHART2_INTERNALDATAPROVIDER_HXX #define CHART2_INTERNALDATAPROVIDER_HXX +#include "InternalData.hxx" + #include <com/sun/star/lang/XServiceInfo.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> #include <com/sun/star/chart2/data/XDataProvider.hpp> #include <com/sun/star/chart2/XInternalDataProvider.hpp> #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> @@ -49,12 +51,11 @@ namespace chart namespace impl { -class InternalData; typedef ::cppu::WeakImplHelper6< ::com::sun::star::chart2::XInternalDataProvider, ::com::sun::star::chart2::data::XRangeXMLConversion, - ::com::sun::star::chart::XChartDataArray, + ::com::sun::star::chart::XComplexDescriptionAccess, ::com::sun::star::util::XCloneable, ::com::sun::star::lang::XInitialization, ::com::sun::star::lang::XServiceInfo > @@ -75,16 +76,9 @@ class InternalDataProvider : public impl::InternalDataProvider_Base { public: - explicit InternalDataProvider(); explicit InternalDataProvider(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & _xContext); - /// sets the internal data to the given data - explicit InternalDataProvider( - const ::com::sun::star::uno::Reference< - ::com::sun::star::chart::XChartDataArray > & xDataToCopy ); - /// copies the data from the given data provider for all given used ranges explicit InternalDataProvider( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XChartDocument > & xChartDoc ); - // copy-CTOR + ::com::sun::star::chart2::XChartDocument > & xChartDoc, bool bConnectToModel ); explicit InternalDataProvider( const InternalDataProvider & rOther ); virtual ~InternalDataProvider(); @@ -110,6 +104,10 @@ public: throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL appendSequence() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertComplexCategoryLevel( ::sal_Int32 nLevel ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteComplexCategoryLevel( ::sal_Int32 nLevel ) + throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL insertDataPointForAllSequences( ::sal_Int32 nAfterIndex ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL deleteDataPointForAllSequences( ::sal_Int32 nAtIndex ) @@ -151,7 +149,21 @@ public: throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); - // ____ XChartDataArray ____ + // ____ XComplexDescriptionAccess ____ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > > SAL_CALL + getComplexRowDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setComplexRowDescriptions( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< ::rtl::OUString > >& aRowDescriptions ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > > SAL_CALL + getComplexColumnDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setComplexColumnDescriptions( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< ::rtl::OUString > >& aColumnDescriptions ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XChartDataArray (base of XComplexDescriptionAccess) ____ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > > SAL_CALL getData() throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL setData( @@ -189,29 +201,27 @@ public: throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::uno::Exception); private: - impl::InternalData & getInternalData(); - const impl::InternalData & getInternalData() const; - - void addDataSequenceToMap( + void lcl_addDataSequenceToMap( const ::rtl::OUString & rRangeRepresentation, const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > & xSequence ); + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > - createDataSequenceAndAddToMap( const ::rtl::OUString & rRangeRepresentation, + lcl_createDataSequenceAndAddToMap( const ::rtl::OUString & rRangeRepresentation, const ::rtl::OUString & rRole ); ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > - createDataSequenceAndAddToMap( const ::rtl::OUString & rRangeRepresentation ); - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSequence > - createErrorBarDataSequenceAndAddToMap( const ::rtl::OUString & rRangeRepresentation ); - void deleteMapReferences( const ::rtl::OUString & rRangeRepresentation ); - void adaptMapReferences( + lcl_createDataSequenceAndAddToMap( const ::rtl::OUString & rRangeRepresentation ); + + void lcl_deleteMapReferences( const ::rtl::OUString & rRangeRepresentation ); + + void lcl_adaptMapReferences( const ::rtl::OUString & rOldRangeRepresentation, const ::rtl::OUString & rNewRangeRepresentation ); - void increaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd ); - void decreaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd ); + + void lcl_increaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd ); + void lcl_decreaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd ); typedef ::std::multimap< ::rtl::OUString, ::com::sun::star::uno::WeakReference< ::com::sun::star::chart2::data::XDataSequence > > @@ -225,14 +235,9 @@ private: referred to by some component (weak reference is valid), the range will be adapted. */ - mutable tSequenceMap m_aSequenceMap; - mutable ::std::auto_ptr< impl::InternalData > m_apData; + tSequenceMap m_aSequenceMap; + InternalData m_aInternalData; bool m_bDataInColumns; - -// typedef ::std::map< ::rtl::OUString, -// ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > -// tHardRefSequenceMap; -// tHardRefSequenceMap m_aErrorBarSequences; }; } // namespace chart diff --git a/chart2/source/model/inc/Diagram.hxx b/chart2/source/model/inc/Diagram.hxx index bf888775f337..fc672e29b24c 100644 --- a/chart2/source/model/inc/Diagram.hxx +++ b/chart2/source/model/inc/Diagram.hxx @@ -136,11 +136,6 @@ protected: virtual void SAL_CALL setDefaultColorScheme( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XColorScheme >& xColorScheme ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setUnusedData( - const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XLabeledDataSequence > >& aUnusedData ) - throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XLabeledDataSequence > > SAL_CALL getUnusedData() - throw (::com::sun::star::uno::RuntimeException); // ____ XCoordinateSystemContainer ____ @@ -237,11 +232,6 @@ private: ::com::sun::star::chart2::XColorScheme > m_xColorScheme; - ::com::sun::star::uno::Sequence< - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XLabeledDataSequence > > - m_aUnusedData; - ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > m_xModifyEventForwarder; }; diff --git a/chart2/source/model/main/ChartData.cxx b/chart2/source/model/main/ChartData.cxx deleted file mode 100644 index 866d4c67e885..000000000000 --- a/chart2/source/model/main/ChartData.cxx +++ /dev/null @@ -1,104 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_chart2.hxx" - -#include "ChartData.hxx" -#include "ChartModelHelper.hxx" - -#include <com/sun/star/lang/XInitialization.hpp> -#include <com/sun/star/beans/NamedValue.hpp> - -using namespace ::com::sun::star; - -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; -using ::rtl::OUString; - -namespace chart -{ - -ChartData::ChartData( const Reference< uno::XComponentContext > & xContext ) : - m_xContext( xContext ), - m_xDataProvider( 0 ), - m_xInternalDataProvider( 0 ) -{} - -ChartData::~ChartData() -{} - -void ChartData::setDataProvider( - const Reference< chart2::data::XDataProvider > & xDataProvider ) throw() -{ - m_xDataProvider.set( xDataProvider ); - m_xInternalDataProvider.clear(); -} - -Reference< chart2::data::XDataProvider > ChartData::getDataProvider() const throw() -{ - return m_xDataProvider; -} - -bool ChartData::createInternalData( - bool bCloneOldData, const Reference< chart2::XChartDocument > & xChartDoc ) throw() -{ - if( hasInternalData() ) - return false; - - if( bCloneOldData ) - m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( xChartDoc ); - else - m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider(); - - m_xDataProvider.set( m_xInternalDataProvider ); - return true; -} - -bool ChartData::hasInternalData() const -{ - return (m_xDataProvider.is() && m_xInternalDataProvider.is()); -} - -bool ChartData::createDefaultData() throw() -{ - if( hasInternalData() ) - { - uno::Reference< lang::XInitialization > xIni(m_xInternalDataProvider,uno::UNO_QUERY); - if ( xIni.is() ) - { - uno::Sequence< uno::Any > aArgs(1); - beans::NamedValue aParam(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),uno::makeAny(sal_True)); - aArgs[0] <<= aParam; - xIni->initialize(aArgs); - return true; - } - } - return false; -} - -} // namespace chart diff --git a/chart2/source/model/main/ChartData.hxx b/chart2/source/model/main/ChartData.hxx deleted file mode 100644 index c2a528bc89d7..000000000000 --- a/chart2/source/model/main/ChartData.hxx +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef CHART2_CHARTDATA_HXX -#define CHART2_CHARTDATA_HXX - -#include <com/sun/star/uno/Reference.hxx> -#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> -#include <com/sun/star/chart2/XChartDocument.hpp> - -#include <memory> - -namespace com { namespace sun { namespace star { - namespace uno { - class XComponentContext; - } - namespace embed { - class XStorage; - class XEmbeddedObject; - class XEmbeddedClient; - } - namespace chart2 { - namespace data { - class XDataProvider; - } - } - namespace util { - class XCloseBroadcaster; - } -}}} - -namespace chart -{ - -class ChartData -{ -public: - explicit ChartData( - const ::com::sun::star::uno::Reference< - ::com::sun::star::uno::XComponentContext > & xContext ); - ~ChartData(); - - void setDataProvider( - const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataProvider > & xDataProvider ) throw(); - - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > - getDataProvider() const throw(); - - /** @return </TRUE>, if a new internal data provider has been created - */ - bool createInternalData( - bool bCloneOldData, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > & xChartDoc ) throw(); - - bool hasInternalData() const; - - /** only works if currently an internal data provider is set - */ - bool createDefaultData() throw(); - -private: - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > - m_xContext; - - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > - m_xDataProvider; - - /** is only valid if m_xDataProvider is set. If m_xDataProvider is set to an - external data provider this reference must be set to 0 - */ - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > - m_xInternalDataProvider; -}; - -} // namespace chart - -// CHART2_CHARTDATA_HXX -#endif diff --git a/chart2/source/model/main/ChartModel.cxx b/chart2/source/model/main/ChartModel.cxx index 4eedac67f713..77533ec1306b 100644..100755 --- a/chart2/source/model/main/ChartModel.cxx +++ b/chart2/source/model/main/ChartModel.cxx @@ -28,19 +28,22 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_chart2.hxx" #include "ChartModel.hxx" -#include "ImplChartModel.hxx" #include "servicenames.hxx" #include "MediaDescriptorHelper.hxx" #include "macros.hxx" -#include "InternalData.hxx" #include "servicenames.hxx" -#include "DataSourceHelper.hxx" #include "NoWarningThisInCTOR.hxx" +#include "DataSourceHelper.hxx" #include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" #include "DisposeHelper.hxx" #include "ControllerLockGuard.hxx" #include "ObjectIdentifier.hxx" -#include "ChartModelHelper.hxx" +#include "PageBackground.hxx" +#include "CloneHelper.hxx" +#include "NameContainer.hxx" + +#include <com/sun/star/chart/ChartDataRowSource.hpp> #include <comphelper/InlineContainer.hxx> #include <comphelper/processfactory.hxx> @@ -57,13 +60,16 @@ #include <com/sun/star/embed/XStorage.hpp> #include <com/sun/star/embed/EmbedMapUnits.hpp> #include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/awt/Gradient.hpp> #include <com/sun/star/awt/XWindow.hpp> #include <com/sun/star/awt/PosSize.hpp> #include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/drawing/Hatch.hpp> +#include <com/sun/star/drawing/LineDash.hpp> #include <com/sun/star/drawing/XShapes.hpp> -#include <map> -#include <algorithm> +// header for class SvNumberFormatter +#include <svl/zforlist.hxx> using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; @@ -73,6 +79,7 @@ using ::osl::MutexGuard; using namespace ::com::sun::star; using namespace ::apphelper; +using namespace ::chart::CloneHelper; namespace { @@ -101,14 +108,22 @@ ChartModel::ChartModel(uno::Reference<uno::XComponentContext > const & xContext) , m_xContext( xContext ) // default visual area is 8 x 7 cm , m_aVisualAreaSize( 8000, 7000 ) + , m_xDataProvider( 0 ) + , m_xInternalDataProvider( 0 ) + , m_xPageBackground( new PageBackground( m_xContext ) ) + , m_xXMLNamespaceMap( createNameContainer( ::getCppuType( (const OUString*) 0 ), + C2U( "com.sun.star.xml.NamespaceMap" ), C2U( "com.sun.star.comp.chart.XMLNameSpaceMap" ) ), uno::UNO_QUERY) { OSL_TRACE( "ChartModel: CTOR called" ); + osl_incrementInterlockedCount(&m_refCount); - // attention: passing this as reference to ImplChartModel - m_pImplChartModel.reset( new impl::ImplChartModel( xContext, this )); - + ModifyListenerHelper::addListener( m_xPageBackground, this ); + m_xChartTypeManager.set( xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.chart2.ChartTypeManager" ), m_xContext ), uno::UNO_QUERY ); m_xUndoManager = Reference< chart2::XUndoManager >( this->createInstance( CHART_UNDOMANAGER_SERVICE_NAME ), uno::UNO_QUERY ); + + osl_decrementInterlockedCount(&m_refCount); } ChartModel::ChartModel( const ChartModel & rOther ) @@ -129,15 +144,23 @@ ChartModel::ChartModel( const ChartModel & rOther ) , m_xStorage( 0 ) //rOther.m_xStorage ) , m_aVisualAreaSize( rOther.m_aVisualAreaSize ) , m_aGraphicObjectVector( rOther.m_aGraphicObjectVector ) + , m_xDataProvider( rOther.m_xDataProvider ) + , m_xInternalDataProvider( rOther.m_xInternalDataProvider ) , m_xUndoManager( rOther.m_xUndoManager ) { OSL_TRACE( "ChartModel: Copy-CTOR called" ); + osl_incrementInterlockedCount(&m_refCount); - // attention: passing this as reference to ImplChartModel - if( rOther.m_pImplChartModel.get()) - m_pImplChartModel.reset( new impl::ImplChartModel( * rOther.m_pImplChartModel.get(), this )); - else - m_pImplChartModel.reset( new impl::ImplChartModel( m_xContext, this )); + m_xChartTypeManager.set( CreateRefClone< Reference< chart2::XChartTypeManager > >()( rOther.m_xChartTypeManager )); + m_xTitle.set( CreateRefClone< Reference< chart2::XTitle > >()( rOther.m_xTitle )); + ModifyListenerHelper::addListener( m_xTitle, this ); + m_xPageBackground.set( CreateRefClone< Reference< beans::XPropertySet > >()( rOther.m_xPageBackground )); + ModifyListenerHelper::addListener( m_xPageBackground, this ); + + m_xXMLNamespaceMap.set( CreateRefClone< Reference< container::XNameAccess > >()( rOther.m_xXMLNamespaceMap )); + + CloneRefVector< Reference< chart2::XDiagram > >( rOther.m_aDiagrams, m_aDiagrams ); + osl_decrementInterlockedCount(&m_refCount); } ChartModel::~ChartModel() @@ -152,8 +175,7 @@ ChartModel::~ChartModel() // private methods //----------------------------------------------------------------- - ::rtl::OUString ChartModel -::impl_g_getLocation() +::rtl::OUString ChartModel::impl_g_getLocation() { LifeTimeGuard aGuard(m_aLifeTimeManager); @@ -163,8 +185,7 @@ ChartModel::~ChartModel() return m_aResource; } - sal_Bool ChartModel -::impl_isControllerConnected( const uno::Reference< frame::XController >& xController ) +sal_Bool ChartModel::impl_isControllerConnected( const uno::Reference< frame::XController >& xController ) { try { @@ -181,8 +202,7 @@ ChartModel::~ChartModel() return sal_False; } - uno::Reference< frame::XController > ChartModel -::impl_getCurrentController() throw(uno::RuntimeException) +uno::Reference< frame::XController > ChartModel::impl_getCurrentController() throw(uno::RuntimeException) { //@todo? hold only weak references to controllers @@ -201,8 +221,7 @@ ChartModel::~ChartModel() return uno::Reference< frame::XController > (); } - void SAL_CALL ChartModel -::impl_notifyCloseListeners() +void SAL_CALL ChartModel::impl_notifyCloseListeners() throw( uno::RuntimeException) { ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer @@ -259,8 +278,7 @@ void ChartModel::impl_adjustAdditionalShapesPositionAndSize( const awt::Size& aV APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) - uno::Sequence< rtl::OUString > ChartModel -::getSupportedServiceNames_Static() +uno::Sequence< rtl::OUString > ChartModel::getSupportedServiceNames_Static() { uno::Sequence< rtl::OUString > aSNS( 3 ); aSNS[0] = CHART_MODEL_SERVICE_NAME; @@ -274,8 +292,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) // frame::XModel (required interface) //----------------------------------------------------------------- - sal_Bool SAL_CALL ChartModel -::attachResource( const ::rtl::OUString& rURL +sal_Bool SAL_CALL ChartModel::attachResource( const ::rtl::OUString& rURL , const uno::Sequence< beans::PropertyValue >& rMediaDescriptor ) throw(uno::RuntimeException) { @@ -301,14 +318,12 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) return sal_True; } - ::rtl::OUString SAL_CALL ChartModel -::getURL() throw(uno::RuntimeException) +::rtl::OUString SAL_CALL ChartModel::getURL() throw(uno::RuntimeException) { return impl_g_getLocation(); } - uno::Sequence< beans::PropertyValue > SAL_CALL ChartModel -::getArgs() throw(uno::RuntimeException) +uno::Sequence< beans::PropertyValue > SAL_CALL ChartModel::getArgs() throw(uno::RuntimeException) { /* The method getArgs() returns a sequence of property values @@ -324,8 +339,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) return m_aMediaDescriptor; } - void SAL_CALL ChartModel -::connectController( const uno::Reference< frame::XController >& xController ) +void SAL_CALL ChartModel::connectController( const uno::Reference< frame::XController >& xController ) throw(uno::RuntimeException) { //@todo? this method is declared as oneway -> ...? @@ -339,8 +353,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) m_aControllers.addInterface(xController); } - void SAL_CALL ChartModel -::disconnectController( const uno::Reference< frame::XController >& xController ) +void SAL_CALL ChartModel::disconnectController( const uno::Reference< frame::XController >& xController ) throw(uno::RuntimeException) { //@todo? this method is declared as oneway -> ...? @@ -359,8 +372,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); } - void SAL_CALL ChartModel -::lockControllers() throw(uno::RuntimeException) +void SAL_CALL ChartModel::lockControllers() throw(uno::RuntimeException) { /* suspends some notifications to the controllers which are used for display updates. @@ -378,8 +390,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) ++m_nControllerLockCount; } - void SAL_CALL ChartModel -::unlockControllers() throw(uno::RuntimeException) +void SAL_CALL ChartModel::unlockControllers() throw(uno::RuntimeException) { /* resumes the notifications which were suspended by lockControllers() . @@ -407,8 +418,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) } } - sal_Bool SAL_CALL ChartModel -::hasControllersLocked() throw(uno::RuntimeException) +sal_Bool SAL_CALL ChartModel::hasControllersLocked() throw(uno::RuntimeException) { LifeTimeGuard aGuard(m_aLifeTimeManager); if(!aGuard.startApiCall()) @@ -416,8 +426,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) return ( m_nControllerLockCount != 0 ) ; } - uno::Reference< frame::XController > SAL_CALL ChartModel -::getCurrentController() throw(uno::RuntimeException) +uno::Reference< frame::XController > SAL_CALL ChartModel::getCurrentController() throw(uno::RuntimeException) { LifeTimeGuard aGuard(m_aLifeTimeManager); if(!aGuard.startApiCall()) @@ -428,8 +437,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) return impl_getCurrentController(); } - void SAL_CALL ChartModel -::setCurrentController( const uno::Reference< frame::XController >& xController ) +void SAL_CALL ChartModel::setCurrentController( const uno::Reference< frame::XController >& xController ) throw(container::NoSuchElementException, uno::RuntimeException) { LifeTimeGuard aGuard(m_aLifeTimeManager); @@ -449,8 +457,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); } - uno::Reference< uno::XInterface > SAL_CALL ChartModel -::getCurrentSelection() throw(uno::RuntimeException) +uno::Reference< uno::XInterface > SAL_CALL ChartModel::getCurrentSelection() throw(uno::RuntimeException) { LifeTimeGuard aGuard(m_aLifeTimeManager); if(!aGuard.startApiCall()) @@ -483,8 +490,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) //----------------------------------------------------------------- // lang::XComponent (base of XModel) //----------------------------------------------------------------- - void SAL_CALL ChartModel -::dispose() throw(uno::RuntimeException) +void SAL_CALL ChartModel::dispose() throw(uno::RuntimeException) { //This object should release all resources and references in the //easiest possible manner @@ -497,8 +503,17 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) //--release all resources and references //// @todo - if( m_pImplChartModel.get()) - m_pImplChartModel->dispose(); + + m_xDataProvider.clear(); + m_xInternalDataProvider.clear(); + m_xNumberFormatsSupplier.clear(); + DisposeHelper::DisposeAndClear( m_xOwnNumberFormatsSupplier ); + DisposeHelper::DisposeAndClear( m_xChartTypeManager ); + DisposeHelper::DisposeAllElements( m_aDiagrams ); + m_aDiagrams.clear(); + DisposeHelper::DisposeAndClear( m_xTitle ); + DisposeHelper::DisposeAndClear( m_xPageBackground ); + DisposeHelper::DisposeAndClear( m_xXMLNamespaceMap ); // not owner of storage // if( m_xStorage.is()) @@ -524,8 +539,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) OSL_TRACE( "ChartModel: dispose() called" ); } - void SAL_CALL ChartModel -::addEventListener( const uno::Reference< lang::XEventListener > & xListener ) +void SAL_CALL ChartModel::addEventListener( const uno::Reference< lang::XEventListener > & xListener ) throw(uno::RuntimeException) { if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) @@ -534,8 +548,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) m_aLifeTimeManager.m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), xListener ); } - void SAL_CALL ChartModel -::removeEventListener( const uno::Reference< lang::XEventListener > & xListener ) +void SAL_CALL ChartModel::removeEventListener( const uno::Reference< lang::XEventListener > & xListener ) throw(uno::RuntimeException) { if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) @@ -548,15 +561,13 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) //----------------------------------------------------------------- // util::XCloseBroadcaster (base of XCloseable) //----------------------------------------------------------------- - void SAL_CALL ChartModel -::addCloseListener( const uno::Reference< util::XCloseListener > & xListener ) +void SAL_CALL ChartModel::addCloseListener( const uno::Reference< util::XCloseListener > & xListener ) throw(uno::RuntimeException) { m_aLifeTimeManager.g_addCloseListener( xListener ); } - void SAL_CALL ChartModel -::removeCloseListener( const uno::Reference< util::XCloseListener > & xListener ) +void SAL_CALL ChartModel::removeCloseListener( const uno::Reference< util::XCloseListener > & xListener ) throw(uno::RuntimeException) { if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) @@ -569,8 +580,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) //----------------------------------------------------------------- // util::XCloseable //----------------------------------------------------------------- - void SAL_CALL ChartModel -::close( sal_Bool bDeliverOwnership ) +void SAL_CALL ChartModel::close( sal_Bool bDeliverOwnership ) throw( util::CloseVetoException, uno::RuntimeException ) { @@ -627,8 +637,7 @@ APPHELPER_XSERVICEINFO_IMPL(ChartModel,CHART_MODEL_SERVICE_IMPLEMENTATION_NAME) //----------------------------------------------------------------- // lang::XTypeProvider //----------------------------------------------------------------- - uno::Sequence< uno::Type > SAL_CALL ChartModel -::getTypes() +uno::Sequence< uno::Type > SAL_CALL ChartModel::getTypes() throw (uno::RuntimeException) { uno::Reference< lang::XTypeProvider > xAggTypeProvider; @@ -669,82 +678,121 @@ uno::Reference< document::XDocumentProperties > SAL_CALL // chart2::XChartDocument //----------------------------------------------------------------- - uno::Reference< chart2::XDiagram > SAL_CALL ChartModel -::getFirstDiagram() +uno::Reference< chart2::XDiagram > SAL_CALL ChartModel::getFirstDiagram() throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); // /-- MutexGuard aGuard( m_aModelMutex ); - try - { - return m_pImplChartModel->GetDiagram( 0 ); - } - catch( container::NoSuchElementException ) - { - } - + if( m_aDiagrams.size() ) + return m_aDiagrams[ 0 ]; return uno::Reference< chart2::XDiagram >(); // \-- } - void SAL_CALL ChartModel -::setFirstDiagram( const uno::Reference< chart2::XDiagram >& xDiagram ) +void ChartModel::impl_removeAllDiagrams() +{ + ModifyListenerHelper::removeListenerFromAllElements( m_aDiagrams, this ); + m_aDiagrams.clear(); +} + +void ChartModel::impl_appendDiagram( const Reference< chart2::XDiagram > & xDiagram ) +{ + Reference< util::XModifyBroadcaster > xBroadcaster( xDiagram, uno::UNO_QUERY ); + ModifyListenerHelper::addListener( xDiagram, this ); + m_aDiagrams.push_back( xDiagram ); +} + + +void SAL_CALL ChartModel::setFirstDiagram( const uno::Reference< chart2::XDiagram >& xDiagram ) throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); { // /-- MutexGuard aGuard( m_aModelMutex ); - m_pImplChartModel->RemoveAllDiagrams(); - m_pImplChartModel->AppendDiagram( xDiagram ); + impl_removeAllDiagrams(); + impl_appendDiagram( xDiagram ); // \-- } setModified( sal_True ); } - void SAL_CALL ChartModel -::createInternalDataProvider( sal_Bool bCloneExistingData ) - throw (util::CloseVetoException, - uno::RuntimeException) +Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData() +{ + Reference< chart2::data::XDataSource > xDataSource; + if( hasInternalDataProvider() ) + { + uno::Reference< lang::XInitialization > xIni(m_xInternalDataProvider,uno::UNO_QUERY); + if( xIni.is() ) + { + //init internal dataprovider + { + uno::Sequence< uno::Any > aArgs(1); + beans::NamedValue aParam(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),uno::makeAny(sal_True)); + aArgs[0] <<= aParam; + xIni->initialize(aArgs); + } + //create data + uno::Sequence< beans::PropertyValue > aArgs( 4 ); + aArgs[0] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, + uno::makeAny( C2U("all") ), beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("HasCategories"), -1, + uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, + uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); + aArgs[3] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("DataRowSource"), -1, + uno::makeAny( ::com::sun::star::chart::ChartDataRowSource_COLUMNS ), beans::PropertyState_DIRECT_VALUE ); + xDataSource = m_xInternalDataProvider->createDataSource( aArgs ); + } + } + return xDataSource; +} + +void SAL_CALL ChartModel::createInternalDataProvider( sal_Bool bCloneExistingData ) + throw (util::CloseVetoException, uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); // don't lock the mutex, because this call calls out to code that tries to // lock the solar mutex. On the other hand, a paint locks the solar mutex // and calls to the model lock the model's mutex => deadlock // @todo: lock a separate mutex in the InternalData class - m_pImplChartModel->CreateInternalDataProvider( bCloneExistingData, this ); + if( !hasInternalDataProvider() ) + { + if( bCloneExistingData ) + m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( this, true ); + else + m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( Reference<XChartDocument>(), true ); + m_xDataProvider.set( m_xInternalDataProvider ); + } setModified( sal_True ); } sal_Bool SAL_CALL ChartModel::hasInternalDataProvider() throw (uno::RuntimeException) { - return m_pImplChartModel->HasInternalDataProvider(); + return m_xDataProvider.is() && m_xInternalDataProvider.is(); } - uno::Reference< chart2::data::XDataProvider > SAL_CALL ChartModel -::getDataProvider() +uno::Reference< chart2::data::XDataProvider > SAL_CALL ChartModel::getDataProvider() throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); // /-- MutexGuard aGuard( m_aModelMutex ); - return m_pImplChartModel->GetDataProvider(); + return m_xDataProvider; // \-- } // ____ XDataReceiver ____ - void SAL_CALL ChartModel -::attachDataProvider( const uno::Reference< chart2::data::XDataProvider >& xProvider ) +void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< chart2::data::XDataProvider >& xDataProvider ) throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); { // /-- MutexGuard aGuard( m_aModelMutex ); - uno::Reference< beans::XPropertySet > xProp( xProvider, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xProp( xDataProvider, uno::UNO_QUERY ); if( xProp.is() ) { try @@ -757,41 +805,95 @@ sal_Bool SAL_CALL ChartModel::hasInternalDataProvider() } } - m_pImplChartModel->SetDataProvider( xProvider ); + m_xDataProvider.set( xDataProvider ); + m_xInternalDataProvider.clear(); + + //the numberformatter is kept independent of the data provider! // \-- } setModified( sal_True ); } - void SAL_CALL ChartModel -::attachNumberFormatsSupplier( const uno::Reference< util::XNumberFormatsSupplier >& xSupplier ) +void SAL_CALL ChartModel::attachNumberFormatsSupplier( const uno::Reference< util::XNumberFormatsSupplier >& xNewSupplier ) throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); { // /-- MutexGuard aGuard( m_aModelMutex ); - m_pImplChartModel->SetNumberFormatsSupplier( xSupplier ); + if( xNewSupplier==m_xNumberFormatsSupplier ) + return; + if( xNewSupplier==m_xOwnNumberFormatsSupplier ) + return; + if( m_xOwnNumberFormatsSupplier.is() && xNewSupplier.is() ) + { + //@todo + //merge missing numberformats from own to new formatter + } + else if( !xNewSupplier.is() ) + { + if( m_xNumberFormatsSupplier.is() ) + { + //@todo + //merge missing numberformats from old numberformatter to own numberformatter + //create own numberformatter if necessary + } + } + + m_xNumberFormatsSupplier.set( xNewSupplier ); + m_xOwnNumberFormatsSupplier.clear(); // \-- } setModified( sal_True ); } - void SAL_CALL ChartModel -::setArguments( const Sequence< beans::PropertyValue >& aArguments ) +void SAL_CALL ChartModel::setArguments( const Sequence< beans::PropertyValue >& aArguments ) throw (lang::IllegalArgumentException, uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); { // /-- MutexGuard aGuard( m_aModelMutex ); + if( !m_xDataProvider.is() ) + return; lockControllers(); + try { - m_pImplChartModel->SetArguments( aArguments, true /* bSetData */ ); + Reference< chart2::data::XDataSource > xDataSource( m_xDataProvider->createDataSource( aArguments ) ); + if( xDataSource.is() ) + { + // set new data + Reference< chart2::XChartTypeTemplate > xTemplate; + Reference< chart2::XDiagram > xDia( getFirstDiagram() ); + if( xDia.is()) + { + // apply new data + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( + xDia, Reference< lang::XMultiServiceFactory >( m_xChartTypeManager, uno::UNO_QUERY )); + xTemplate.set( aTemplateAndService.first ); + } + + if( !xTemplate.is()) + xTemplate.set( impl_createDefaultChartTypeTemplate() ); + + if( xTemplate.is()) + { + if( xDia.is()) + xTemplate->changeDiagramData( xDia, xDataSource, aArguments ); + else + { + impl_removeAllDiagrams(); + impl_appendDiagram( xTemplate->createDiagramByDataSource( xDataSource, aArguments )); + } + } + } + } + catch( lang::IllegalArgumentException & ) + { + throw; } - catch( const uno::Exception & ex ) + catch( uno::Exception & ex ) { ASSERT_EXCEPTION( ex ); } @@ -801,22 +903,19 @@ sal_Bool SAL_CALL ChartModel::hasInternalDataProvider() setModified( sal_True ); } - Sequence< OUString > SAL_CALL ChartModel -::getUsedRangeRepresentations() +Sequence< OUString > SAL_CALL ChartModel::getUsedRangeRepresentations() throw (uno::RuntimeException) { return DataSourceHelper::getUsedDataRanges( Reference< frame::XModel >(this)); } - Reference< chart2::data::XDataSource > SAL_CALL ChartModel -::getUsedData() +Reference< chart2::data::XDataSource > SAL_CALL ChartModel::getUsedData() throw (uno::RuntimeException) { return DataSourceHelper::getUsedData( Reference< chart2::XChartDocument >(this)); } - Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel -::getRangeHighlighter() +Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighlighter() throw (uno::RuntimeException) { if( ! m_xRangeHighlighter.is()) @@ -828,40 +927,42 @@ sal_Bool SAL_CALL ChartModel::hasInternalDataProvider() return m_xRangeHighlighter; } +Reference< chart2::XChartTypeTemplate > ChartModel::impl_createDefaultChartTypeTemplate() +{ + Reference< chart2::XChartTypeTemplate > xTemplate; + Reference< lang::XMultiServiceFactory > xFact( m_xChartTypeManager, uno::UNO_QUERY ); + if( xFact.is() ) + xTemplate.set( xFact->createInstance( C2U( "com.sun.star.chart2.template.Column" ) ), uno::UNO_QUERY ); + return xTemplate; +} - void SAL_CALL ChartModel -::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager ) +void SAL_CALL ChartModel::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager ) throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); { // /-- MutexGuard aGuard( m_aModelMutex ); - m_pImplChartModel->SetChartTypeManager( xNewManager ); + m_xChartTypeManager = xNewManager; // \-- } setModified( sal_True ); } - uno::Reference< chart2::XChartTypeManager > SAL_CALL ChartModel -::getChartTypeManager() +uno::Reference< chart2::XChartTypeManager > SAL_CALL ChartModel::getChartTypeManager() throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); // /-- MutexGuard aGuard( m_aModelMutex ); - return m_pImplChartModel->GetChartTypeManager(); + return m_xChartTypeManager; // \-- } - uno::Reference< beans::XPropertySet > SAL_CALL ChartModel -::getPageBackground() +uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getPageBackground() throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); // /-- MutexGuard aGuard( m_aModelMutex ); - return m_pImplChartModel->GetPageBackground(); + return m_xPageBackground; // \-- } @@ -869,23 +970,22 @@ sal_Bool SAL_CALL ChartModel::hasInternalDataProvider() uno::Reference< chart2::XTitle > SAL_CALL ChartModel::getTitleObject() throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); // /-- MutexGuard aGuard( m_aModelMutex ); - return m_pImplChartModel->GetTitle(); + return m_xTitle; // \-- } -void SAL_CALL ChartModel::setTitleObject( - const uno::Reference< - chart2::XTitle >& Title ) +void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& xTitle ) throw (uno::RuntimeException) { - OSL_ASSERT( m_pImplChartModel.get() != 0 ); { // /-- MutexGuard aGuard( m_aModelMutex ); - m_pImplChartModel->SetTitle( Title ); + if( m_xTitle.is() ) + ModifyListenerHelper::removeListener( m_xTitle, this ); + m_xTitle = xTitle; + ModifyListenerHelper::addListener( m_xTitle, this ); // \-- } setModified( sal_True ); @@ -1123,9 +1223,6 @@ tServiceNameMap & lcl_getStaticServiceNameMap() Reference< uno::XInterface > SAL_CALL ChartModel::createInstance( const OUString& rServiceSpecifier ) throw( uno::Exception, uno::RuntimeException ) { - if( ! m_pImplChartModel.get() ) - return 0; - uno::Reference< uno::XInterface > xResult; tServiceNameMap & rMap = lcl_getStaticServiceNameMap(); @@ -1150,9 +1247,7 @@ Reference< uno::XInterface > SAL_CALL ChartModel::createInstance( const OUString } break; case SERVICE_NAMESPACE_MAP: - // not yet supported, @todo -// return 0; - return m_pImplChartModel->GetXMLNameSpaceMap(); + return Reference< uno::XInterface >( m_xXMLNamespaceMap ); } } else @@ -1198,6 +1293,21 @@ Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames() return aResult; } +Reference< util::XNumberFormatsSupplier > ChartModel::impl_getNumberFormatsSupplier() +{ + if( !m_xNumberFormatsSupplier.is() ) + { + if( !m_xOwnNumberFormatsSupplier.is() ) + { + Reference< lang::XMultiServiceFactory > xFactory( m_xContext->getServiceManager(), uno::UNO_QUERY ); + m_xOwnNumberFormatsSupplier = new SvNumberFormatsSupplierObj( new SvNumberFormatter( xFactory, LANGUAGE_SYSTEM ) ); + //pOwnNumberFormatter->ChangeStandardPrec( 15 ); todo? + } + m_xNumberFormatsSupplier = m_xOwnNumberFormatsSupplier; + } + return m_xNumberFormatsSupplier; +} + // ____ XUnoTunnel ___ ::sal_Int64 SAL_CALL ChartModel::getSomething( const Sequence< ::sal_Int8 >& aIdentifier ) throw( uno::RuntimeException) @@ -1205,14 +1315,9 @@ Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames() if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( SvNumberFormatsSupplierObj::getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) { - OSL_ENSURE( m_pImplChartModel.get(), "need a model implementation to provide a numberformatter" ); - if( m_pImplChartModel.get() ) - { - Reference< lang::XUnoTunnel > xTunnel( m_pImplChartModel->GetNumberFormatsSupplier(), uno::UNO_QUERY ); - if( xTunnel.is() ) - return xTunnel->getSomething( aIdentifier ); - } - return 0; + Reference< lang::XUnoTunnel > xTunnel( impl_getNumberFormatsSupplier(), uno::UNO_QUERY ); + if( xTunnel.is() ) + return xTunnel->getSomething( aIdentifier ); } return 0; } @@ -1221,26 +1326,18 @@ Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames() uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getNumberFormatSettings() throw (uno::RuntimeException) { - OSL_ENSURE( m_pImplChartModel.get(), "need a model implementation to provide a numberformatter" ); - if( m_pImplChartModel.get() ) - { - Reference< util::XNumberFormatsSupplier > xSupplier( m_pImplChartModel->GetNumberFormatsSupplier() ); - if( xSupplier.is() ) - return xSupplier->getNumberFormatSettings(); - } + Reference< util::XNumberFormatsSupplier > xSupplier( impl_getNumberFormatsSupplier() ); + if( xSupplier.is() ) + return xSupplier->getNumberFormatSettings(); return uno::Reference< beans::XPropertySet >(); } uno::Reference< util::XNumberFormats > SAL_CALL ChartModel::getNumberFormats() throw (uno::RuntimeException) { - OSL_ENSURE( m_pImplChartModel.get(), "need a model implementation to provide a numberformatter" ); - if( m_pImplChartModel.get() ) - { - Reference< util::XNumberFormatsSupplier > xSupplier( m_pImplChartModel->GetNumberFormatsSupplier() ); - if( xSupplier.is() ) - return xSupplier->getNumberFormats(); - } + Reference< util::XNumberFormatsSupplier > xSupplier( impl_getNumberFormatsSupplier() ); + if( xSupplier.is() ) + return xSupplier->getNumberFormats(); return uno::Reference< util::XNumberFormats >(); } diff --git a/chart2/source/model/main/ChartModel.hxx b/chart2/source/model/main/ChartModel.hxx index ab30e40f85fc..860f71f909ea 100644 --- a/chart2/source/model/main/ChartModel.hxx +++ b/chart2/source/model/main/ChartModel.hxx @@ -47,6 +47,8 @@ #include <com/sun/star/container/XChild.hpp> #include <com/sun/star/chart2/XUndoSupplier.hpp> #include <com/sun/star/chart2/data/XDataSource.hpp> +#include <com/sun/star/chart2/XChartTypeTemplate.hpp> +#include <com/sun/star/container/XNameContainer.hpp> // public API #include <com/sun/star/chart2/data/XDataProvider.hpp> @@ -81,7 +83,6 @@ namespace chart namespace impl { - class ImplChartModel; // Note: needed for queryInterface (if it calls the base-class implementation) typedef ::comphelper::WeakImplHelper20< @@ -136,8 +137,6 @@ private: // ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aPrinterOptions; - ::std::auto_ptr< impl::ImplChartModel > m_pImplChartModel; - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation > m_xOldModelAgg; @@ -147,7 +146,40 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > m_xParent; ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XRangeHighlighter > m_xRangeHighlighter; ::std::vector< GraphicObject > m_aGraphicObjectVector; - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XUndoManager > m_xUndoManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > m_xDataProvider; + /** is only valid if m_xDataProvider is set. If m_xDataProvider is set to an + external data provider this reference must be set to 0 + */ + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > m_xInternalDataProvider; + + ::com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier > + m_xOwnNumberFormatsSupplier; + ::com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier > + m_xNumberFormatsSupplier; + + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartTypeManager > + m_xChartTypeManager; + + // Diagram Access + typedef ::std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XDiagram > > + tDiagramContainer; + + tDiagramContainer m_aDiagrams; + + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTitle > + m_xTitle; + + bool m_bIsDisposed; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xPageBackground; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XUndoManager > + m_xUndoManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> m_xXMLNamespaceMap; + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > m_xModifyListener; private: //private methods @@ -193,9 +225,19 @@ private: impl_createFilter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > & rMediaDescriptor ); + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartTypeTemplate > impl_createDefaultChartTypeTemplate(); + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > impl_createDefaultData(); + void impl_adjustAdditionalShapesPositionAndSize( const ::com::sun::star::awt::Size& aVisualAreaSize ); + void impl_removeAllDiagrams(); + void impl_appendDiagram( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XDiagram > & xDiagram ); + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > + impl_getNumberFormatsSupplier(); + public: //no default constructor ChartModel(::com::sun::star::uno::Reference< diff --git a/chart2/source/model/main/ChartModel_Persistence.cxx b/chart2/source/model/main/ChartModel_Persistence.cxx index 82f1cdc2054a..b7b8f380ceea 100644 --- a/chart2/source/model/main/ChartModel_Persistence.cxx +++ b/chart2/source/model/main/ChartModel_Persistence.cxx @@ -29,28 +29,36 @@ #include "precompiled_chart2.hxx" #include "ChartModel.hxx" -#include "ImplChartModel.hxx" #include "MediaDescriptorHelper.hxx" #include "ChartDebugTrace.hxx" #include "macros.hxx" #include "ChartViewHelper.hxx" #include "ChartModelHelper.hxx" +#include "AxisHelper.hxx" +#include "ThreeDHelper.hxx" + +#include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/container/XNameAccess.hpp> #include <com/sun/star/document/XExporter.hpp> #include <com/sun/star/document/XImporter.hpp> #include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> #include <com/sun/star/embed/ElementModes.hpp> #include <com/sun/star/embed/XStorage.hpp> #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/io/XSeekable.hpp> + #include <ucbhelper/content.hxx> #ifndef _UNOTOOLS_UCBSTREAMHELPER_HXX #include <unotools/ucbstreamhelper.hxx> #endif #include <vcl/cvtgrf.hxx> #include <comphelper/storagehelper.hxx> +#include <vcl/svapp.hxx> #include <algorithm> #include <functional> @@ -404,7 +412,88 @@ void SAL_CALL ChartModel::initNew() createInternalDataProvider( sal_False ); try { - m_pImplChartModel->CreateDefaultChart(); + // create default chart + impl_removeAllDiagrams(); + + Reference< chart2::XChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() ); + if( xTemplate.is()) + { + try + { + Reference< chart2::data::XDataSource > xDataSource( impl_createDefaultData() ); + Sequence< beans::PropertyValue > aParam; + + bool bSupportsCategories = xTemplate->supportsCategories(); + if( bSupportsCategories ) + { + aParam.realloc( 1 ); + aParam[0] = beans::PropertyValue( C2U("HasCategories"), -1, uno::makeAny( true ), + beans::PropertyState_DIRECT_VALUE ); + } + + Reference< chart2::XDiagram > xDiagram( xTemplate->createDiagramByDataSource( xDataSource, aParam ) ); + + impl_appendDiagram( xDiagram ); + + bool bIsRTL = Application::GetSettings().GetLayoutRTL(); + //reverse x axis for rtl charts + if( bIsRTL ) + AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); + + // create and attach legend + Reference< chart2::XLegend > xLegend( + m_xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.chart2.Legend" ), m_xContext ), uno::UNO_QUERY_THROW ); + Reference< beans::XPropertySet > xLegendProperties( xLegend, uno::UNO_QUERY ); + if( xLegendProperties.is() ) + { + xLegendProperties->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_NONE )); + xLegendProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE )); + xLegendProperties->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30 + xLegendProperties->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + + if( bIsRTL ) + xLegendProperties->setPropertyValue( C2U( "AnchorPosition" ), uno::makeAny( chart2::LegendPosition_LINE_START )); + } + if(xDiagram.is()) + xDiagram->setLegend( xLegend ); + + // set simple 3D look + Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); + if( xDiagramProperties.is() ) + { + xDiagramProperties->setPropertyValue( C2U("RightAngledAxes"), uno::makeAny( sal_True )); + xDiagramProperties->setPropertyValue( C2U("D3DScenePerspective"), uno::makeAny( drawing::ProjectionMode_PARALLEL )); + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Simple ); + } + + //set some new 'defaults' for wall and floor + if( xDiagram.is() ) + { + Reference< beans::XPropertySet > xWall( xDiagram->getWall() ); + if( xWall.is() ) + { + xWall->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ); + xWall->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_NONE ) ); + xWall->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + xWall->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + } + Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() ); + if( xFloor.is() ) + { + xFloor->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) ); + xFloor->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_SOLID ) ); + xFloor->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + xFloor->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20 + } + + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } ChartModelHelper::setIncludeHiddenCells( false, this ); } catch( uno::Exception & ex ) diff --git a/chart2/source/model/main/Diagram.cxx b/chart2/source/model/main/Diagram.cxx index d5436ddc02eb..f74764c398ef 100644 --- a/chart2/source/model/main/Diagram.cxx +++ b/chart2/source/model/main/Diagram.cxx @@ -369,18 +369,6 @@ void SAL_CALL Diagram::setDefaultColorScheme( const Reference< chart2::XColorSch fireModifyEvent(); } -void SAL_CALL Diagram::setUnusedData( const Sequence< Reference< chart2::data::XLabeledDataSequence > >& aUnusedData ) - throw (uno::RuntimeException) -{ - m_aUnusedData = aUnusedData; -} - -Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL Diagram::getUnusedData() - throw (uno::RuntimeException) -{ - return m_aUnusedData; -} - // ____ XTitled ____ uno::Reference< chart2::XTitle > SAL_CALL Diagram::getTitleObject() throw (uno::RuntimeException) diff --git a/chart2/source/model/main/ImplChartModel.cxx b/chart2/source/model/main/ImplChartModel.cxx deleted file mode 100755 index 77b78f16c861..000000000000 --- a/chart2/source/model/main/ImplChartModel.cxx +++ /dev/null @@ -1,537 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_chart2.hxx" -#include "ImplChartModel.hxx" -#include "DataSeries.hxx" -#include "macros.hxx" -#include "PageBackground.hxx" -#include "DiagramHelper.hxx" -#include "NameContainer.hxx" -#include "CloneHelper.hxx" -#include "ModifyListenerHelper.hxx" -#include "DataSourceHelper.hxx" -#include "DisposeHelper.hxx" -#include "ChartModelHelper.hxx" -#include "ThreeDHelper.hxx" -#include "AxisHelper.hxx" - -// header for class SvNumberFormatter -#include <svl/zforlist.hxx> -// header for class SvNumberFormatsSupplierObj -#include <svl/numuno.hxx> -#include <vcl/svapp.hxx> -#include <cppuhelper/component_context.hxx> - -#include <com/sun/star/chart2/LegendPosition.hpp> -#include <com/sun/star/chart2/XDataSeries.hpp> -#include <com/sun/star/chart/ChartDataRowSource.hpp> -#include <com/sun/star/uno/XComponentContext.hpp> -#include <com/sun/star/embed/XStorage.hpp> -#include <com/sun/star/embed/ElementModes.hpp> -#include <com/sun/star/document/XFilter.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> -#include <com/sun/star/util/XModifyBroadcaster.hpp> -#include <com/sun/star/drawing/FillStyle.hpp> -#include <com/sun/star/drawing/Hatch.hpp> -#include <com/sun/star/drawing/LineDash.hpp> -#include <com/sun/star/drawing/LineStyle.hpp> -#include <com/sun/star/awt/Gradient.hpp> -#include <com/sun/star/drawing/ProjectionMode.hpp> - -#include <vector> -#include <algorithm> -#include <functional> - -using namespace ::com::sun::star; -using namespace ::chart::CloneHelper; - -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; - -using ::rtl::OUString; - -namespace -{ - -struct lcl_removeListener : public ::std::unary_function< Reference< chart2::XDiagram >, void > -{ - explicit lcl_removeListener( const Reference< util::XModifyListener > & xListener ) : - m_xListener( xListener ) - {} - - void operator() ( const Reference< chart2::XDiagram > & xDia ) - { - Reference< util::XModifyBroadcaster > xBroadcaster( xDia, uno::UNO_QUERY ); - if( xBroadcaster.is() && m_xListener.is()) - xBroadcaster->removeModifyListener( m_xListener ); - } -private: - Reference< util::XModifyListener > m_xListener; -}; - -} // anonymous namespace - -namespace chart -{ -namespace impl -{ - -ImplChartModel::ImplChartModel( - Reference< uno::XComponentContext > const & xContext, - const Reference< util::XModifyListener > & xListener ) : - m_xContext( xContext ), - m_spChartData( new ChartData( m_xContext )), - m_bIsDisposed( false ), - m_xPageBackground( new PageBackground( m_xContext )), - m_xXMLNamespaceMap( createNameContainer( ::getCppuType( (const OUString*) 0 ), - C2U( "com.sun.star.xml.NamespaceMap" ), C2U( "com.sun.star.comp.chart.XMLNameSpaceMap" ) ), uno::UNO_QUERY), - m_xModifyListener( xListener ) -{ - ModifyListenerHelper::addListener( m_xPageBackground, m_xModifyListener ); - m_xChartTypeManager.set( - xContext->getServiceManager()->createInstanceWithContext( - C2U( "com.sun.star.chart2.ChartTypeManager" ), - xContext ), uno::UNO_QUERY ); - - GetStyleFamilies(); - CreateDefaultChartTypeTemplate(); -} - -ImplChartModel::ImplChartModel( const ImplChartModel & rOther, const Reference< util::XModifyListener > & xListener ) : - m_xContext( rOther.m_xContext ), - m_spChartData( rOther.m_spChartData ), - m_bIsDisposed( rOther.m_bIsDisposed ), - m_xModifyListener( xListener ) -{ - m_xFamilies.set( CreateRefClone< Reference< container::XNameAccess > >()( rOther.m_xFamilies )); - m_xChartTypeManager.set( CreateRefClone< Reference< chart2::XChartTypeManager > >()( rOther.m_xChartTypeManager )); - m_xChartTypeTemplate.set( CreateRefClone< Reference< chart2::XChartTypeTemplate > >()( rOther.m_xChartTypeTemplate )); - m_xTitle.set( CreateRefClone< Reference< chart2::XTitle > >()( rOther.m_xTitle )); - ModifyListenerHelper::addListener( m_xTitle, m_xModifyListener ); - m_xPageBackground.set( CreateRefClone< Reference< beans::XPropertySet > >()( rOther.m_xPageBackground )); - ModifyListenerHelper::addListener( m_xPageBackground, m_xModifyListener ); - - m_xXMLNamespaceMap.set( CreateRefClone< Reference< container::XNameAccess > >()( rOther.m_xXMLNamespaceMap )); - - CloneRefVector< Reference< chart2::XDiagram > >( rOther.m_aDiagrams, m_aDiagrams ); -} - -ImplChartModel::~ImplChartModel() -{} - -Reference< container::XNameAccess > ImplChartModel::GetStyleFamilies() -{ - return m_xFamilies; -} - -// Diagram Access - -void ImplChartModel::RemoveAllDiagrams() -{ - ModifyListenerHelper::removeListenerFromAllElements( m_aDiagrams, m_xModifyListener ); - m_aDiagrams.clear(); -} - -void ImplChartModel::AppendDiagram( const Reference< chart2::XDiagram > & xDiagram ) -{ - Reference< util::XModifyBroadcaster > xBroadcaster( xDiagram, uno::UNO_QUERY ); - ModifyListenerHelper::addListener( xDiagram, m_xModifyListener ); - m_aDiagrams.push_back( xDiagram ); -} - -Reference< chart2::XDiagram > ImplChartModel::GetDiagram( size_t nIndex ) const - throw( container::NoSuchElementException ) -{ - if( nIndex >= m_aDiagrams.size() ) - throw container::NoSuchElementException(); - - return m_aDiagrams[ nIndex ]; -} - -void ImplChartModel::SetDataProvider( - const Reference< chart2::data::XDataProvider > & xProvider ) -{ - OSL_ASSERT( m_spChartData.get() ); - - m_spChartData->setDataProvider( xProvider ); - - //the numberformatter is kept independent of the data provider! - - // release other ressources - - // @todo: maybe we need to save some properties of the old diagrams. When - // the data provider changes from an outside Calc to an internal Calc, - // e.g. when copying a chart into the clipboard as "standalone" format -// if( bDeleteDiagrams && ! m_aDiagrams.empty()) -// m_aDiagrams.clear(); -} - -Reference< chart2::data::XDataProvider > ImplChartModel::GetDataProvider() const -{ - OSL_ASSERT( m_spChartData.get() ); - - return m_spChartData->getDataProvider(); -} - -void ImplChartModel::CreateInternalDataProvider( - bool bCloneExistingData, - const Reference< chart2::XChartDocument > & xChartDoc ) -{ - m_spChartData->createInternalData( bCloneExistingData, xChartDoc ); -} - -bool ImplChartModel::HasInternalDataProvider() const -{ - OSL_ASSERT( m_spChartData.get() ); - - return m_spChartData->hasInternalData(); -} - -Reference< chart2::data::XDataSource > SAL_CALL ImplChartModel::SetArguments( - const Sequence< beans::PropertyValue > & aArguments, - bool bSetData ) - throw (lang::IllegalArgumentException) -{ - Reference< chart2::data::XDataSource > xResult; - try - { - OSL_ASSERT( m_spChartData.get() ); - - Reference< chart2::data::XDataProvider > xDataProvider( - m_spChartData->getDataProvider()); - if( xDataProvider.is() ) - { - xResult.set( xDataProvider->createDataSource( aArguments )); - - if( bSetData && xResult.is()) - SetNewData( xResult, aArguments ); - } - } - catch( lang::IllegalArgumentException & ) - { - throw; - } - catch( uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - - return xResult; -} - -Reference< chart2::data::XDataSource > SAL_CALL ImplChartModel::SetRangeRepresentation( - const OUString & rRangeRepresentation, bool bSetData ) - throw (::com::sun::star::lang::IllegalArgumentException) -{ - uno::Sequence< beans::PropertyValue > aArgs( 4 ); - aArgs[0] = beans::PropertyValue( - ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, - uno::makeAny( rRangeRepresentation ), beans::PropertyState_DIRECT_VALUE ); - aArgs[1] = beans::PropertyValue( - ::rtl::OUString::createFromAscii("HasCategories"), -1, - uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); - aArgs[2] = beans::PropertyValue( - ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, - uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); - aArgs[3] = beans::PropertyValue( - ::rtl::OUString::createFromAscii("DataRowSource"), -1, - uno::makeAny( ::com::sun::star::chart::ChartDataRowSource_COLUMNS ), beans::PropertyState_DIRECT_VALUE ); - return SetArguments( aArgs, bSetData ); - /* - uno::Sequence< beans::PropertyValue > aArgs(); - - Reference< chart2::data::XDataProvider > xDataProvider( this->GetDataProvider() ); - if( xDataProvider.is() ) - aArgs = xDataProvider->detectArguments( DataSourceHelper::getUsedData( xChartModel ) ), - - ::rtl::OUString aRangeString; - uno::Sequence< sal_Int32 > aSequenceMapping; - bool bUseColumns = true; - bool bFirstCellAsLabel = true; - bool bHasCategories = true; - - DataSourceHelper::detectRangeSegmentation( - uno::Reference< frame::XModel >( m_xChartDoc, uno::UNO_QUERY ), - aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ); - - aArgs = createArguments( rRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ) ); - - return SetArguments( aArgs, bSetData ); - */ -} - -void ImplChartModel::SetChartTypeManager( - const Reference< chart2::XChartTypeManager > & xManager ) -{ - m_xChartTypeManager = xManager; -} - -Reference< chart2::XChartTypeManager > ImplChartModel::GetChartTypeManager() -{ - return m_xChartTypeManager; -} - -Reference< chart2::XChartTypeTemplate > ImplChartModel::GetChartTypeTemplate() -{ - return m_xChartTypeTemplate; -} - -void ImplChartModel::CreateDefaultChart() -{ - CreateDefaultChartTypeTemplate(); - - // clean up - RemoveAllDiagrams(); - - Reference< chart2::XChartTypeTemplate > xTemplate( GetChartTypeTemplate()); - if( xTemplate.is()) - { - try - { - Reference< chart2::data::XDataSource > xDataSource( CreateDefaultData()); - Sequence< beans::PropertyValue > aParam; - - Sequence< OUString > aParamNames( xTemplate->getAvailableCreationParameterNames()); - const OUString * pBeg = aParamNames.getConstArray(); - const OUString * pEnd = pBeg + aParamNames.getLength(); - const OUString * pFound( ::std::find( pBeg, pEnd, C2U("HasCategories"))); - if( pFound != pEnd ) - { - aParam.realloc( 1 ); - aParam[0] = beans::PropertyValue( C2U("HasCategories"), -1, uno::makeAny( true ), - beans::PropertyState_DIRECT_VALUE ); - } - - Reference< chart2::XDiagram > xDiagram( xTemplate->createDiagramByDataSource( xDataSource, aParam ) ); - - AppendDiagram( xDiagram ); - - bool bIsRTL = Application::GetSettings().GetLayoutRTL(); - //reverse x axis for rtl charts - if( bIsRTL ) - AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); - - // create and attach legend - Reference< chart2::XLegend > xLegend( - m_xContext->getServiceManager()->createInstanceWithContext( - C2U( "com.sun.star.chart2.Legend" ), m_xContext ), uno::UNO_QUERY_THROW ); - Reference< beans::XPropertySet > xLegendProperties( xLegend, uno::UNO_QUERY ); - if( xLegendProperties.is() ) - { - xLegendProperties->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_NONE )); - xLegendProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE )); - xLegendProperties->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30 - xLegendProperties->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 - - if( bIsRTL ) - xLegendProperties->setPropertyValue( C2U( "AnchorPosition" ), uno::makeAny( chart2::LegendPosition_LINE_START )); - } - if(xDiagram.is()) - xDiagram->setLegend( xLegend ); - - // set simple 3D look - Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); - if( xDiagramProperties.is() ) - { - xDiagramProperties->setPropertyValue( C2U("RightAngledAxes"), uno::makeAny( sal_True )); - xDiagramProperties->setPropertyValue( C2U("D3DScenePerspective"), uno::makeAny( drawing::ProjectionMode_PARALLEL )); - ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Simple ); - } - - //set some new 'defaults' for wall and floor - if( xDiagram.is() ) - { - Reference< beans::XPropertySet > xWall( xDiagram->getWall() ); - if( xWall.is() ) - { - xWall->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ); - xWall->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_NONE ) ); - xWall->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 - xWall->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 - } - Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() ); - if( xFloor.is() ) - { - xFloor->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) ); - xFloor->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_SOLID ) ); - xFloor->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 - xFloor->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20 - } - - } - } - catch( uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - } -} - -Reference< chart2::XTitle > ImplChartModel::GetTitle() -{ - return m_xTitle; -} - -void ImplChartModel::SetTitle( const Reference< chart2::XTitle >& rTitle ) -{ - if( m_xTitle.is()) - ModifyListenerHelper::removeListener( m_xTitle, m_xModifyListener ); - m_xTitle = rTitle; - ModifyListenerHelper::addListener( m_xTitle, m_xModifyListener ); -} - -void ImplChartModel::dispose() -{ - // exception is thrown by ChartModel - if( m_bIsDisposed ) - return; - - m_spChartData.reset(); - m_xNumberFormatsSupplier.clear(); - - DisposeHelper::DisposeAndClear( m_xFamilies ); - DisposeHelper::DisposeAndClear( m_xOwnNumberFormatsSupplier ); - DisposeHelper::DisposeAndClear( m_xChartTypeManager ); - DisposeHelper::DisposeAndClear( m_xChartTypeTemplate ); - DisposeHelper::DisposeAllElements( m_aDiagrams ); - m_aDiagrams.clear(); - DisposeHelper::DisposeAndClear( m_xTitle ); - DisposeHelper::DisposeAndClear( m_xPageBackground ); - DisposeHelper::DisposeAndClear( m_xXMLNamespaceMap ); - - // note: m_xModifyListener is the ChartModel, so don't call dispose() - m_xModifyListener.clear(); - - m_bIsDisposed = true; -} - -Reference< beans::XPropertySet > ImplChartModel::GetPageBackground() -{ - return m_xPageBackground; -} - -void ImplChartModel::SetNewData( const Reference< chart2::data::XDataSource > & xDataSource, - const Sequence< beans::PropertyValue > & rArgs ) -{ - Reference< chart2::XDiagram > xDia; - if( m_aDiagrams.size() > 0 ) - xDia.set( GetDiagram(0)); - Reference< chart2::XChartTypeTemplate > xTemplate; - - if( xDia.is()) - { - // apply new data - DiagramHelper::tTemplateWithServiceName aTemplateAndService = - DiagramHelper::getTemplateForDiagram( - xDia, Reference< lang::XMultiServiceFactory >( m_xChartTypeManager, uno::UNO_QUERY )); - xTemplate.set( aTemplateAndService.first ); - } - - if( !xTemplate.is()) - xTemplate.set( GetChartTypeTemplate()); - - if( xTemplate.is()) - { - if( xDia.is()) - xTemplate->changeDiagramData( xDia, xDataSource, rArgs ); - else - { - RemoveAllDiagrams(); - AppendDiagram( xTemplate->createDiagramByDataSource( xDataSource, rArgs )); - } - } -} - -Reference< chart2::data::XDataSource > ImplChartModel::CreateDefaultData() -{ - Reference< chart2::data::XDataSource > xResult; - if( m_spChartData->createDefaultData()) - xResult.set( SetRangeRepresentation( C2U("all"), false /* bSetData */ )); - return xResult; -} - -void ImplChartModel::CreateDefaultChartTypeTemplate() -{ - // set default chart type - Reference< lang::XMultiServiceFactory > xFact( m_xChartTypeManager, uno::UNO_QUERY ); - if( xFact.is() ) - { - m_xChartTypeTemplate.set( - xFact->createInstance( C2U( "com.sun.star.chart2.template.Column" ) ), uno::UNO_QUERY ); - } -} - -Reference< uno::XInterface > ImplChartModel::GetXMLNameSpaceMap() const -{ - return Reference< uno::XInterface >( m_xXMLNamespaceMap ); -} - -void ImplChartModel::SetNumberFormatsSupplier( - const Reference< util::XNumberFormatsSupplier > & xNew ) -{ - if( xNew==m_xNumberFormatsSupplier ) - return; - if( xNew==m_xOwnNumberFormatsSupplier ) - return; - if( m_xOwnNumberFormatsSupplier.is() && xNew.is() ) - { - //@todo - //merge missing numberformats from own to new formatter - } - else if( !xNew.is() ) - { - if( m_xNumberFormatsSupplier.is() ) - { - //@todo - //merge missing numberformats from old numberformatter to own numberformatter - //create own numberformatter if necessary - } - } - - m_xNumberFormatsSupplier.set( xNew ); - m_xOwnNumberFormatsSupplier.clear(); -} - -Reference< util::XNumberFormatsSupplier > ImplChartModel::GetNumberFormatsSupplier() -{ - if( !m_xNumberFormatsSupplier.is() ) - { - if( !m_xOwnNumberFormatsSupplier.is() ) - { - Reference< lang::XMultiServiceFactory > xFactory( m_xContext->getServiceManager(), uno::UNO_QUERY ); - m_xOwnNumberFormatsSupplier = new SvNumberFormatsSupplierObj( new SvNumberFormatter( xFactory, LANGUAGE_SYSTEM ) ); - //pOwnNumberFormatter->ChangeStandardPrec( 15 ); todo? - } - m_xNumberFormatsSupplier = m_xOwnNumberFormatsSupplier; - } - return m_xNumberFormatsSupplier; -} - -} // namespace impl -} // namespace chart diff --git a/chart2/source/model/main/ImplChartModel.hxx b/chart2/source/model/main/ImplChartModel.hxx deleted file mode 100644 index 1e0a0bf2c35a..000000000000 --- a/chart2/source/model/main/ImplChartModel.hxx +++ /dev/null @@ -1,228 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef CHART_IMPLCHARTMODEL_HXX -#define CHART_IMPLCHARTMODEL_HXX - -#include <com/sun/star/chart2/data/XDataSource.hpp> -#include <com/sun/star/chart2/XDataSeries.hpp> -#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> -#include <com/sun/star/chart2/XDiagram.hpp> -#include <com/sun/star/chart2/data/XDataProvider.hpp> -#include <com/sun/star/chart2/XChartTypeManager.hpp> -#include <com/sun/star/chart2/XChartTypeTemplate.hpp> -#include <com/sun/star/chart2/XTitle.hpp> -#include <com/sun/star/chart2/XChartDocument.hpp> -#include <com/sun/star/chart2/XUndoManager.hpp> - -#include <com/sun/star/container/XNameContainer.hpp> -#include <com/sun/star/container/NoSuchElementException.hpp> -#include <com/sun/star/io/IOException.hpp> -#include <com/sun/star/util/XNumberFormatsSupplier.hpp> - -#include <cppuhelper/weakref.hxx> - -#include "ChartData.hxx" - -#include <vector> -#include <memory> -#include <boost/shared_ptr.hpp> - -namespace com { namespace sun { namespace star { - namespace container { - class XNameAccess; - } - namespace uno { - class XComponentContext; - } - namespace embed { - class XStorage; - } - namespace document { - class XFilter; - } - namespace util { - class XModifyListener; - } -}}} - -class SvNumberFormatter; - -namespace chart -{ -namespace impl -{ - -class ImplChartModel -{ - typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > tDataSourceType; - -public: - ImplChartModel( ::com::sun::star::uno::Reference< - ::com::sun::star::uno::XComponentContext > const & xContext, - const ::com::sun::star::uno::Reference< - ::com::sun::star::util::XModifyListener > & xListener ); - explicit ImplChartModel( const ImplChartModel & rOther, - const ::com::sun::star::uno::Reference< - ::com::sun::star::util::XModifyListener > & xListener ); - ~ImplChartModel(); - -// ::com::sun::star::uno::Sequence< -// ::com::sun::star::uno::Reference< -// ::com::sun::star::chart2::XDataSeries > > -// GetDataSeries() const; - - ::com::sun::star::uno::Reference< - ::com::sun::star::container::XNameAccess > - GetStyleFamilies(); - - // Diagram Access - void RemoveAllDiagrams(); - /** @return true, if the chart was found and removed, false otherwise. - */ - void AppendDiagram( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XDiagram > & xDiagram ); - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XDiagram > - GetDiagram( size_t nIndex ) const - throw( ::com::sun::star::container::NoSuchElementException ); - - void SetDataProvider( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataProvider > & xProvider ); - - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataProvider > GetDataProvider() const; - - void CreateInternalDataProvider( - bool bCloneExistingData, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > & xChartDoc ); - - bool HasInternalDataProvider() const; - - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSource > SAL_CALL SetArguments( - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > & rArgs, - bool bSetData ) - throw (::com::sun::star::lang::IllegalArgumentException); - - void SetChartTypeManager( - const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XChartTypeManager > & xManager ); - - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XChartTypeManager > - GetChartTypeManager(); - - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XChartTypeTemplate > - GetChartTypeTemplate(); - - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTitle > - GetTitle(); - - void SetTitle( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XTitle >& rTitle ); - - /** Is called by the ChartModel's XComponent::dispose() to notify the - impl-class to release resources - */ - void dispose(); - - ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > - GetPageBackground(); - - void CreateDefaultChart(); - - ::com::sun::star::uno::Reference< - ::com::sun::star::uno::XInterface > GetXMLNameSpaceMap() const; - - ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > - GetNumberFormatsSupplier(); - - void SetNumberFormatsSupplier( - const ::com::sun::star::uno::Reference< - ::com::sun::star::util::XNumberFormatsSupplier > & xNumberFormatsSupplier ); - -private: - void CreateDefaultChartTypeTemplate(); - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSource > CreateDefaultData(); - void SetNewData( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSource > & xDataSource, - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > & rArgs ); - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSource > SAL_CALL SetRangeRepresentation( - const ::rtl::OUString & rRangeRepresentation, bool bSetData ) - throw (::com::sun::star::lang::IllegalArgumentException); - -// void CreateDefaultLayout(); - - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; - ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xFamilies; - - ::boost::shared_ptr< ChartData > m_spChartData; - - // Data Access (deprecated, temporary solution) -// ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > m_xChartData; -// ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > m_xDataProvider; - -// ::std::vector< ::com::sun::star::uno::Reference< -// ::com::sun::star::chart2::XDataSeries > > m_aInterpretedData; - - ::com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier > - m_xOwnNumberFormatsSupplier; - ::com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier > - m_xNumberFormatsSupplier; - - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartTypeManager > - m_xChartTypeManager; - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartTypeTemplate > - m_xChartTypeTemplate; - - // Diagram Access - typedef ::std::vector< ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XDiagram > > - tDiagramContainer; - - tDiagramContainer m_aDiagrams; - - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTitle > - m_xTitle; - - bool m_bIsDisposed; - ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > - m_xPageBackground; - - ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> m_xXMLNamespaceMap; - - ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > m_xModifyListener; -}; - -} // namespace impl -} // namespace chart - -// CHART_IMPLCHARTMODEL_HXX -#endif diff --git a/chart2/source/model/main/InternalData.cxx b/chart2/source/model/main/InternalData.cxx deleted file mode 100644 index 860715825af4..000000000000 --- a/chart2/source/model/main/InternalData.cxx +++ /dev/null @@ -1,257 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_chart2.hxx" - -#include "InternalData.hxx" -#include "macros.hxx" -#include <com/sun/star/embed/XEmbedPersist.hpp> -#include <com/sun/star/embed/XEmbedObjectCreator.hpp> -#include <com/sun/star/chart2/data/XDataProvider.hpp> -#include <com/sun/star/util/XCloseable.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> -#include <com/sun/star/uno/XComponentContext.hpp> -#include <sot/clsids.hxx> - -using namespace ::com::sun::star; - -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; -using ::rtl::OUString; - -namespace -{ -/** convert a class-id macro into a byte-sequence - call e.g. lcl_GetSequenceClassID( SO3_SC_CLASSID_60 ) - */ -Sequence< sal_Int8 > lcl_GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, - sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, - sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 ) -{ - Sequence< sal_Int8 > aResult( 16 ); - aResult[0] = static_cast<sal_Int8>(n1 >> 24); - aResult[1] = static_cast<sal_Int8>(( n1 << 8 ) >> 24); - aResult[2] = static_cast<sal_Int8>(( n1 << 16 ) >> 24); - aResult[3] = static_cast<sal_Int8>(( n1 << 24 ) >> 24); - aResult[4] = n2 >> 8; - aResult[5] = ( n2 << 8 ) >> 8; - aResult[6] = n3 >> 8; - aResult[7] = ( n3 << 8 ) >> 8; - aResult[8] = b8; - aResult[9] = b9; - aResult[10] = b10; - aResult[11] = b11; - aResult[12] = b12; - aResult[13] = b13; - aResult[14] = b14; - aResult[15] = b15; - - return aResult; -} - -Reference< embed::XStorage > lcl_CreateTempStorage( - const Reference< lang::XMultiServiceFactory > & rFactory ) -{ - Reference< embed::XStorage > xResult; - - try - { - Reference< lang::XSingleServiceFactory > xStorageFact( - rFactory->createInstance( C2U( "com.sun.star.embed.StorageFactory" )), - uno::UNO_QUERY_THROW ); - xResult.set( xStorageFact->createInstance(), uno::UNO_QUERY_THROW ); - } - catch( uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - - return xResult; -} - -} // anonymous namespace - - - -namespace chart -{ - -//explicit -InternalData::InternalData( - const Reference< uno::XComponentContext > & xContext, - const Reference< embed::XStorage > & xParentStorage ) : - m_aDataStorageName( RTL_CONSTASCII_USTRINGPARAM("ChartData")), - m_xContext( xContext ), - m_xParentStorage( xParentStorage ) -{} - -InternalData::~InternalData() -{ -} - -void SAL_CALL InternalData::saveObject() - throw (embed::ObjectSaveVetoException, - uno::Exception, - uno::RuntimeException) -{ - if( m_xInternalData.is()) - { - try - { - Reference< embed::XEmbedPersist > xPersist( m_xInternalData, uno::UNO_QUERY_THROW ); - xPersist->storeOwn(); - } - catch( uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - } -} - -void SAL_CALL InternalData::visibilityChanged( sal_Bool bVisible ) - throw (embed::WrongStateException, - uno::RuntimeException) -{ - // ignore (this is for swapping OLE objects?) -} - -Reference< util::XCloseable > SAL_CALL InternalData::getComponent() - throw (uno::RuntimeException) -{ - return Reference< util::XCloseable >( m_xInternalData, uno::UNO_QUERY ); -} - -// ____ XCloseListener ____ -void SAL_CALL InternalData::queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) - throw (util::CloseVetoException, - uno::RuntimeException) -{ - // empty -} - -void SAL_CALL InternalData::notifyClosing( const lang::EventObject& Source ) - throw (uno::RuntimeException) -{ - try - { - Reference< util::XCloseable > xCloseable( m_xInternalData, uno::UNO_QUERY ); - if( xCloseable.is()) - xCloseable->close( /* DeliverOwnership */ sal_False ); - - Reference< lang::XComponent > xComp( m_xInternalData, uno::UNO_QUERY ); - if( xComp.is()) - xComp->dispose(); - m_xInternalData = 0; - } - catch( const util::CloseVetoException & ) - { - throw; - } - catch( const uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } -} - - // ____ XEventListener ____ -void SAL_CALL InternalData::disposing( - const lang::EventObject& Source ) - throw (uno::RuntimeException) -{ - // empty -} - -Reference< chart2::data::XDataProvider > InternalData::createEmbeddedObject() throw() -{ - OSL_ASSERT( m_xContext.is()); - Reference< chart2::data::XDataProvider > xResult; - - try - { - if( ! m_xInternalData.is() && m_xContext.is()) - { - Reference< lang::XMultiServiceFactory > xFactory( - m_xContext->getServiceManager(), uno::UNO_QUERY_THROW ); - Reference< embed::XEmbedObjectCreator > xCreator( - xFactory->createInstance( - C2U( "com.sun.star.embed.EmbeddedObjectCreator")), uno::UNO_QUERY_THROW ); - - Reference< embed::XStorage > xStorage( m_xParentStorage ); - if( !xStorage.is()) - { - // as we don't store the spreadsheet as substorage in the final - // document, it is ok, or maybe even better to create a - // temporary storage -// OSL_ENSURE( false, "Using temporary storage for chart data!" ); - xStorage.set( lcl_CreateTempStorage( xFactory )); - } - - m_xInternalData.set( - xCreator->createInstanceInitNew( - lcl_GetSequenceClassID( SO3_SC_CLASSID_60 ), - C2U( "ChartDataEditor" ), - xStorage, - m_aDataStorageName, - Sequence< beans::PropertyValue >() ), uno::UNO_QUERY_THROW ); - - m_xInternalData->setClientSite( this ); - - xFactory.set( m_xInternalData->getComponent(), uno::UNO_QUERY_THROW ); - xResult.set( - xFactory->createInstance( C2U( "com.sun.star.chart2.data.DataProvider" )), uno::UNO_QUERY_THROW ); - } - } - catch( uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - - return xResult; -} - -void InternalData::removeEmbeddedObject() throw() -{ - if( m_xParentStorage.is()) - { - try - { - m_xParentStorage->removeElement( m_aDataStorageName ); - } - catch( uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - } -} - -Reference< embed::XEmbeddedObject > InternalData::getEmbeddedObject() const throw() -{ - return m_xInternalData; -} - -} // namespace chart diff --git a/chart2/source/model/main/InternalData.hxx b/chart2/source/model/main/InternalData.hxx deleted file mode 100644 index 15b3e9d0e8f0..000000000000 --- a/chart2/source/model/main/InternalData.hxx +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef CHART2_INTERNALDATA_HXX -#define CHART2_INTERNALDATA_HXX - -#include <com/sun/star/embed/XEmbeddedClient.hpp> -#include <com/sun/star/embed/XEmbeddedObject.hpp> -#include <com/sun/star/util/XCloseListener.hpp> -#include <cppuhelper/implbase2.hxx> - -namespace com { namespace sun { namespace star { - namespace uno { - class XComponentContext; - } - namespace embed { - class XStorage; - class XEmbeddedObject; - } - namespace chart2 { - namespace data { - class XDataProvider; - } - } -}}} - -namespace chart -{ - -class InternalData : - public ::cppu::WeakImplHelper2< - ::com::sun::star::embed::XEmbeddedClient, - ::com::sun::star::util::XCloseListener > -{ -public: - explicit InternalData( - const ::com::sun::star::uno::Reference< - ::com::sun::star::uno::XComponentContext > & xContext, - const ::com::sun::star::uno::Reference< - ::com::sun::star::embed::XStorage > & xParentStorage ); - virtual ~InternalData(); - - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataProvider > createEmbeddedObject() throw(); - - void removeEmbeddedObject() throw(); - - ::com::sun::star::uno::Reference< - ::com::sun::star::embed::XEmbeddedObject > getEmbeddedObject() const throw(); - - // ____ XEmbeddedClient ____ - virtual void SAL_CALL saveObject() - throw (::com::sun::star::embed::ObjectSaveVetoException, - ::com::sun::star::uno::Exception, - ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) - throw (::com::sun::star::embed::WrongStateException, - ::com::sun::star::uno::RuntimeException); - - // ____ XComponentSupplier ____ - virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > SAL_CALL getComponent() - throw (::com::sun::star::uno::RuntimeException); - - // ____ XCloseListener ____ - virtual void SAL_CALL queryClosing( - const ::com::sun::star::lang::EventObject& Source, - ::sal_Bool GetsOwnership ) - throw (::com::sun::star::util::CloseVetoException, - ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL notifyClosing( - const ::com::sun::star::lang::EventObject& Source ) - throw (::com::sun::star::uno::RuntimeException); - - // ____ XEventListener ____ - virtual void SAL_CALL disposing( - const ::com::sun::star::lang::EventObject& Source ) - throw (::com::sun::star::uno::RuntimeException); - -private: - const ::rtl::OUString m_aDataStorageName; - - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > - m_xContext; - - ::com::sun::star::uno::Reference< ::com::sun::star::embed::XEmbeddedObject > - m_xInternalData; - - ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > - m_xParentStorage; -}; - -} // namespace chart - -// CHART2_INTERNALDATA_HXX -#endif diff --git a/chart2/source/model/main/makefile.mk b/chart2/source/model/main/makefile.mk index b4d74a878584..8e963dfa0f5c 100644 --- a/chart2/source/model/main/makefile.mk +++ b/chart2/source/model/main/makefile.mk @@ -46,7 +46,6 @@ SLOFILES= \ $(SLO)$/GridProperties.obj \ $(SLO)$/BaseCoordinateSystem.obj \ $(SLO)$/CartesianCoordinateSystem.obj \ - $(SLO)$/ChartData.obj \ $(SLO)$/ChartModel.obj \ $(SLO)$/ChartModel_Persistence.obj \ $(SLO)$/DataPoint.obj \ @@ -55,7 +54,6 @@ SLOFILES= \ $(SLO)$/Diagram.obj \ $(SLO)$/DataSeriesProperties.obj \ $(SLO)$/FormattedString.obj \ - $(SLO)$/ImplChartModel.obj \ $(SLO)$/Legend.obj \ $(SLO)$/PageBackground.obj \ $(SLO)$/PolarCoordinateSystem.obj \ diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.cxx b/chart2/source/model/template/BubbleChartTypeTemplate.cxx index 706db07f8288..3f297d1e2e27 100644 --- a/chart2/source/model/template/BubbleChartTypeTemplate.cxx +++ b/chart2/source/model/template/BubbleChartTypeTemplate.cxx @@ -178,12 +178,6 @@ StackMode BubbleChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ return StackMode_NONE; } -bool BubbleChartTypeTemplate::supportsCategories() const -{ - return false; -} - - void SAL_CALL BubbleChartTypeTemplate::applyStyle( const Reference< chart2::XDataSeries >& xSeries, ::sal_Int32 nChartTypeIndex, @@ -203,10 +197,10 @@ void SAL_CALL BubbleChartTypeTemplate::applyStyle( } // ____ XChartTypeTemplate ____ -Sequence< OUString > SAL_CALL BubbleChartTypeTemplate::getAvailableCreationParameterNames() +sal_Bool SAL_CALL BubbleChartTypeTemplate::supportsCategories() throw (uno::RuntimeException) { - return Sequence< OUString >(); + return false; } sal_Bool SAL_CALL BubbleChartTypeTemplate::matchesTemplate( diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.hxx b/chart2/source/model/template/BubbleChartTypeTemplate.hxx index 27259f877805..24d35c6acbb7 100644 --- a/chart2/source/model/template/BubbleChartTypeTemplate.hxx +++ b/chart2/source/model/template/BubbleChartTypeTemplate.hxx @@ -67,7 +67,7 @@ protected: throw (::com::sun::star::uno::RuntimeException); // ____ XChartTypeTemplate ____ - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableCreationParameterNames() + virtual sal_Bool SAL_CALL supportsCategories() throw (::com::sun::star::uno::RuntimeException); virtual sal_Bool SAL_CALL matchesTemplate( const ::com::sun::star::uno::Reference< @@ -93,8 +93,6 @@ protected: getChartTypeForIndex( sal_Int32 nChartTypeIndex ); virtual sal_Int32 getDimension() const; virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const; - - virtual bool supportsCategories() const; }; } // namespace chart diff --git a/chart2/source/model/template/BubbleDataInterpreter.cxx b/chart2/source/model/template/BubbleDataInterpreter.cxx index b69055a9e632..1f26fff907e4 100644 --- a/chart2/source/model/template/BubbleDataInterpreter.cxx +++ b/chart2/source/model/template/BubbleDataInterpreter.cxx @@ -78,8 +78,6 @@ chart2::InterpretedData SAL_CALL BubbleDataInterpreter::interpretDataSource( Reference< data::XLabeledDataSequence > xCategories; bool bHasCategories = HasCategories( aArguments, aData ); - Sequence< Reference< data::XLabeledDataSequence > > aUnusedData; - bool bHasXValues = false; sal_Int32 nDataSeqCount = aData.getLength(); @@ -170,7 +168,7 @@ chart2::InterpretedData SAL_CALL BubbleDataInterpreter::interpretDataSource( Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); aSeries[0] = ContainerHelper::ContainerToSequence( aSeriesVec ); - return InterpretedData( aSeries, xCategories, aUnusedData ); + return InterpretedData( aSeries, xCategories ); } chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( @@ -178,8 +176,6 @@ chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( throw (uno::RuntimeException) { InterpretedData aResult( aInterpretedData ); - vector< Reference< data::XLabeledDataSequence > > aUnused( - ContainerHelper::SequenceToVector( aInterpretedData.UnusedData )); sal_Int32 i=0; Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); @@ -266,17 +262,15 @@ chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); if( aSeqs.getLength() != aNewSequences.getLength() ) { +#if OSL_DEBUG_LEVEL > 1 sal_Int32 j=0; for( ; j<aSeqs.getLength(); ++j ) { - if( aSeqs[j] != xValuesY && - aSeqs[j] != xValuesX && - aSeqs[j] != xValuesSize ) - aUnused.push_back( aSeqs[j] ); + OSL_ENSURE( aSeqs[j] == xValuesY || aSeqs[j] == xValuesX || aSeqs[j] == xValuesSize, "All sequences should be used" ); } +#endif Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); xSink->setData( aNewSequences ); - aResult.UnusedData = ContainerHelper::ContainerToSequence( aUnused ); } } catch( uno::Exception & ex ) diff --git a/chart2/source/model/template/ChartTypeTemplate.cxx b/chart2/source/model/template/ChartTypeTemplate.cxx index 2fd0ca2a1d89..393321a19d55 100644 --- a/chart2/source/model/template/ChartTypeTemplate.cxx +++ b/chart2/source/model/template/ChartTypeTemplate.cxx @@ -192,11 +192,10 @@ uno::Reference< XDiagram > SAL_CALL ChartTypeTemplate::createDiagramByDataSource return xDia; } -Sequence< OUString > SAL_CALL ChartTypeTemplate::getAvailableCreationParameterNames() +sal_Bool SAL_CALL ChartTypeTemplate::supportsCategories() throw (uno::RuntimeException) { - OUString aHasCat( C2U("HasCategories")); - return Sequence< OUString >( & aHasCat, 1 ); + return sal_True; } void SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram >& xDiagram ) @@ -217,10 +216,8 @@ void SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram > chart2::InterpretedData aData; aData.Series = aSeriesSeq; aData.Categories = DiagramHelper::getCategoriesFromDiagram( xDiagram ); - aData.UnusedData = xDiagram->getUnusedData(); - if( (aData.UnusedData.getLength() == 0) && - xInterpreter->isDataCompatible( aData )) + if( xInterpreter->isDataCompatible( aData ) ) { aData = xInterpreter->reinterpretDataSeries( aData ); } @@ -238,32 +235,9 @@ void SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram > aParam[0] = beans::PropertyValue( C2U("HasCategories"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); } - else if( aData.UnusedData.getLength()) - { - for( sal_Int32 i=0; i<aData.UnusedData.getLength(); ++i ) - try - { - Reference< beans::XPropertySet > xProp( aData.UnusedData[i]->getValues(), uno::UNO_QUERY_THROW ); - OUString aRole; - if( (xProp->getPropertyValue(C2U("Role")) >>= aRole) & - aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) ) - { - aData.Categories = aData.UnusedData[i]; - for( ++i; i<aData.UnusedData.getLength(); ++i ) - aData.UnusedData[i-1] = aData.UnusedData[i]; - aData.UnusedData.realloc( aData.UnusedData.getLength() - 1 ); - break; - } - } - catch( const uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - } aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq ); } aSeriesSeq = aData.Series; - xDiagram->setUnusedData( aData.UnusedData ); sal_Int32 i, j, nIndex = 0; for( i=0; i<aSeriesSeq.getLength(); ++i ) @@ -583,11 +557,6 @@ bool ChartTypeTemplate::isSwapXAndY() const return false; } -bool ChartTypeTemplate::supportsCategories() const -{ - return true; -} - // ________________________________________ void ChartTypeTemplate::createCoordinateSystems( @@ -661,7 +630,7 @@ void ChartTypeTemplate::adaptScales( const Reference< data::XLabeledDataSequence > & xCategories //@todo: in future there may be more than one sequence of categories (e.g. charttype with categories at x and y axis ) ) { - bool bSupportsCategories( supportsCategories()); + bool bSupportsCategories( supportsCategories() ); for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx ) { try diff --git a/chart2/source/model/template/ChartTypeTemplate.hxx b/chart2/source/model/template/ChartTypeTemplate.hxx index 2247c13ec940..3f43e0ca6038 100644 --- a/chart2/source/model/template/ChartTypeTemplate.hxx +++ b/chart2/source/model/template/ChartTypeTemplate.hxx @@ -100,7 +100,8 @@ protected: const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource >& xDataSource, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArguments ) throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableCreationParameterNames() + /// denotes if the chart needs categories at the first scale + virtual sal_Bool SAL_CALL supportsCategories() throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL changeDiagram( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDiagram >& xDiagram ) @@ -158,9 +159,6 @@ protected: virtual bool isSwapXAndY() const; - /// denotes if the chart needs categories at the first scale - virtual bool supportsCategories() const; - // Methods for creating the diagram piecewise // ------------------------------------------ diff --git a/chart2/source/model/template/DataInterpreter.cxx b/chart2/source/model/template/DataInterpreter.cxx index 6d5b85fd3e4b..b619553ee959 100644 --- a/chart2/source/model/template/DataInterpreter.cxx +++ b/chart2/source/model/template/DataInterpreter.cxx @@ -149,7 +149,7 @@ InterpretedData SAL_CALL DataInterpreter::interpretDataSource( Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); aSeries[0] = ContainerToSequence( aSeriesVec ); - return InterpretedData( aSeries, xCategories, Sequence< Reference< data::XLabeledDataSequence > >() ); + return InterpretedData( aSeries, xCategories ); } InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries( @@ -157,8 +157,6 @@ InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries( throw (uno::RuntimeException) { InterpretedData aResult( aInterpretedData ); - vector< Reference< data::XLabeledDataSequence > > aUnused( - SequenceToVector( aInterpretedData.UnusedData )); sal_Int32 i=0; Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); @@ -190,14 +188,14 @@ InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries( Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); if( aSeqs.getLength() != aNewSequences.getLength() ) { +#if OSL_DEBUG_LEVEL > 1 sal_Int32 j=0; for( ; j<aSeqs.getLength(); ++j ) { - if( aSeqs[j] != xValuesY ) - aUnused.push_back( aSeqs[j] ); + OSL_ENSURE( aSeqs[j] == xValuesY, "All sequences should be used" ); } +#endif Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); - xSink->setData( aNewSequences ); } } @@ -207,8 +205,6 @@ InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries( } } - aResult.UnusedData = ContainerToSequence( aUnused ); - return aResult; } @@ -294,34 +290,13 @@ Reference< data::XDataSource > SAL_CALL DataInterpreter::mergeInterpretedData( throw (uno::RuntimeException) { vector< Reference< data::XLabeledDataSequence > > aResultVec; - vector< Reference< data::XLabeledDataSequence > > aUnusedDataVec; aResultVec.reserve( aInterpretedData.Series.getLength() + - aInterpretedData.UnusedData.getLength() + 1 // categories ); if( aInterpretedData.Categories.is()) aResultVec.push_back( aInterpretedData.Categories ); - // add unused data that has the Role categories at front - if( aInterpretedData.UnusedData.getLength()) - { - sal_Int32 nSize = aInterpretedData.UnusedData.getLength(); - for( sal_Int32 i=0; i<nSize; ++i ) - { - Reference< data::XLabeledDataSequence > xPotentialCategories( aInterpretedData.UnusedData[i] ); - if( xPotentialCategories.is() ) - { - if( GetRole( xPotentialCategories->getValues()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("categories"))) - aResultVec.push_back( xPotentialCategories ); - else - aUnusedDataVec.push_back( xPotentialCategories ); - } - } - } - else - aUnusedDataVec = SequenceToVector( aInterpretedData.UnusedData ); - Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx ) { @@ -349,9 +324,6 @@ Reference< data::XDataSource > SAL_CALL DataInterpreter::mergeInterpretedData( } } - // add unused data at end - copy( aUnusedDataVec.begin(), aUnusedDataVec.end(), back_inserter( aResultVec )); - return Reference< data::XDataSource >( DataSourceHelper::createDataSource( ContainerToSequence( aResultVec ) ) ); } diff --git a/chart2/source/model/template/ScatterChartTypeTemplate.cxx b/chart2/source/model/template/ScatterChartTypeTemplate.cxx index 7c83e80d7234..f952abaa3611 100644 --- a/chart2/source/model/template/ScatterChartTypeTemplate.cxx +++ b/chart2/source/model/template/ScatterChartTypeTemplate.cxx @@ -219,12 +219,6 @@ StackMode ScatterChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex * return StackMode_NONE; } -bool ScatterChartTypeTemplate::supportsCategories() const -{ - return false; -} - - void SAL_CALL ScatterChartTypeTemplate::applyStyle( const Reference< chart2::XDataSeries >& xSeries, ::sal_Int32 nChartTypeIndex, @@ -249,10 +243,10 @@ void SAL_CALL ScatterChartTypeTemplate::applyStyle( } // ____ XChartTypeTemplate ____ -Sequence< OUString > SAL_CALL ScatterChartTypeTemplate::getAvailableCreationParameterNames() +sal_Bool SAL_CALL ScatterChartTypeTemplate::supportsCategories() throw (uno::RuntimeException) { - return Sequence< OUString >(); + return sal_False; } sal_Bool SAL_CALL ScatterChartTypeTemplate::matchesTemplate( diff --git a/chart2/source/model/template/ScatterChartTypeTemplate.hxx b/chart2/source/model/template/ScatterChartTypeTemplate.hxx index 6cb15247a0d9..048cca73a92c 100644 --- a/chart2/source/model/template/ScatterChartTypeTemplate.hxx +++ b/chart2/source/model/template/ScatterChartTypeTemplate.hxx @@ -71,7 +71,7 @@ protected: throw (::com::sun::star::uno::RuntimeException); // ____ XChartTypeTemplate ____ - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableCreationParameterNames() + virtual sal_Bool SAL_CALL supportsCategories() throw (::com::sun::star::uno::RuntimeException); virtual sal_Bool SAL_CALL matchesTemplate( const ::com::sun::star::uno::Reference< @@ -98,8 +98,6 @@ protected: virtual sal_Int32 getDimension() const; virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const; - virtual bool supportsCategories() const; - private: bool m_bHasSymbols; bool m_bHasLines; diff --git a/chart2/source/model/template/StockDataInterpreter.cxx b/chart2/source/model/template/StockDataInterpreter.cxx index d7da1e7ea04c..0d134516a1bb 100644 --- a/chart2/source/model/template/StockDataInterpreter.cxx +++ b/chart2/source/model/template/StockDataInterpreter.cxx @@ -268,8 +268,7 @@ InterpretedData SAL_CALL StockDataInterpreter::interpretDataSource( } } - const Sequence< Reference< data::XLabeledDataSequence > > aUnusedData;//@todo remove the unused data concept completely - return InterpretedData( aResultSeries, xCategories, aUnusedData ); + return InterpretedData( aResultSeries, xCategories ); } // criterion: there must be two groups for stock-charts with volume and all @@ -302,7 +301,7 @@ sal_Bool SAL_CALL StockDataInterpreter::isDataCompatible( if( ! DataInterpreter::isDataCompatible( InterpretedData( Sequence< Sequence< Reference< XDataSeries > > >( aInterpretedData.Series.getConstArray(), 1 ), - aInterpretedData.Categories, aInterpretedData.UnusedData ))) + aInterpretedData.Categories ))) return sal_False; } diff --git a/chart2/source/model/template/XYDataInterpreter.cxx b/chart2/source/model/template/XYDataInterpreter.cxx index 0bf1e73562e4..839c0cbac510 100644 --- a/chart2/source/model/template/XYDataInterpreter.cxx +++ b/chart2/source/model/template/XYDataInterpreter.cxx @@ -79,8 +79,6 @@ chart2::InterpretedData SAL_CALL XYDataInterpreter::interpretDataSource( bool bHasCategories = HasCategories( aArguments, aData ); // parse data - Sequence< Reference< data::XLabeledDataSequence > > aUnusedData; - bool bCategoriesUsed = false; for( sal_Int32 nDataIdx= 0; nDataIdx < aData.getLength(); ++nDataIdx ) { @@ -157,7 +155,7 @@ chart2::InterpretedData SAL_CALL XYDataInterpreter::interpretDataSource( Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); aSeries[0] = ContainerHelper::ContainerToSequence( aSeriesVec ); - return InterpretedData( aSeries, xCategories, aUnusedData ); + return InterpretedData( aSeries, xCategories ); } chart2::InterpretedData SAL_CALL XYDataInterpreter::reinterpretDataSeries( @@ -165,8 +163,6 @@ chart2::InterpretedData SAL_CALL XYDataInterpreter::reinterpretDataSeries( throw (uno::RuntimeException) { InterpretedData aResult( aInterpretedData ); - vector< Reference< data::XLabeledDataSequence > > aUnused( - ContainerHelper::SequenceToVector( aInterpretedData.UnusedData )); sal_Int32 i=0; Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); @@ -230,16 +226,15 @@ chart2::InterpretedData SAL_CALL XYDataInterpreter::reinterpretDataSeries( Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); if( aSeqs.getLength() != aNewSequences.getLength() ) { +#if OSL_DEBUG_LEVEL > 1 sal_Int32 j=0; for( ; j<aSeqs.getLength(); ++j ) { - if( aSeqs[j] != xValuesY && - aSeqs[j] != xValuesX ) - aUnused.push_back( aSeqs[j] ); + OSL_ENSURE( aSeqs[j] == xValuesY || aSeqs[j] == xValuesX, "All sequences should be used" ); } +#endif Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); xSink->setData( aNewSequences ); - aResult.UnusedData = ContainerHelper::ContainerToSequence( aUnused ); } } catch( uno::Exception & ex ) diff --git a/chart2/source/tools/ChartModelHelper.cxx b/chart2/source/tools/ChartModelHelper.cxx index 8ce45e85038d..ed8c36e08c8d 100644 --- a/chart2/source/tools/ChartModelHelper.cxx +++ b/chart2/source/tools/ChartModelHelper.cxx @@ -62,23 +62,10 @@ uno::Reference< chart2::data::XRangeHighlighter > ChartModelHelper::createRangeH } //static -uno::Reference< chart2::data::XDataProvider > ChartModelHelper::createInternalDataProvider() -{ - return new InternalDataProvider(); -} - -//static uno::Reference< chart2::data::XDataProvider > ChartModelHelper::createInternalDataProvider( - const uno::Reference< ::com::sun::star::chart::XChartDataArray >& xDataToCopy ) + const uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDoc, bool bConnectToModel ) { - return new InternalDataProvider( xDataToCopy ); -} - -//static -uno::Reference< chart2::data::XDataProvider > ChartModelHelper::createInternalDataProvider( - const uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDoc ) -{ - return new InternalDataProvider( xChartDoc ); + return new InternalDataProvider( xChartDoc, bConnectToModel ); } //static @@ -105,6 +92,20 @@ uno::Reference< XDiagram > ChartModelHelper::findDiagram( const uno::Reference< return NULL; } +//static +uno::Reference< XCoordinateSystem > ChartModelHelper::getFirstCoordinateSystem( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XCoordinateSystem > XCooSys; + uno::Reference< XCoordinateSystemContainer > xCooSysCnt( ChartModelHelper::findDiagram( xModel ), uno::UNO_QUERY ); + if( xCooSysCnt.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); + if( aCooSysSeq.getLength() ) + XCooSys = aCooSysSeq[0]; + } + return XCooSys; +} + // static ::std::vector< uno::Reference< XDataSeries > > ChartModelHelper::getDataSeries( const uno::Reference< XChartDocument > & xChartDoc ) diff --git a/chart2/source/tools/DataSourceHelper.cxx b/chart2/source/tools/DataSourceHelper.cxx index 837f07432e32..0cc6ef4a4315 100644 --- a/chart2/source/tools/DataSourceHelper.cxx +++ b/chart2/source/tools/DataSourceHelper.cxx @@ -298,18 +298,13 @@ uno::Sequence< ::rtl::OUString > DataSourceHelper::getUsedDataRanges( const uno: } uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( - const uno::Reference< chart2::XChartDocument >& xChartDoc, - bool bIncludeUnusedData /* = false */ ) + const uno::Reference< chart2::XChartDocument >& xChartDoc ) { - if( bIncludeUnusedData ) - return getUsedData( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ), bIncludeUnusedData ); - else - return pressUsedDataIntoRectangularFormat( xChartDoc ); + return pressUsedDataIntoRectangularFormat( xChartDoc ); } uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( - const uno::Reference< frame::XModel >& xChartModel, - bool bIncludeUnusedData /* = false */ ) + const uno::Reference< frame::XModel >& xChartModel ) { ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult; @@ -330,14 +325,6 @@ uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( ::std::back_inserter( aResult )); } - if( bIncludeUnusedData && xDiagram.is()) - { - uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aUnusedData( xDiagram->getUnusedData()); - ::std::copy( aUnusedData.getConstArray(), - aUnusedData.getConstArray() + aUnusedData.getLength(), - ::std::back_inserter( aResult )); - } - return uno::Reference< chart2::data::XDataSource >( new DataSource( ContainerHelper::ContainerToSequence( aResult ))); } @@ -349,8 +336,7 @@ bool DataSourceHelper::detectRangeSegmentation( , ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping , bool& rOutUseColumns , bool& rOutFirstCellAsLabel - , bool& rOutHasCategories - , bool bIncludeUnusedData /* = false */) + , bool& rOutHasCategories ) { bool bSomethingDetected = false; @@ -361,9 +347,6 @@ bool DataSourceHelper::detectRangeSegmentation( if( !xDataProvider.is() ) return bSomethingDetected; - OSL_ASSERT( !bIncludeUnusedData ); //bIncludeUnusedData is not supported currently - (void)(bIncludeUnusedData); // avoid warning in non-debug build - try { DataSourceHelper::readArguments( @@ -531,6 +514,19 @@ Sequence< OUString > DataSourceHelper::getRangesFromLabeledDataSequence( return aResult; } +OUString DataSourceHelper::getRangeFromValues( + const Reference< data::XLabeledDataSequence > & xLSeq ) +{ + OUString aResult; + if( xLSeq.is() ) + { + Reference< data::XDataSequence > xValues( xLSeq->getValues() ); + if( xValues.is() ) + aResult = xValues->getSourceRangeRepresentation(); + } + return aResult; +} + Sequence< OUString > DataSourceHelper::getRangesFromDataSource( const Reference< data::XDataSource > & xSource ) { ::std::vector< OUString > aResult; diff --git a/chart2/source/tools/DiagramHelper.cxx b/chart2/source/tools/DiagramHelper.cxx index 31ac5f1ae4ec..a8da65e5133d 100644 --- a/chart2/source/tools/DiagramHelper.cxx +++ b/chart2/source/tools/DiagramHelper.cxx @@ -35,7 +35,9 @@ #include "AxisHelper.hxx" #include "ContainerHelper.hxx" #include "ChartTypeHelper.hxx" +#include "ChartModelHelper.hxx" #include "CommonConverters.hxx" +#include "ExplicitCategoriesProvider.hxx" #include "servicenames_charttypes.hxx" #include <com/sun/star/chart/MissingValueTreatment.hpp> @@ -955,8 +957,7 @@ Reference< data::XLabeledDataSequence > return xResult; } -//static -void DiagramHelper::generateAutomaticCategoriesFromChartType( +void lcl_generateAutomaticCategoriesFromChartType( Sequence< rtl::OUString >& rRet, const Reference< XChartType >& xChartType ) { @@ -986,64 +987,35 @@ void DiagramHelper::generateAutomaticCategoriesFromChartType( } } -//static -Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategories( - const Reference< XChartDocument >& xChartDoc ) +Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference< XCoordinateSystem > & xCooSys ) { Sequence< rtl::OUString > aRet; - if(xChartDoc.is()) + + Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY ); + if( xTypeCntr.is() ) { - uno::Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram() ); - if(xDia.is()) + Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() ); + for( sal_Int32 nN=0; nN<aChartTypes.getLength(); nN++ ) { - Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDia ) ); - if( xCategories.is() ) - aRet = DataSequenceToStringSequence(xCategories->getValues()); - if( !aRet.getLength() ) - { - /* - //unused ranges are very problematic as they bear the risk to damage the rectangular structure completly - if( bUseUnusedDataAlso ) - { - Sequence< Reference< chart2::data::XLabeledDataSequence > > aUnusedSequences( xDia->getUnusedData() ); - ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aUnusedCategoryVector( - DataSeriesHelper::getAllDataSequencesByRole( aUnusedSequences, C2U("categories") ) ); - if( aUnusedCategoryVector.size() && aUnusedCategoryVector[0].is() ) - aRet = DataSequenceToStringSequence(aUnusedCategoryVector[0]->getValues()); - } - */ - if( !aRet.getLength() ) - { - Reference< XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY ); - if( xCooSysCnt.is() ) - { - Sequence< Reference< XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); - if( aCooSysSeq.getLength() ) - aRet = DiagramHelper::generateAutomaticCategories( aCooSysSeq[0] ); - } - } - } + lcl_generateAutomaticCategoriesFromChartType( aRet, aChartTypes[nN] ); + if( aRet.getLength() ) + return aRet; } } return aRet; } //static -Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategories( - const Reference< XCoordinateSystem > & xCooSys ) +Sequence< rtl::OUString > DiagramHelper::getExplicitSimpleCategories( + const Reference< XChartDocument >& xChartDoc ) { Sequence< rtl::OUString > aRet; - - Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY ); - if( xTypeCntr.is() ) + uno::Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY ); + if(xChartModel.is()) { - Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() ); - for( sal_Int32 nN=0; nN<aChartTypes.getLength(); nN++ ) - { - DiagramHelper::generateAutomaticCategoriesFromChartType( aRet, aChartTypes[nN] ); - if( aRet.getLength() ) - return aRet; - } + uno::Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) ); + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, xChartModel ); + aRet = aExplicitCategoriesProvider.getSimpleCategories(); } return aRet; } diff --git a/chart2/source/tools/ExplicitCategoriesProvider.cxx b/chart2/source/tools/ExplicitCategoriesProvider.cxx index cd4b0334f117..bd1c1bb79813 100644 --- a/chart2/source/tools/ExplicitCategoriesProvider.cxx +++ b/chart2/source/tools/ExplicitCategoriesProvider.cxx @@ -31,6 +31,10 @@ #include "ExplicitCategoriesProvider.hxx" #include "DiagramHelper.hxx" #include "CommonConverters.hxx" +#include "DataSourceHelper.hxx" +#include "ChartModelHelper.hxx" +#include "ContainerHelper.hxx" +#include "macros.hxx" //............................................................................. namespace chart @@ -41,18 +45,88 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; -using rtl::OUString; +using ::rtl::OUString; +using ::std::vector; -ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel ) + +ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel + , const uno::Reference< frame::XModel >& xChartModel ) : m_bDirty(true) , m_xCooSysModel( xCooSysModel ) - , m_xCategories() + , m_xOriginalCategories() { - if( xCooSysModel.is() ) + try + { + if( xCooSysModel.is() ) + { + uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) ); + if( xAxis.is() ) + m_xOriginalCategories = xAxis->getScaleData().Categories; + } + + if( m_xOriginalCategories.is() ) + { + Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); + if( xChartDoc.is() ) + { + uno::Reference< data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() ); + + if( xDataProvider.is() ) + { + OUString aCatgoriesRange( DataSourceHelper::getRangeFromValues( m_xOriginalCategories ) ); + const bool bFirstCellAsLabel = false; + const bool bHasCategories = false; + const uno::Sequence< sal_Int32 > aSequenceMapping; + + uno::Reference< data::XDataSource > xColumnCategoriesSource( xDataProvider->createDataSource( + DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, true /*bUseColumns*/ + , bFirstCellAsLabel, bHasCategories ) ) ); + + uno::Reference< data::XDataSource > xRowCategoriesSource( xDataProvider->createDataSource( + DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, false /*bUseColumns*/ + , bFirstCellAsLabel, bHasCategories ) ) ); + + if( xColumnCategoriesSource.is() && xRowCategoriesSource.is() ) + { + Sequence< Reference< data::XLabeledDataSequence> > aColumns = xColumnCategoriesSource->getDataSequences(); + Sequence< Reference< data::XLabeledDataSequence> > aRows = xRowCategoriesSource->getDataSequences(); + + sal_Int32 nColumnCount = aColumns.getLength(); + sal_Int32 nRowCount = aRows.getLength(); + if( nColumnCount>1 && nRowCount>1 ) + { + //we have complex categories + //->split them in the direction of the first series + //detect whether the first series is a row or a column + bool bSeriesUsesColumns = true; + ::std::vector< Reference< XDataSeries > > aSeries( ChartModelHelper::getDataSeries( xChartModel ) ); + if( !aSeries.empty() ) + { + uno::Reference< data::XDataSource > xSeriesSource( aSeries.front(), uno::UNO_QUERY ); + ::rtl::OUString aStringDummy; + bool bDummy; + uno::Sequence< sal_Int32 > aSeqDummy; + DataSourceHelper::readArguments( xDataProvider->detectArguments( xSeriesSource), + aStringDummy, aSeqDummy, bSeriesUsesColumns, bDummy, bDummy ); + } + if( bSeriesUsesColumns ) + m_aSplitCategoriesList=aColumns; + else + m_aSplitCategoriesList=aRows; + } + } + } + } + if( !m_aSplitCategoriesList.getLength() ) + { + m_aSplitCategoriesList.realloc(1); + m_aSplitCategoriesList[0]=m_xOriginalCategories; + } + } + } + catch( const uno::Exception & ex ) { - uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) ); - if( xAxis.is() ) - m_xCategories = xAxis->getScaleData().Categories; + ASSERT_EXCEPTION( ex ); } } @@ -60,34 +134,285 @@ ExplicitCategoriesProvider::~ExplicitCategoriesProvider() { } -//XTextualDataSequence -Sequence< ::rtl::OUString > SAL_CALL ExplicitCategoriesProvider::getTextualData() throw( uno::RuntimeException) +const Sequence< Reference< data::XLabeledDataSequence> >& ExplicitCategoriesProvider::getSplitCategoriesList() +{ + return m_aSplitCategoriesList; +} + +bool ExplicitCategoriesProvider::hasComplexCategories() const +{ + return m_aSplitCategoriesList.getLength() > 1; +} + +sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const +{ + sal_Int32 nCount = m_aSplitCategoriesList.getLength(); + if(!nCount) + nCount = 1; + return nCount; +} + +std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories ) +{ + std::vector<sal_Int32> aLimitingBorders; + std::vector< ComplexCategory >::const_iterator aIt( rComplexCategories.begin() ); + std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() ); + sal_Int32 nBorderIndex = 0; /*border below the index*/ + for( ; aIt != aEnd; ++aIt ) + { + ComplexCategory aComplexCategory(*aIt); + nBorderIndex += aComplexCategory.Count; + aLimitingBorders.push_back(nBorderIndex); + } + return aLimitingBorders; +} + +uno::Sequence< rtl::OUString > lcl_DataToStringSequence( const uno::Reference< data::XDataSequence >& xDataSequence ) +{ + uno::Sequence< rtl::OUString > aStrings; + + OSL_ASSERT( xDataSequence.is()); + if( !xDataSequence.is() ) + return aStrings; + + + uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY ); + if( xTextualDataSequence.is() ) + { + aStrings = xTextualDataSequence->getTextualData(); + } + else + { + uno::Sequence< uno::Any > aValues = xDataSequence->getData(); + aStrings.realloc(aValues.getLength()); + + for(sal_Int32 nN=aValues.getLength();nN--;) + aValues[nN] >>= aStrings[nN]; + } + + return aStrings; +} + +SplitCategoriesProvider::~SplitCategoriesProvider() +{ +} + +class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider +{ +public: + + explicit SplitCategoriesProvider_ForLabeledDataSequences( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence> >& rSplitCategoriesList ) + : m_rSplitCategoriesList( rSplitCategoriesList ) + {} + virtual ~SplitCategoriesProvider_ForLabeledDataSequences() + {} + + virtual sal_Int32 getLevelCount() const; + virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const; + +private: + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence> >& m_rSplitCategoriesList; +}; + +sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const +{ + return m_rSplitCategoriesList.getLength(); +} +uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForLabeledDataSequences::getStringsForLevel( sal_Int32 nLevel ) const +{ + uno::Sequence< rtl::OUString > aRet; + Reference< data::XLabeledDataSequence > xLabeledDataSequence( m_rSplitCategoriesList[nLevel] ); + if( xLabeledDataSequence.is() ) + aRet = lcl_DataToStringSequence( xLabeledDataSequence->getValues() ); + return aRet; +} + +std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector( + const uno::Sequence< rtl::OUString >& rStrings + , const std::vector<sal_Int32>& rLimitingBorders, bool bCreateSingleCategories ) +{ + std::vector< ComplexCategory > aResult; + + sal_Int32 nMaxCount = rStrings.getLength(); + OUString aPrevious; + sal_Int32 nCurrentCount=0; + for( sal_Int32 nN=0; nN<nMaxCount; nN++ ) + { + OUString aCurrent = rStrings[nN]; + if( bCreateSingleCategories || ::std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() ) + { + aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); + nCurrentCount=1; + aPrevious = aCurrent; + } + else + { + if( aCurrent.getLength() && aPrevious != aCurrent ) + { + aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); + nCurrentCount=1; + aPrevious = aCurrent; + } + else + nCurrentCount++; + } + } + if( nCurrentCount ) + aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); + + return aResult; +} + +sal_Int32 lcl_getCategoryCount( std::vector< ComplexCategory >& rComplexCategories ) +{ + sal_Int32 nCount = 0; + std::vector< ComplexCategory >::iterator aIt( rComplexCategories.begin() ); + std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() ); + for( ; aIt != aEnd; ++aIt ) + nCount+=aIt->Count; + return nCount; +} + +Sequence< OUString > lcl_getExplicitSimpleCategories( + const SplitCategoriesProvider& rSplitCategoriesProvider, + ::std::vector< ::std::vector< ComplexCategory > >& rComplexCats ) +{ + Sequence< OUString > aRet; + + rComplexCats.clear(); + sal_Int32 nLCount = rSplitCategoriesProvider.getLevelCount(); + for( sal_Int32 nL = 0; nL < nLCount; nL++ ) + { + std::vector<sal_Int32> aLimitingBorders; + if(nL>0) + aLimitingBorders = lcl_getLimitingBorders( rComplexCats.back() ); + rComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector( + rSplitCategoriesProvider.getStringsForLevel(nL), aLimitingBorders, nL==(nLCount-1) ) ); + } + + std::vector< std::vector< ComplexCategory > >::iterator aOuterIt( rComplexCats.begin() ); + std::vector< std::vector< ComplexCategory > >::const_iterator aOuterEnd( rComplexCats.end() ); + + //ensure that the category count is the same on each level + sal_Int32 nMaxCategoryCount = 0; + { + for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) + { + sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt ); + nMaxCategoryCount = std::max( nCurrentCount, nMaxCategoryCount ); + } + for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) + { + sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt ); + if( nCurrentCount< nMaxCategoryCount ) + { + ComplexCategory& rComplexCategory = aOuterIt->back(); + rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount); + } + } + } + + //create a list with an element for every index + std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex; + for( aOuterIt=rComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) + { + std::vector< ComplexCategory > aSingleLevel; + std::vector< ComplexCategory >::iterator aIt( aOuterIt->begin() ); + std::vector< ComplexCategory >::const_iterator aEnd( aOuterIt->end() ); + for( ; aIt != aEnd; ++aIt ) + { + ComplexCategory aComplexCategory( *aIt ); + sal_Int32 nCount = aComplexCategory.Count; + while( nCount-- ) + aSingleLevel.push_back(aComplexCategory); + } + aComplexCatsPerIndex.push_back( aSingleLevel ); + } + + if(nMaxCategoryCount) + { + aRet.realloc(nMaxCategoryCount); + aOuterEnd = aComplexCatsPerIndex.end(); + OUString aSpace(C2U(" ")); + for(sal_Int32 nN=0; nN<nMaxCategoryCount; nN++) + { + OUString aText; + for( aOuterIt=aComplexCatsPerIndex.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) + { + OUString aAddText = (*aOuterIt)[nN].Text; + if( aAddText.getLength() ) + { + if(aText.getLength()) + aText += aSpace; + aText += aAddText; + } + } + aRet[nN]=aText; + } + } + return aRet; +} + +//static +Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories( + const SplitCategoriesProvider& rSplitCategoriesProvider ) +{ + vector< vector< ComplexCategory > > aComplexCats; + return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats ); +} + +void ExplicitCategoriesProvider::init() { if( m_bDirty ) { - if( m_xCategories.is() ) - m_aExplicitCategories = DataSequenceToStringSequence(m_xCategories->getValues()); + m_aExplicitCategories.realloc(0); + m_aComplexCats.clear();//not one per index + + if( m_xOriginalCategories.is() ) + { + if( !hasComplexCategories() ) + m_aExplicitCategories = DataSequenceToStringSequence(m_xOriginalCategories->getValues()); + else + m_aExplicitCategories = lcl_getExplicitSimpleCategories( + SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList ), m_aComplexCats ); + } if(!m_aExplicitCategories.getLength()) - m_aExplicitCategories = DiagramHelper::generateAutomaticCategories( uno::Reference< chart2::XCoordinateSystem >( m_xCooSysModel.get(), uno::UNO_QUERY ) ); + m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel ); m_bDirty = false; } +} + + +Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories() +{ + init(); return m_aExplicitCategories; } +std::vector< ComplexCategory > ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel ) +{ + std::vector< ComplexCategory > aRet; + init(); + sal_Int32 nMaxIndex = m_aComplexCats.size()-1; + if( nLevel >= 0 && nLevel <= nMaxIndex ) + aRet = m_aComplexCats[nMaxIndex-nLevel]; + return aRet; +} + // static OUString ExplicitCategoriesProvider::getCategoryByIndex( - const Reference< XCoordinateSystem >& xCooSysModel, - sal_Int32 nIndex ) + const Reference< XCoordinateSystem >& xCooSysModel + , const uno::Reference< frame::XModel >& xChartModel + , sal_Int32 nIndex ) { if( xCooSysModel.is()) { - Reference< XTextualDataSequence > xTemp( new ExplicitCategoriesProvider( xCooSysModel )); - if( xTemp.is()) - { - Sequence< OUString > aCategories( xTemp->getTextualData()); - if( nIndex < aCategories.getLength()) - return aCategories[ nIndex ]; - } + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel ); + Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories()); + if( nIndex < aCategories.getLength()) + return aCategories[ nIndex ]; } return OUString(); } diff --git a/chart2/source/tools/InternalData.cxx b/chart2/source/tools/InternalData.cxx new file mode 100755 index 000000000000..65fc97a04b38 --- /dev/null +++ b/chart2/source/tools/InternalData.cxx @@ -0,0 +1,530 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "InternalData.hxx" +#include "ResId.hxx" +#include "Strings.hrc" +#include "macros.hxx" + +#include <rtl/math.hxx> + +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +using namespace ::std; + +namespace chart +{ + +// ---------------------------------------- +namespace +{ +struct lcl_NumberedStringGenerator +{ + lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) : + m_aStub( rStub ), + m_nCounter( 0 ), + m_nStubStartIndex( rStub.indexOf( rWildcard )), + m_nWildcardLength( rWildcard.getLength()) + { + } + vector< OUString > operator()() + { + vector< OUString > aRet(1); + aRet[0] = m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )); + return aRet; + } +private: + OUString m_aStub; + sal_Int32 m_nCounter; + const sal_Int32 m_nStubStartIndex; + const sal_Int32 m_nWildcardLength; +}; + +template< typename T > + Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray ) +{ + // is there a more elegant way of conversion? + Sequence< T > aResult( rValarray.size()); + for( size_t i = 0; i < rValarray.size(); ++i ) + aResult[i] = rValarray[i]; + return aResult; +} + +} // anonymous namespace +// ---------------------------------------- + +InternalData::InternalData() + : m_nColumnCount( 0 ) + , m_nRowCount( 0 ) + , m_aRowLabels( 0 ) + , m_aColumnLabels( 0 ) +{} + +void InternalData::createDefaultData() +{ + const sal_Int32 nRowCount = 4; + const sal_Int32 nColumnCount = 3; + + m_nRowCount = nRowCount; + m_nColumnCount = nColumnCount; + const sal_Int32 nSize = nColumnCount * nRowCount; + // @todo: localize this! + const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL )); + const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL )); + + const double fDefaultData[ nSize ] = + { 9.10, 3.20, 4.54, + 2.40, 8.80, 9.65, + 3.10, 1.50, 3.70, + 4.30, 9.02, 6.20 }; + + m_aData.resize( nSize ); + for( sal_Int32 i=0; i<nSize; ++i ) + m_aData[i] = fDefaultData[i]; + + m_aRowLabels.clear(); + m_aRowLabels.reserve( m_nRowCount ); + generate_n( back_inserter( m_aRowLabels ), m_nRowCount, + lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") )); + + m_aColumnLabels.clear(); + m_aColumnLabels.reserve( m_nColumnCount ); + generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount, + lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") )); +} + +void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows ) +{ + m_nRowCount = rDataInRows.getLength(); + m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0); + + if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount )) + m_aRowLabels.resize( m_nRowCount ); + if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount )) + m_aColumnLabels.resize( m_nColumnCount ); + + m_aData.resize( m_nRowCount * m_nColumnCount ); + double fNan; + ::rtl::math::setNan( & fNan ); + // set all values to Nan + m_aData = fNan; + + for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow ) + { + int nDataIdx = nRow*m_nColumnCount; + const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount ); + for( sal_Int32 nCol=0; nCol < nMax; ++nCol ) + { + m_aData[nDataIdx] = rDataInRows[nRow][nCol]; + nDataIdx += 1; + } + } +} + +Sequence< Sequence< double > > InternalData::getData() const +{ + Sequence< Sequence< double > > aResult( m_nRowCount ); + + for( sal_Int32 i=0; i<m_nRowCount; ++i ) + aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >( + m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); + + return aResult; +} + +Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const +{ + if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount ) + return lcl_ValarrayToSequence< tDataType::value_type >( + m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] ); + return Sequence< double >(); +} +Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const +{ + if( nRowIndex >= 0 && nRowIndex < m_nRowCount ) + return lcl_ValarrayToSequence< tDataType::value_type >( + m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] ); + return Sequence< double >(); +} + +void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData ) +{ + if( nColumnIndex < 0 ) + return; + enlargeData( nColumnIndex + 1, rNewData.size() ); + + tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ]; + for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) + aSlice[i] = rNewData[i]; + m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice; +} + +void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData ) +{ + if( nRowIndex < 0 ) + return; + enlargeData( rNewData.size(), nRowIndex+1 ); + + tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]; + for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) + aSlice[i] = rNewData[i]; + m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice; +} + +void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< OUString >& rComplexLabel ) +{ + if( nColumnIndex < 0 ) + return; + if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) + { + m_aColumnLabels.resize(nColumnIndex+1); + enlargeData( nColumnIndex+1, 0 ); + } + + m_aColumnLabels[nColumnIndex]=rComplexLabel; +} +void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< OUString >& rComplexLabel ) +{ + if( nRowIndex < 0 ) + return; + if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) ) + { + m_aRowLabels.resize(nRowIndex+1); + enlargeData( 0, nRowIndex+1 ); + } + + m_aRowLabels[nRowIndex] = rComplexLabel; +} + +vector< OUString > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const +{ + if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) + return m_aColumnLabels[nColumnIndex]; + else + return vector< OUString >(); +} +vector< OUString > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const +{ + if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) ) + return m_aRowLabels[nRowIndex]; + else + return vector< OUString >(); +} + +void InternalData::swapRowWithNext( sal_Int32 nRowIndex ) +{ + if( nRowIndex < m_nRowCount - 1 ) + { + const sal_Int32 nMax = m_nColumnCount; + for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx ) + { + size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount; + size_t nIndex2 = nIndex1 + m_nColumnCount; + double fTemp = m_aData[nIndex1]; + m_aData[nIndex1] = m_aData[nIndex2]; + m_aData[nIndex2] = fTemp; + } + + vector< OUString > aTemp( m_aRowLabels[nRowIndex] ); + m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1]; + m_aRowLabels[nRowIndex + 1] = aTemp; + } +} + +void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex ) +{ + if( nColumnIndex < m_nColumnCount - 1 ) + { + const sal_Int32 nMax = m_nRowCount; + for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx ) + { + size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount; + size_t nIndex2 = nIndex1 + 1; + double fTemp = m_aData[nIndex1]; + m_aData[nIndex1] = m_aData[nIndex2]; + m_aData[nIndex2] = fTemp; + } + + vector< OUString > aTemp( m_aColumnLabels[nColumnIndex] ); + m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1]; + m_aColumnLabels[nColumnIndex + 1] = aTemp; + } +} + +bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ) +{ + sal_Int32 nNewColumnCount( ::std::max<sal_Int32>( m_nColumnCount, nColumnCount ) ); + sal_Int32 nNewRowCount( ::std::max<sal_Int32>( m_nRowCount, nRowCount ) ); + sal_Int32 nNewSize( nNewColumnCount*nNewRowCount ); + + bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); + + if( bGrow ) + { + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + // copy old data + for( int nCol=0; nCol<m_nColumnCount; ++nCol ) + static_cast< tDataType >( + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) = + m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ]; + + m_aData.resize( nNewSize ); + m_aData = aNewData; + } + m_nColumnCount = nNewColumnCount; + m_nRowCount = nNewRowCount; + return bGrow; +} + +void InternalData::insertColumn( sal_Int32 nAfterIndex ) +{ + // note: -1 is allowed, as we insert after the given index + OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 ); + if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 ) + return; + sal_Int32 nNewColumnCount = m_nColumnCount + 1; + sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + int nCol=0; + for( ; nCol<=nAfterIndex; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); + for( ++nCol; nCol<nNewColumnCount; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] ); + + m_nColumnCount = nNewColumnCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) + m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< OUString >(1) ); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +sal_Int32 InternalData::appendColumn() +{ + insertColumn( getColumnCount() - 1 ); + return getColumnCount() - 1; +} + +sal_Int32 InternalData::appendRow() +{ + insertRow( getRowCount() - 1 ); + return getRowCount() - 1; +} + +void InternalData::insertRow( sal_Int32 nAfterIndex ) +{ + // note: -1 is allowed, as we insert after the given index + OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 ); + if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 ) + return; + sal_Int32 nNewRowCount = m_nRowCount + 1; + sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + sal_Int32 nIndex = nAfterIndex + 1; + aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); + + if( nIndex < m_nRowCount ) + { + sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex); + aNewData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] ); + } + + m_nRowCount = nNewRowCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) + m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< OUString> (1)); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +void InternalData::deleteColumn( sal_Int32 nAtIndex ) +{ + OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 ); + if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 ) + return; + sal_Int32 nNewColumnCount = m_nColumnCount - 1; + sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + int nCol=0; + for( ; nCol<nAtIndex; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); + for( ; nCol<nNewColumnCount; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] ); + + m_nColumnCount = nNewColumnCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) + m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex ); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +void InternalData::deleteRow( sal_Int32 nAtIndex ) +{ + OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 ); + if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 ) + return; + sal_Int32 nNewRowCount = m_nRowCount - 1; + sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + sal_Int32 nIndex = nAtIndex; + if( nIndex ) + aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); + + if( nIndex < nNewRowCount ) + { + sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex); + aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] ); + } + + m_nRowCount = nNewRowCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) + m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex ); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +sal_Int32 InternalData::getRowCount() const +{ + return m_nRowCount; +} + +sal_Int32 InternalData::getColumnCount() const +{ + return m_nColumnCount; +} + +void InternalData::setComplexRowLabels( const vector< vector< OUString > >& rNewRowLabels ) +{ + m_aRowLabels = rNewRowLabels; + sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() ); + if( nNewRowCount < m_nRowCount ) + m_aRowLabels.resize( m_nRowCount ); + else + enlargeData( 0, nNewRowCount ); +} + +vector< vector< OUString > > InternalData::getComplexRowLabels() const +{ + return m_aRowLabels; +} + +void InternalData::setComplexColumnLabels( const vector< vector< OUString > >& rNewColumnLabels ) +{ + m_aColumnLabels = rNewColumnLabels; + sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() ); + if( nNewColumnCount < m_nColumnCount ) + m_aColumnLabels.resize( m_nColumnCount ); + else + enlargeData( nNewColumnCount, 0 ); +} + +vector< vector< OUString > > InternalData::getComplexColumnLabels() const +{ + return m_aColumnLabels; +} + +#if OSL_DEBUG_LEVEL > 2 +void InternalData::traceData() const +{ + OSL_TRACE( "InternalData: Data in rows\n" ); + + for( sal_Int32 i=0; i<m_nRowCount; ++i ) + { + tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); + for( sal_Int32 j=0; j<m_nColumnCount; ++j ) + OSL_TRACE( "%lf ", aSlice[j] ); + OSL_TRACE( "\n" ); + } + OSL_TRACE( "\n" ); +} +#endif + +} // namespace chart diff --git a/chart2/source/tools/InternalDataProvider.cxx b/chart2/source/tools/InternalDataProvider.cxx index 70215623840d..4abc51be31af 100644 --- a/chart2/source/tools/InternalDataProvider.cxx +++ b/chart2/source/tools/InternalDataProvider.cxx @@ -45,8 +45,8 @@ #include "DataSourceHelper.hxx" #include "ChartModelHelper.hxx" #include "DiagramHelper.hxx" -#include "ResId.hxx" -#include "Strings.hrc" +#include "ExplicitCategoriesProvider.hxx" + #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/data/XDataSequence.hpp> #include <com/sun/star/chart/ChartDataRowSource.hpp> @@ -67,774 +67,327 @@ using ::rtl::OUStringBuffer; namespace chart { -namespace impl -{ - - -struct OUStringBufferAppend : public unary_function< OUString, void > -{ - OUStringBufferAppend( OUStringBuffer & rBuffer, const OUString & rSeparator ) : - m_rBuffer( rBuffer ), - m_aSep( rSeparator ) - {} - void operator() ( const OUString & rStr ) - { - m_rBuffer.append( m_aSep ); - m_rBuffer.append( rStr ); - } -private: - OUStringBuffer m_rBuffer; - OUString m_aSep; -}; - -OUString FlattenStringSequence( const Sequence< OUString > & aSeq ) -{ - if( aSeq.getLength() == 0 ) - return OUString(); - OUStringBuffer aBuf( aSeq[0] ); - for_each( aSeq.getConstArray() + 1, aSeq.getConstArray() + aSeq.getLength(), - OUStringBufferAppend( aBuf, OUString(RTL_CONSTASCII_USTRINGPARAM(" ")))); - return aBuf.makeStringAndClear(); -} - -class InternalData -{ -public: - InternalData(); - - void createDefaultData(); - - void setData( const Sequence< Sequence< double > > & rNewData, bool bDataInColumns ); - Sequence< Sequence< double > > getData( bool bDataInColumns ) const; - Sequence< double > getDataAt( sal_Int32 nIndex, bool bDataInColumns ) const; - void setDataAt( sal_Int32 nIndex, bool bDataInColumns, const ::std::vector< double > & rNewData ); - void swapAllDataAtIndexWithNext( sal_Int32 nAtIndex, bool bDataInColumns ); - - /** resizes the data if at least one of the given dimensions is larger than - before. The data is never becoming smaller only larger. - - @return </TRUE>, if the data was enlarged - */ - bool enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ); - - void insertColumn( sal_Int32 nAfterIndex ); - void insertRow( sal_Int32 nAfterIndex ); - void deleteColumn( sal_Int32 nAtIndex ); - void deleteRow( sal_Int32 nAtIndex ); - - /// @return the index of the newly appended column - sal_Int32 appendColumn(); - /// @return the index of the newly appended row - sal_Int32 appendRow(); - - sal_Int32 getRowCount() const; - sal_Int32 getColumnCount() const; - - void setRowLabels( const ::std::vector< OUString > & rNewRowLabels ); - ::std::vector< OUString > getRowLabels() const; - void setColumnLabels( const ::std::vector< OUString > & rNewColumnLabels ); - ::std::vector< OUString > getColumnLabels() const; - -#if OSL_DEBUG_LEVEL > 2 - void traceData() const; -#endif -private: - sal_Int32 m_nColumnCount; - sal_Int32 m_nRowCount; - - typedef ::std::valarray< double > tDataType; - typedef ::std::vector< OUString > tLabelType; - - tDataType m_aData; - tLabelType m_aRowLabels; - tLabelType m_aColumnLabels; -}; +// ================================================================================ -// ---------------------------------------- namespace { -struct lcl_NumberedStringGenerator -{ - lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) : - m_aStub( rStub ), - m_nCounter( 0 ), - m_nStubStartIndex( rStub.indexOf( rWildcard )), - m_nWildcardLength( rWildcard.getLength()) - { - } - OUString operator()() { - return m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )); - } -private: - OUString m_aStub; - sal_Int32 m_nCounter; - const sal_Int32 m_nStubStartIndex; - const sal_Int32 m_nWildcardLength; -}; - -template< typename T > - Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray ) -{ - // is there a more elegant way of conversion? - Sequence< T > aResult( rValarray.size()); - for( size_t i = 0; i < rValarray.size(); ++i ) - aResult[i] = rValarray[i]; - return aResult; -} - -struct lcl_ValuesOfLabeledSequence : - public unary_function< Reference< chart2::data::XLabeledDataSequence >, Sequence< double > > -{ - Sequence< double > operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) - { - if( ! xLSeq.is()) - return Sequence< double >(); - return DataSequenceToDoubleSequence( xLSeq->getValues()); - } -}; - -struct lcl_LabelsOfLabeledSequence : - public unary_function< Reference< chart2::data::XLabeledDataSequence >, Sequence< OUString > > -{ - Sequence< OUString > operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) - { - if( ! xLSeq.is()) - return Sequence< OUString >(); - return DataSequenceToStringSequence( xLSeq->getLabel()); - } -}; - -struct lcl_LabelOfLabeledSequence : - public unary_function< Reference< chart2::data::XLabeledDataSequence >, OUString > -{ - OUString operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) - { - if( ! xLSeq.is()) - return OUString(); - return FlattenStringSequence( DataSequenceToStringSequence( xLSeq->getLabel())); - } -}; -} // anonymous namespace -// ---------------------------------------- +// note: in xmloff this name is used to indicate usage of own data +static const ::rtl::OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" )); -InternalData::InternalData() : - m_nColumnCount( 0 ), - m_nRowCount( 0 ) -{} +static const ::rtl::OUString lcl_aCategoriesRangeName( + RTL_CONSTASCII_USTRINGPARAM( "categories" )); +static const ::rtl::OUString lcl_aCategoriesLevelRangeNamePrefix( + RTL_CONSTASCII_USTRINGPARAM( "categoriesL " )); //L <-> level +static const ::rtl::OUString lcl_aCategoriesPointRangeNamePrefix( + RTL_CONSTASCII_USTRINGPARAM( "categoriesP " )); //P <-> point +static const ::rtl::OUString lcl_aCategoriesRoleName( + RTL_CONSTASCII_USTRINGPARAM( "categories" )); +static const ::rtl::OUString lcl_aLabelRangePrefix( + RTL_CONSTASCII_USTRINGPARAM( "label " )); +static const ::rtl::OUString lcl_aCompleteRange( + RTL_CONSTASCII_USTRINGPARAM( "all" )); -void InternalData::createDefaultData() -{ - const sal_Int32 nNumRows = 4; - const sal_Int32 nNumColumns = 3; - const sal_Int32 nSize = nNumColumns * nNumRows; - // @todo: localize this! - const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL )); - const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL )); - - const double fDefaultData[ nSize ] = - { 9.10, 3.20, 4.54, - 2.40, 8.80, 9.65, - 3.10, 1.50, 3.70, - 4.30, 9.02, 6.20 }; - - m_aData.resize( nSize ); - for( sal_Int32 i=0; i<nSize; ++i ) - m_aData[i] = fDefaultData[i]; - m_nRowCount = nNumRows; - m_nColumnCount = nNumColumns; - - vector< OUString > aRowLabels; - aRowLabels.reserve( nNumRows ); - generate_n( back_inserter( aRowLabels ), nNumRows, - lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") )); - setRowLabels( aRowLabels ); - - vector< OUString > aColumnLabels; - aColumnLabels.reserve( nNumColumns ); - generate_n( back_inserter( aColumnLabels ), nNumColumns, - lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") )); - setColumnLabels( aColumnLabels ); -} +typedef ::std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > > + lcl_tSequenceMap; -void InternalData::setData( const Sequence< Sequence< double > > & rNewData, bool bDataInColumns ) +struct lcl_setModified : public ::std::unary_function< lcl_tSequenceMap, void > { - sal_Int32 nOuterSize = rNewData.getLength(); - sal_Int32 nInnerSize = (nOuterSize ? rNewData[0].getLength() : 0); - - m_nRowCount = (bDataInColumns ? nInnerSize : nOuterSize); - m_nColumnCount = (bDataInColumns ? nOuterSize : nInnerSize); - - if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount )) - m_aRowLabels.resize( m_nRowCount ); - if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount )) - m_aColumnLabels.resize( m_nColumnCount ); - - m_aData.resize( m_nRowCount * m_nColumnCount ); - double fNan; - ::rtl::math::setNan( & fNan ); - // set all values to Nan - m_aData = fNan; - - for( sal_Int32 nOuterIdx=0; nOuterIdx<nOuterSize; ++nOuterIdx ) + void operator() ( const lcl_tSequenceMap::value_type & rMapEntry ) { - int nDataIdx = (bDataInColumns ? nOuterIdx : nOuterIdx*nInnerSize); - const sal_Int32 nMax = ::std::min( rNewData[nOuterIdx].getLength(), nInnerSize ); - sal_Int32 nInnerIdx=0; - for( ; nInnerIdx < nMax; ++nInnerIdx ) + // convert weak reference to reference + Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second ); + if( xSeq.is()) { - m_aData[nDataIdx] = rNewData[nOuterIdx][nInnerIdx]; - nDataIdx += (bDataInColumns ? m_nColumnCount : 1); + Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY ); + if( xMod.is()) + xMod->setModified( sal_True ); } } -} - -Sequence< Sequence< double > > InternalData::getData( bool bDataInColumns ) const -{ - Sequence< Sequence< double > > aResult( bDataInColumns ? m_nColumnCount : m_nRowCount ); - - if( bDataInColumns ) - { - for( sal_Int32 i=0; i<m_nColumnCount; ++i ) - aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >( - m_aData[ ::std::slice( i, m_nRowCount, m_nColumnCount ) ] ); - } - else - { - for( sal_Int32 i=0; i<m_nRowCount; ++i ) - aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >( - m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); - } - - return aResult; -} - -Sequence< double > InternalData::getDataAt( sal_Int32 nIndex, bool bDataInColumns ) const -{ - Sequence< double > aResult( bDataInColumns ? m_nRowCount : m_nColumnCount ); - - if( bDataInColumns ) - { - if( nIndex < m_nColumnCount ) - return lcl_ValarrayToSequence< tDataType::value_type >( - m_aData[ ::std::slice( nIndex, m_nRowCount, m_nColumnCount ) ] ); - } - else - { - if( nIndex < m_nRowCount ) - return lcl_ValarrayToSequence< tDataType::value_type >( - m_aData[ ::std::slice( nIndex*m_nColumnCount, m_nColumnCount, 1 ) ] ); - } - - return Sequence< double >(); -} +}; -void InternalData::setDataAt( sal_Int32 nIndex, bool bDataInColumns, const ::std::vector< double > & rNewData ) +struct lcl_internalizeSeries : public ::std::unary_function< Reference< chart2::XDataSeries >, void > { - if( bDataInColumns ) - { - if( nIndex < m_nColumnCount ) - { - tDataType aSlice = m_aData[ ::std::slice( nIndex, m_nRowCount, m_nColumnCount ) ]; - for( ::std::vector< double >::size_type i = 0; i < rNewData.size(); ++i ) - aSlice[i] = rNewData[i]; - m_aData[ ::std::slice( nIndex, m_nRowCount, m_nColumnCount ) ] = aSlice; - } - } - else + lcl_internalizeSeries( InternalData & rInternalData, + InternalDataProvider & rProvider, + bool bConnectToModel, bool bDataInColumns ) : + m_rInternalData( rInternalData ), + m_rProvider( rProvider ), + m_bConnectToModel( bConnectToModel ), + m_bDataInColumns( bDataInColumns ) + {} + void operator() ( const Reference< chart2::XDataSeries > & xSeries ) { - if( nIndex < m_nRowCount ) + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + Reference< chart2::data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + if( xSource.is() && xSink.is() ) { - tDataType aSlice = m_aData[ ::std::slice( nIndex*m_nColumnCount, m_nColumnCount, 1 ) ]; - for( ::std::vector< double >::size_type i = 0; i < rNewData.size(); ++i ) - aSlice[i] = rNewData[i]; - m_aData[ ::std::slice( nIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice; + Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeriesData = xSource->getDataSequences(); + Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.getLength() ); + for( sal_Int32 i=0; i<aOldSeriesData.getLength(); ++i ) + { + sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() ); + OUString aIdentifier( OUString::valueOf( nNewIndex )); + //@todo: deal also with genericXDataSequence + Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY ); + Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY ); + Reference< chart2::data::XDataSequence > xNewValues; + + if( xValues.is() ) + { + ::std::vector< double > aValues( ContainerHelper::SequenceToVector( xValues->getNumericalData())); + if( m_bDataInColumns ) + m_rInternalData.setColumnValues( nNewIndex, aValues ); + else + m_rInternalData.setRowValues( nNewIndex, aValues ); + if( m_bConnectToModel ) + { + xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier )); + comphelper::copyProperties( + Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ), + Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY )); + } + } + + if( xLabel.is() ) + { + if( m_bDataInColumns ) + m_rInternalData.setComplexColumnLabel( nNewIndex, ContainerHelper::SequenceToVector( xLabel->getTextualData() ) ); + else + m_rInternalData.setComplexRowLabel( nNewIndex, ContainerHelper::SequenceToVector( xLabel->getTextualData() ) ); + if( m_bConnectToModel ) + { + Reference< chart2::data::XDataSequence > xNewLabel( + m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier )); + comphelper::copyProperties( + Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ), + Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY )); + aNewSeriesData[i] = Reference< chart2::data::XLabeledDataSequence >( + new LabeledDataSequence( xNewValues, xNewLabel )); + } + } + else + { + if( m_bConnectToModel ) + aNewSeriesData[i] = Reference< chart2::data::XLabeledDataSequence >( + new LabeledDataSequence( xNewValues )); + } + } + if( m_bConnectToModel ) + xSink->setData( aNewSeriesData ); } - } -} + } -void InternalData::swapAllDataAtIndexWithNext( sal_Int32 nAtIndex, bool bDataInColumns ) -{ - if( bDataInColumns && nAtIndex < m_nRowCount - 1 ) - { - const sal_Int32 nMax = m_nColumnCount; - for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx ) - { - size_t nIndex1 = nColIdx + nAtIndex*m_nColumnCount; - size_t nIndex2 = nIndex1 + m_nColumnCount; - double fTemp = m_aData[nIndex1]; - m_aData[nIndex1] = m_aData[nIndex2]; - m_aData[nIndex2] = fTemp; - } - OUString sTemp( m_aRowLabels[nAtIndex] ); - m_aRowLabels[nAtIndex] = m_aRowLabels[nAtIndex + 1]; - m_aRowLabels[nAtIndex + 1] = sTemp; - } - else if( nAtIndex < m_nColumnCount - 1 ) - { - const sal_Int32 nMax = m_nRowCount; - for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx ) - { - size_t nIndex1 = nAtIndex + nRowIdx*m_nColumnCount; - size_t nIndex2 = nIndex1 + 1; - double fTemp = m_aData[nIndex1]; - m_aData[nIndex1] = m_aData[nIndex2]; - m_aData[nIndex2] = fTemp; - } - OUString sTemp( m_aColumnLabels[nAtIndex] ); - m_aColumnLabels[nAtIndex] = m_aColumnLabels[nAtIndex + 1]; - m_aColumnLabels[nAtIndex + 1] = sTemp; - } -} +private: + InternalData & m_rInternalData; + InternalDataProvider & m_rProvider; + bool m_bConnectToModel; + bool m_bDataInColumns; +}; -bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ) +struct lcl_makeAnyFromLevelVector : public ::std::unary_function< vector< OUString >, uno::Any > { - sal_Int32 nNewColumnCount( ::std::max<sal_Int32>( m_nColumnCount, nColumnCount ) ); - sal_Int32 nNewRowCount( ::std::max<sal_Int32>( m_nRowCount, nRowCount ) ); - sal_Int32 nNewSize( nNewColumnCount*nNewRowCount ); +public: - bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); + explicit lcl_makeAnyFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} - if( bGrow ) + uno::Any operator() ( const vector< OUString >& rVector ) { - double fNan; - ::rtl::math::setNan( &fNan ); - tDataType aNewData( fNan, nNewSize ); - // copy old data - for( int nCol=0; nCol<m_nColumnCount; ++nCol ) - static_cast< tDataType >( - aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) = - m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ]; - - m_aData.resize( nNewSize ); - m_aData = aNewData; + OUString aString; + if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) ) + aString = rVector[m_nLevel]; + return uno::makeAny( aString ); } - m_nColumnCount = nNewColumnCount; - m_nRowCount = nNewRowCount; - return bGrow; -} - -void InternalData::insertColumn( sal_Int32 nAfterIndex ) -{ - // note: -1 is allowed, as we insert after the given index - OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 ); - if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 ) - return; - sal_Int32 nNewColumnCount = m_nColumnCount + 1; - sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); - double fNan; - ::rtl::math::setNan( &fNan ); - tDataType aNewData( fNan, nNewSize ); - - // copy old data - int nCol=0; - for( ; nCol<=nAfterIndex; ++nCol ) - aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); - for( ++nCol; nCol<nNewColumnCount; ++nCol ) - aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] ); - - m_nColumnCount = nNewColumnCount; - m_aData.resize( nNewSize ); - m_aData = aNewData; - - // labels - if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) - m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), OUString()); - -#if OSL_DEBUG_LEVEL > 2 - traceData(); -#endif -} - -sal_Int32 InternalData::appendColumn() -{ - insertColumn( getColumnCount() - 1 ); - return getColumnCount() - 1; -} - -sal_Int32 InternalData::appendRow() -{ - insertRow( getRowCount() - 1 ); - return getRowCount() - 1; -} +private: + sal_Int32 m_nLevel; +}; -void InternalData::insertRow( sal_Int32 nAfterIndex ) +struct lcl_getStringFromLevelVector : public ::std::unary_function< vector< OUString >, OUString > { - // note: -1 is allowed, as we insert after the given index - OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 ); - if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 ) - return; - sal_Int32 nNewRowCount = m_nRowCount + 1; - sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); - - double fNan; - ::rtl::math::setNan( &fNan ); - tDataType aNewData( fNan, nNewSize ); +public: - // copy old data - sal_Int32 nIndex = nAfterIndex + 1; - aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); + explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} - if( nIndex < m_nRowCount ) + OUString operator() ( const vector< OUString >& rVector ) { - sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex); - aNewData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] ); + OUString aString; + if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) ) + aString = rVector[m_nLevel]; + return aString; } - m_nRowCount = nNewRowCount; - m_aData.resize( nNewSize ); - m_aData = aNewData; - - // labels - if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) - m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, OUString()); - -#if OSL_DEBUG_LEVEL > 2 - traceData(); -#endif -} - -void InternalData::deleteColumn( sal_Int32 nAtIndex ) -{ - OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 ); - if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 ) - return; - sal_Int32 nNewColumnCount = m_nColumnCount - 1; - sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); +private: + sal_Int32 m_nLevel; +}; - double fNan; - ::rtl::math::setNan( &fNan ); - tDataType aNewData( fNan, nNewSize ); - - // copy old data - int nCol=0; - for( ; nCol<nAtIndex; ++nCol ) - aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); - for( ; nCol<nNewColumnCount; ++nCol ) - aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] ); - - m_nColumnCount = nNewColumnCount; - m_aData.resize( nNewSize ); - m_aData = aNewData; - - // labels - if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) - m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex ); - -#if OSL_DEBUG_LEVEL > 2 - traceData(); -#endif -} -void InternalData::deleteRow( sal_Int32 nAtIndex ) +struct lcl_setStringAtLevel : public ::std::binary_function< vector< OUString >, OUString, vector< OUString > > { - OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 ); - if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 ) - return; - sal_Int32 nNewRowCount = m_nRowCount - 1; - sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); - - double fNan; - ::rtl::math::setNan( &fNan ); - tDataType aNewData( fNan, nNewSize ); +public: - // copy old data - sal_Int32 nIndex = nAtIndex; - if( nIndex ) - aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); + explicit lcl_setStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} - if( nIndex < nNewRowCount ) + vector< OUString > operator() ( const vector< OUString >& rVector, const OUString& rNewText ) { - sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex); - aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] = - static_cast< tDataType >( - m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] ); + vector< OUString > aRet( rVector ); + if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) ) + aRet.resize( m_nLevel+1 ); + aRet[ m_nLevel ]=rNewText; + return aRet; } - m_nRowCount = nNewRowCount; - m_aData.resize( nNewSize ); - m_aData = aNewData; - - // labels - if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) - m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex ); - -#if OSL_DEBUG_LEVEL > 2 - traceData(); -#endif -} - -sal_Int32 InternalData::getRowCount() const -{ - return m_nRowCount; -} - -sal_Int32 InternalData::getColumnCount() const -{ - return m_nColumnCount; -} - -void InternalData::setRowLabels( const ::std::vector< OUString > & rNewRowLabels ) -{ - m_aRowLabels = rNewRowLabels; - if( m_aRowLabels.size() < static_cast< ::std::vector< OUString >::size_type >( m_nRowCount )) - m_aRowLabels.resize( m_nRowCount ); - else - enlargeData( 0, static_cast< sal_Int32 >( m_aRowLabels.size() )); -} - -::std::vector< OUString > InternalData::getRowLabels() const -{ - return m_aRowLabels; -} - -void InternalData::setColumnLabels( const ::std::vector< OUString > & rNewColumnLabels ) -{ - m_aColumnLabels = rNewColumnLabels; - if( m_aColumnLabels.size() < static_cast< ::std::vector< OUString >::size_type >( m_nColumnCount )) - m_aColumnLabels.resize( m_nColumnCount ); - else - enlargeData( static_cast< sal_Int32 >( m_aColumnLabels.size()), 0 ); -} +private: + sal_Int32 m_nLevel; +}; -::std::vector< OUString > InternalData::getColumnLabels() const +struct lcl_insertStringAtLevel : public ::std::unary_function< vector< OUString >, void > { - return m_aColumnLabels; -} +public: -#if OSL_DEBUG_LEVEL > 2 -void InternalData::traceData() const -{ - OSL_TRACE( "InternalData: Data in rows\n" ); + explicit lcl_insertStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} - for( sal_Int32 i=0; i<m_nRowCount; ++i ) + void operator() ( vector< OUString >& rVector ) { - tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); - for( sal_Int32 j=0; j<m_nColumnCount; ++j ) - OSL_TRACE( "%lf ", aSlice[j] ); - OSL_TRACE( "\n" ); - } - OSL_TRACE( "\n" ); -} -#endif + if( m_nLevel > static_cast< sal_Int32 >(rVector.size()) ) + rVector.resize( m_nLevel ); -} // namespace impl + vector< OUString >::iterator aIt( rVector.begin() ); + for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++) + { + if( nN==m_nLevel ) + break; + } + rVector.insert( aIt, OUString() ); + } -// ================================================================================ +private: + sal_Int32 m_nLevel; +}; -namespace +struct lcl_removeStringAtLevel : public ::std::unary_function< vector< OUString >, void > { +public: -// note: in xmloff this name is used to indicate usage of own data -static const ::rtl::OUString lcl_aServiceName( - RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" )); - -static const ::rtl::OUString lcl_aCategoriesRangeName( - RTL_CONSTASCII_USTRINGPARAM( "categories" )); -static const ::rtl::OUString lcl_aCategoriesRoleName( - RTL_CONSTASCII_USTRINGPARAM( "categories" )); -static const ::rtl::OUString lcl_aLabelRangePrefix( - RTL_CONSTASCII_USTRINGPARAM( "label " )); -static const ::rtl::OUString lcl_aCompleteRange( - RTL_CONSTASCII_USTRINGPARAM( "all" )); - - -struct lcl_DataProviderRangeCreator : public unary_function< OUString, Reference< chart2::data::XLabeledDataSequence > > -{ - lcl_DataProviderRangeCreator( const Reference< chart2::data::XDataProvider > & xDataProvider ) : - m_xDataProvider( xDataProvider ) + explicit lcl_removeStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel ) {} - Reference< chart2::data::XLabeledDataSequence > operator() ( const OUString & rRange ) + void operator() ( vector< OUString >& rVector ) { - Reference< chart2::data::XLabeledDataSequence > xResult; - if( m_xDataProvider.is()) - try - { - xResult.set( new ::chart::LabeledDataSequence( - m_xDataProvider->createDataSequenceByRangeRepresentation( rRange ))); - } - catch( const lang::IllegalArgumentException & ex ) - { - // data provider cannot create single data sequences, but then - // detectArguments should work also with an empty data source - (void)(ex); - } - catch( const uno::Exception & ex ) + vector< OUString >::iterator aIt( rVector.begin() ); + for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++) + { + if( nN==m_nLevel ) { - ASSERT_EXCEPTION( ex ); + rVector.erase( aIt ); + break; } - return xResult; + } } private: - Reference< chart2::data::XDataProvider > m_xDataProvider; + sal_Int32 m_nLevel; }; -typedef ::std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > > - lcl_tSequenceMap; - -struct lcl_modifySeqMapValue : public ::std::unary_function< lcl_tSequenceMap, void > +vector< OUString > lcl_AnyToStringVector( const Sequence< uno::Any >& aAnySeq ) { - void operator() ( const lcl_tSequenceMap::value_type & rMapEntry ) - { - // convert weak reference to reference - Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second ); - if( xSeq.is()) - { - Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY ); - if( xMod.is()) - xMod->setModified( sal_True ); - } - } -}; + vector< OUString > aStringVec; + transform( aAnySeq.getConstArray(), aAnySeq.getConstArray() + aAnySeq.getLength(), + back_inserter( aStringVec ), CommonFunctors::AnyToString() ); + return aStringVec; +} -Sequence< Reference< chart2::data::XLabeledDataSequence > > - lcl_internalizeData( - const Sequence< Reference< chart2::data::XLabeledDataSequence > > & rDataSeq, - impl::InternalData & rInternalData, - InternalDataProvider & rProvider ) +Sequence< OUString > lcl_AnyToStringSequence( const Sequence< uno::Any >& aAnySeq ) { - Sequence< Reference< chart2::data::XLabeledDataSequence > > aResult( rDataSeq.getLength()); - for( sal_Int32 i=0; i<rDataSeq.getLength(); ++i ) - { - sal_Int32 nNewIndex( rInternalData.appendColumn()); - OUString aIdentifier( OUString::valueOf( nNewIndex )); - //@todo: deal also with genericXDataSequence - Reference< chart2::data::XNumericalDataSequence > xValues( rDataSeq[i]->getValues(), uno::UNO_QUERY ); - Reference< chart2::data::XTextualDataSequence > xLabel( rDataSeq[i]->getLabel(), uno::UNO_QUERY ); - Reference< chart2::data::XDataSequence > xNewValues; - - if( xValues.is()) - { - ::std::vector< double > aValues( ContainerHelper::SequenceToVector( xValues->getNumericalData())); - rInternalData.enlargeData( nNewIndex + 1, aValues.size()); - rInternalData.setDataAt( nNewIndex, true, aValues ); - xNewValues.set( rProvider.createDataSequenceByRangeRepresentation( aIdentifier )); - comphelper::copyProperties( - Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ), - Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY )); - } - - if( xLabel.is()) - { - ::std::vector< OUString > aLabels( rInternalData.getColumnLabels()); - OSL_ASSERT( static_cast< size_t >( nNewIndex ) < aLabels.size()); - if( aLabels.size() <= static_cast< size_t >( nNewIndex ) ) - aLabels.resize( nNewIndex+1 ); - aLabels[nNewIndex] = impl::FlattenStringSequence( xLabel->getTextualData()); - rInternalData.setColumnLabels( aLabels ); - Reference< chart2::data::XDataSequence > xNewLabel( - rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier )); - comphelper::copyProperties( - Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ), - Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY )); - aResult[i] = - Reference< chart2::data::XLabeledDataSequence >( - new LabeledDataSequence( xNewValues, xNewLabel )); - } - else - { - aResult[i] = - Reference< chart2::data::XLabeledDataSequence >( - new LabeledDataSequence( xNewValues )); - } - } + Sequence< OUString > aResult; + aResult.realloc( aAnySeq.getLength() ); + transform( aAnySeq.getConstArray(), aAnySeq.getConstArray() + aAnySeq.getLength(), + aResult.getArray(), CommonFunctors::AnyToString() ); return aResult; } -struct lcl_internalizeSeries : public ::std::unary_function< Reference< chart2::XDataSeries >, void > -{ - lcl_internalizeSeries( impl::InternalData & rInternalData, - InternalDataProvider & rProvider ) : - m_rInternalData( rInternalData ), - m_rProvider( rProvider ) - {} - void operator() ( const Reference< chart2::XDataSeries > & xSeries ) - { - Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); - Reference< chart2::data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); - if( xSource.is() && xSink.is()) - xSink->setData( lcl_internalizeData( xSource->getDataSequences(), m_rInternalData, m_rProvider )); - } - -private: - impl::InternalData & m_rInternalData; - InternalDataProvider & m_rProvider; -}; - } // anonymous namespace -InternalDataProvider::InternalDataProvider(const Reference< uno::XComponentContext > & /*_xContext*/) : - m_bDataInColumns( true ) -{} // ================================================================================ -InternalDataProvider::InternalDataProvider() : - m_bDataInColumns( true ) +InternalDataProvider::InternalDataProvider( const Reference< uno::XComponentContext > & /*_xContext*/) + : m_bDataInColumns( true ) {} -InternalDataProvider::InternalDataProvider( - const Reference< ::com::sun::star::chart::XChartDataArray > & xDataToCopy ) : - m_bDataInColumns( true ) -{ - if( xDataToCopy.is()) - { - setData( xDataToCopy->getData() ); - setColumnDescriptions( xDataToCopy->getColumnDescriptions() ); - setRowDescriptions( xDataToCopy->getRowDescriptions() ); - } -} - -InternalDataProvider::InternalDataProvider( - const Reference< chart2::XChartDocument > & xChartDoc ) : - m_bDataInColumns( true ) +InternalDataProvider::InternalDataProvider( const Reference< chart2::XChartDocument > & xChartDoc, bool bConnectToModel ) + : m_bDataInColumns( true ) { try { Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) ); if( xDiagram.is()) { - impl::InternalData & rData( getInternalData()); + Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY ); + + //data in columns? + { + ::rtl::OUString aRangeString; + bool bFirstCellAsLabel = true; + bool bHasCategories = true; + uno::Sequence< sal_Int32 > aSequenceMapping; + DataSourceHelper::detectRangeSegmentation( xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ); + } + // categories - Reference< chart2::data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram )); - if( xCategories.is()) { - // @todo: be able to deal with XDataSequence, too - Reference< chart2::data::XTextualDataSequence > xSeq( xCategories->getValues(), uno::UNO_QUERY ); - if( xSeq.is()) - rData.setRowLabels( ContainerHelper::SequenceToVector( xSeq->getTextualData())); - DiagramHelper::setCategoriesToDiagram( - new LabeledDataSequence( - createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), - xDiagram ); + vector< vector< OUString > > aNewCategories;//inner count is level + { + ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), xChartModel ); + const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() ); + sal_Int32 nLevelCount = rSplitCategoriesList.getLength(); + for( sal_Int32 nL = 0; nL<nLevelCount; nL++ ) + { + Reference< chart2::data::XLabeledDataSequence > xLDS( rSplitCategoriesList[nL] ); + if( !xLDS.is() ) + continue; + Reference< chart2::data::XTextualDataSequence > xSeq( xLDS->getValues(), uno::UNO_QUERY ); + Sequence< OUString > aStringSeq; + if( xSeq.is() ) + aStringSeq = xSeq->getTextualData(); // @todo: be able to deal with XDataSequence, too + sal_Int32 nLength = aStringSeq.getLength(); + if( static_cast< sal_Int32 >(aNewCategories.size()) < nLength ) + aNewCategories.resize( nLength ); + + transform( aNewCategories.begin(), aNewCategories.end(), aStringSeq.getConstArray(), + aNewCategories.begin(), lcl_setStringAtLevel(nL) ); + } + if( !nLevelCount ) + { + Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories(); + sal_Int32 nLength = aSimplecategories.getLength(); + aNewCategories.reserve( nLength ); + for( sal_Int32 nN=0; nN<nLength; nN++) + { + vector< OUString > aStringVector(1); + aStringVector[0] = aSimplecategories[nN]; + aNewCategories.push_back( aStringVector ); + } + } + } + + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aNewCategories ); + else + m_aInternalData.setComplexColumnLabels( aNewCategories ); + if( bConnectToModel ) + DiagramHelper::setCategoriesToDiagram( new LabeledDataSequence( + createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), xDiagram ); } // data series ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc )); - ::std::for_each( aSeriesVector.begin(), aSeriesVector.end(), - lcl_internalizeSeries( rData, *this )); - - // unused data - Sequence< Reference< chart2::data::XLabeledDataSequence > > aUnusedData( xDiagram->getUnusedData()); - aUnusedData = lcl_internalizeData( aUnusedData, rData, *this ); - xDiagram->setUnusedData( aUnusedData ); + ::std::for_each( aSeriesVector.begin(), aSeriesVector.end(), lcl_internalizeSeries( m_aInternalData, *this, bConnectToModel, m_bDataInColumns ) ); } } catch( const uno::Exception & ex ) @@ -847,14 +400,14 @@ InternalDataProvider::InternalDataProvider( InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) : impl::InternalDataProvider_Base(), m_aSequenceMap( rOther.m_aSequenceMap ), - m_apData( new impl::InternalData( rOther.getInternalData())), + m_aInternalData( rOther.m_aInternalData ), m_bDataInColumns( rOther.m_bDataInColumns ) {} InternalDataProvider::~InternalDataProvider() {} -void InternalDataProvider::addDataSequenceToMap( +void InternalDataProvider::lcl_addDataSequenceToMap( const OUString & rRangeRepresentation, const Reference< chart2::data::XDataSequence > & xSequence ) { @@ -864,7 +417,7 @@ void InternalDataProvider::addDataSequenceToMap( uno::WeakReference< chart2::data::XDataSequence >( xSequence ))); } -void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresentation ) +void InternalDataProvider::lcl_deleteMapReferences( const OUString & rRangeRepresentation ) { // set sequence to deleted by setting its range to an empty string tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation )); @@ -882,7 +435,7 @@ void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresent m_aSequenceMap.erase( aRange.first, aRange.second ); } -void InternalDataProvider::adaptMapReferences( +void InternalDataProvider::lcl_adaptMapReferences( const OUString & rOldRangeRepresentation, const OUString & rNewRangeRepresentation ) { @@ -907,70 +460,52 @@ void InternalDataProvider::adaptMapReferences( m_aSequenceMap.upper_bound( rNewRangeRepresentation ))); } -void InternalDataProvider::increaseMapReferences( +void InternalDataProvider::lcl_increaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd ) { for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex ) { - adaptMapReferences( OUString::valueOf( nIndex ), + lcl_adaptMapReferences( OUString::valueOf( nIndex ), OUString::valueOf( nIndex + 1 )); - adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ), + lcl_adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ), lcl_aLabelRangePrefix + OUString::valueOf( nIndex + 1 )); } } -void InternalDataProvider::decreaseMapReferences( +void InternalDataProvider::lcl_decreaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd ) { for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex ) { - adaptMapReferences( OUString::valueOf( nIndex ), + lcl_adaptMapReferences( OUString::valueOf( nIndex ), OUString::valueOf( nIndex - 1 )); - adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ), + lcl_adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ), lcl_aLabelRangePrefix + OUString::valueOf( nIndex - 1 )); } } -Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap( +Reference< chart2::data::XDataSequence > InternalDataProvider::lcl_createDataSequenceAndAddToMap( const OUString & rRangeRepresentation ) { Reference< chart2::data::XDataSequence > xSeq( new UncachedDataSequence( this, rRangeRepresentation )); - addDataSequenceToMap( rRangeRepresentation, xSeq ); + lcl_addDataSequenceToMap( rRangeRepresentation, xSeq ); return xSeq; } -Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap( +Reference< chart2::data::XDataSequence > InternalDataProvider::lcl_createDataSequenceAndAddToMap( const OUString & rRangeRepresentation, const OUString & rRole ) { Reference< chart2::data::XDataSequence > xSeq( new UncachedDataSequence( this, rRangeRepresentation, rRole )); - addDataSequenceToMap( rRangeRepresentation, xSeq ); + lcl_addDataSequenceToMap( rRangeRepresentation, xSeq ); return xSeq; } -const impl::InternalData & InternalDataProvider::getInternalData() const -{ - if( m_apData.get()) - return *(m_apData.get()); - - m_apData.reset( new impl::InternalData()); - return *(m_apData.get()); -} - -impl::InternalData & InternalDataProvider::getInternalData() -{ - if( m_apData.get()) - return *(m_apData.get()); - - m_apData.reset( new impl::InternalData()); - return *(m_apData.get()); -} - void InternalDataProvider::createDefaultData() { - getInternalData().createDefaultData(); + m_aInternalData.createDefaultData(); } // ____ XDataProvider ____ @@ -980,6 +515,24 @@ void InternalDataProvider::createDefaultData() return true; } +namespace +{ + +sal_Int32 lcl_getInnerLevelCount( const vector< vector< OUString > >& rLabels ) +{ + sal_Int32 nCount = 1;//minimum is 1! + vector< vector< OUString > >::const_iterator aLevelIt( rLabels.begin() ); + vector< vector< OUString > >::const_iterator aLevelEnd( rLabels.end() ); + for( ;aLevelIt!=aLevelEnd; ++aLevelIt ) + { + const vector< ::rtl::OUString >& rCurrentLevelLabels = *aLevelIt; + nCount = std::max<sal_Int32>( rCurrentLevelLabels.size(), nCount ); + } + return nCount; +} + +}//end anonymous namespace + Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource( const Sequence< beans::PropertyValue >& aArguments ) throw (lang::IllegalArgumentException, @@ -992,25 +545,51 @@ Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createData uno::Sequence< sal_Int32 > aSequenceMapping; DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ); + if( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) ) + { + //return split complex categories if we have any: + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories; + vector< vector< OUString > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels()); + if( bUseColumns==m_bDataInColumns ) + { + sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories ); + for( sal_Int32 nL=0; nL<nLevelCount; nL++ ) + aComplexCategories.push_back( new LabeledDataSequence( + new UncachedDataSequence( this + , lcl_aCategoriesLevelRangeNamePrefix + OUString::valueOf( nL ) + , lcl_aCategoriesRoleName ) ) ); + } + else + { + sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount(); + for( sal_Int32 nP=0; nP<nPointCount; nP++ ) + aComplexCategories.push_back( new LabeledDataSequence( + new UncachedDataSequence( this + , lcl_aCategoriesPointRangeNamePrefix + OUString::valueOf( nP ) + , lcl_aCategoriesRoleName ) ) ); + } + //don't add the created sequences to the map as they are used temporarily only ... + return new DataSource( ContainerHelper::ContainerToSequence(aComplexCategories) ); + } + OSL_ASSERT( aRangeRepresentation.equals( lcl_aCompleteRange )); ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec; - impl::InternalData & rData( getInternalData()); // categories - if ( bHasCategories ) + if( bHasCategories ) aResultLSeqVec.push_back( - new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ))); + new LabeledDataSequence( lcl_createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) ); // data with labels ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec; - const sal_Int32 nCount = (bUseColumns ? rData.getColumnCount() : rData.getRowCount()); - for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) + const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount()); + for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) { aDataVec.push_back( new LabeledDataSequence( - createDataSequenceAndAddToMap( OUString::valueOf( nIdx )), - createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIdx )))); + lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIdx )), + lcl_createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIdx )))); } // attention: this data provider has the limitation that it stores @@ -1082,29 +661,31 @@ Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDa throw (lang::IllegalArgumentException, uno::RuntimeException) { - if( aRangeRepresentation.equals( lcl_aCategoriesRangeName )) + if( aRangeRepresentation.match( lcl_aCategoriesRangeName )) { + OSL_ASSERT( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implmented that only parts of the categories are really requested + // categories - return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ); + return lcl_createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ); } else if( aRangeRepresentation.match( lcl_aLabelRangePrefix )) { // label sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); - return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIndex )); + return lcl_createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIndex )); } else if( aRangeRepresentation.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "last" ))) { sal_Int32 nIndex = (m_bDataInColumns - ? getInternalData().getColumnCount() - : getInternalData().getRowCount()) - 1; - return createDataSequenceAndAddToMap( OUString::valueOf( nIndex )); + ? m_aInternalData.getColumnCount() + : m_aInternalData.getRowCount()) - 1; + return lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIndex )); } else if( aRangeRepresentation.getLength()) { // data sal_Int32 nIndex = aRangeRepresentation.toInt32(); - return createDataSequenceAndAddToMap( OUString::valueOf( nIndex )); + return lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIndex )); } return Reference< chart2::data::XDataSequence >(); @@ -1122,21 +703,21 @@ Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelec throw (uno::RuntimeException) { sal_Bool bResult = false; - const impl::InternalData & rData( getInternalData()); - if( aRange.equals( lcl_aCategoriesRangeName )) + if( aRange.match( lcl_aCategoriesRangeName )) { + OSL_ASSERT( aRange.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implmented that only parts of the categories are really requested bResult = true; } else if( aRange.match( lcl_aLabelRangePrefix )) { sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); - bResult = (nIndex < (m_bDataInColumns ? rData.getColumnCount(): rData.getRowCount())); + bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount())); } else { sal_Int32 nIndex = aRange.toInt32(); - bResult = (nIndex < (m_bDataInColumns ? rData.getColumnCount(): rData.getRowCount())); + bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount())); } return bResult; @@ -1146,34 +727,67 @@ Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation throw (uno::RuntimeException) { Sequence< uno::Any > aResult; - const impl::InternalData & rData( getInternalData()); - if( aRange.equals( lcl_aCategoriesRangeName )) + if( aRange.match( lcl_aLabelRangePrefix ) ) { - vector< OUString > aCategories( m_bDataInColumns ? rData.getRowLabels() : rData.getColumnLabels()); - aResult.realloc( aCategories.size()); - transform( aCategories.begin(), aCategories.end(), - aResult.getArray(), CommonFunctors::makeAny< OUString >()); + sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + vector< OUString > aComplexLabel = m_bDataInColumns + ? m_aInternalData.getComplexColumnLabel( nIndex ) + : m_aInternalData.getComplexRowLabel( nIndex ); + if( !aComplexLabel.empty() ) + { + aResult.realloc( aComplexLabel.size() ); + transform( aComplexLabel.begin(), aComplexLabel.end(), + aResult.getArray(), CommonFunctors::makeAny< OUString >()); + } } - else if( aRange.match( lcl_aLabelRangePrefix )) + else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) ) { - sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); - vector< OUString > aLabels( m_bDataInColumns ? rData.getColumnLabels() : rData.getRowLabels()); - if( nIndex < static_cast< sal_Int32 >( aLabels.size())) + sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesPointRangeNamePrefix.getLength() ).toInt32(); + vector< OUString > aComplexCategory = m_bDataInColumns + ? m_aInternalData.getComplexRowLabel( nPointIndex ) + : m_aInternalData.getComplexColumnLabel( nPointIndex ); + if( !aComplexCategory.empty() ) { - aResult.realloc( 1 ); - aResult[0] = uno::makeAny( aLabels[ nIndex ] ); + aResult.realloc( aComplexCategory.size() ); + transform( aComplexCategory.begin(), aComplexCategory.end(), + aResult.getArray(), CommonFunctors::makeAny< OUString >()); } } + else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) ) + { + sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength() ).toInt32(); + vector< vector< OUString > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels()); + if( nLevel < lcl_getInnerLevelCount( aCategories ) ) + { + aResult.realloc( aCategories.size() ); + transform( aCategories.begin(), aCategories.end(), + aResult.getArray(), lcl_makeAnyFromLevelVector(nLevel) ); + } + } + else if( aRange.equals( lcl_aCategoriesRangeName ) ) + { + Sequence< OUString > aLabels = m_bDataInColumns ? this->getRowDescriptions() : this->getColumnDescriptions(); + aResult.realloc( aLabels.getLength() ); + transform( aLabels.getConstArray(), aLabels.getConstArray() + aLabels.getLength(), + aResult.getArray(), CommonFunctors::makeAny< OUString >() ); + } else { sal_Int32 nIndex = aRange.toInt32(); - if( nIndex < (m_bDataInColumns ? rData.getColumnCount() : rData.getRowCount())) + if( nIndex >= 0 ) { - Sequence< double > aData( rData.getDataAt( nIndex, m_bDataInColumns )); - aResult.realloc( aData.getLength()); - transform( aData.getConstArray(), aData.getConstArray() + aData.getLength(), - aResult.getArray(), CommonFunctors::makeAny< double >()); + Sequence< double > aData; + if( m_bDataInColumns ) + aData = m_aInternalData.getColumnValues(nIndex); + else + aData = m_aInternalData.getRowValues(nIndex); + if( aData.getLength() ) + { + aResult.realloc( aData.getLength()); + transform( aData.getConstArray(), aData.getConstArray() + aData.getLength(), + aResult.getArray(), CommonFunctors::makeAny< double >()); + } } } @@ -1184,61 +798,63 @@ void SAL_CALL InternalDataProvider::setDataByRangeRepresentation( const OUString& aRange, const Sequence< uno::Any >& aNewData ) throw (uno::RuntimeException) { - impl::InternalData & rData( getInternalData()); - - if( aRange.equals( lcl_aCategoriesRangeName )) + if( aRange.match( lcl_aLabelRangePrefix ) ) + { + vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) ); + sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + if( m_bDataInColumns ) + m_aInternalData.setComplexColumnLabel( nIndex, aNewStrings ); + else + m_aInternalData.setComplexRowLabel( nIndex, aNewStrings ); + } + else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) ) { - vector< OUString > aCategories; - transform( aNewData.getConstArray(), aNewData.getConstArray() + aNewData.getLength(), - back_inserter( aCategories ), CommonFunctors::AnyToString()); + vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) ); + sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32(); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabel( nPointIndex, aNewStrings ); + else + m_aInternalData.setComplexColumnLabel( nPointIndex, aNewStrings ); + } + else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) ) + { + vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) ); + sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32(); + vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels(); + + //ensure equal length + if( aNewStrings.size() > aComplexCategories.size() ) + aComplexCategories.resize( aNewStrings.size() ); + else if( aNewStrings.size() < aComplexCategories.size() ) + aNewStrings.resize( aComplexCategories.size() ); + + transform( aComplexCategories.begin(), aComplexCategories.end(), aNewStrings.begin(), + aComplexCategories.begin(), lcl_setStringAtLevel(nLevel) ); if( m_bDataInColumns ) - rData.setRowLabels( aCategories ); + m_aInternalData.setComplexRowLabels( aComplexCategories ); else - rData.setColumnLabels( aCategories ); + m_aInternalData.setComplexColumnLabels( aComplexCategories ); } - else if( aRange.match( lcl_aLabelRangePrefix )) + else if( aRange.equals( lcl_aCategoriesRangeName ) ) { - sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); - OUString aNewLabel; - if( aNewData.getLength() && - (aNewData[0] >>= aNewLabel)) - { - if( m_bDataInColumns ) - { - vector< OUString > aLabels( rData.getColumnLabels()); - if ( aLabels.size() <= nIndex ) - aLabels.push_back(aNewLabel); - else - aLabels[ nIndex ] = aNewLabel; - rData.setColumnLabels( aLabels ); - } - else - { - vector< OUString > aLabels( rData.getRowLabels()); - if ( aLabels.size() <= nIndex ) - aLabels.push_back(aNewLabel); - else - aLabels[ nIndex ] = aNewLabel; - rData.setRowLabels( aLabels ); - } - } + if( m_bDataInColumns ) + this->setRowDescriptions( lcl_AnyToStringSequence(aNewData) ); + else + this->setColumnDescriptions( lcl_AnyToStringSequence(aNewData) ); } else { sal_Int32 nIndex = aRange.toInt32(); - // ensure that the data is large enough - if( m_bDataInColumns ) - rData.enlargeData( nIndex, 0 ); - else - rData.enlargeData( 0, nIndex ); - - if( nIndex < (m_bDataInColumns ? rData.getColumnCount() : rData.getRowCount())) + if( nIndex>=0 ) { vector< double > aNewDataVec; transform( aNewData.getConstArray(), aNewData.getConstArray() + aNewData.getLength(), back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble()); - rData.setDataAt( nIndex, m_bDataInColumns, aNewDataVec ); + if( m_bDataInColumns ) + m_aInternalData.setColumnValues( nIndex, aNewDataVec ); + else + m_aInternalData.setRowValues( nIndex, aNewDataVec ); } } } @@ -1248,30 +864,30 @@ void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex ) { if( m_bDataInColumns ) { - increaseMapReferences( nAfterIndex + 1, getInternalData().getColumnCount()); - getInternalData().insertColumn( nAfterIndex ); + lcl_increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount()); + m_aInternalData.insertColumn( nAfterIndex ); } else { - increaseMapReferences( nAfterIndex + 1, getInternalData().getRowCount()); - getInternalData().insertRow( nAfterIndex ); + lcl_increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount()); + m_aInternalData.insertRow( nAfterIndex ); } } void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex ) throw (uno::RuntimeException) { - deleteMapReferences( OUString::valueOf( nAtIndex )); - deleteMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nAtIndex )); + lcl_deleteMapReferences( OUString::valueOf( nAtIndex )); + lcl_deleteMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nAtIndex )); if( m_bDataInColumns ) { - decreaseMapReferences( nAtIndex + 1, getInternalData().getColumnCount()); - getInternalData().deleteColumn( nAtIndex ); + lcl_decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount()); + m_aInternalData.deleteColumn( nAtIndex ); } else { - decreaseMapReferences( nAtIndex + 1, getInternalData().getRowCount()); - getInternalData().deleteRow( nAtIndex ); + lcl_decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount()); + m_aInternalData.deleteRow( nAtIndex ); } } @@ -1279,9 +895,44 @@ void SAL_CALL InternalDataProvider::appendSequence() throw (uno::RuntimeException) { if( m_bDataInColumns ) - getInternalData().appendColumn(); + m_aInternalData.appendColumn(); else - getInternalData().appendRow(); + m_aInternalData.appendRow(); +} + +void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel ) + throw (uno::RuntimeException) +{ + OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error + if( nLevel>0 ) + { + vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels(); + ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertStringAtLevel(nLevel) ); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); + } +} +void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel ) + throw (uno::RuntimeException) +{ + OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error + if( nLevel>0 ) + { + vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels(); + ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeStringAtLevel(nLevel) ); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); + } } void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex ) @@ -1290,22 +941,22 @@ void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 sal_Int32 nMaxRep = 0; if( m_bDataInColumns ) { - getInternalData().insertRow( nAfterIndex ); - nMaxRep = getInternalData().getColumnCount(); + m_aInternalData.insertRow( nAfterIndex ); + nMaxRep = m_aInternalData.getColumnCount(); } else { - getInternalData().insertColumn( nAfterIndex ); - nMaxRep = getInternalData().getRowCount(); + m_aInternalData.insertColumn( nAfterIndex ); + nMaxRep = m_aInternalData.getRowCount(); } // notify change to all affected ranges tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0"))); tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep ))); - ::std::for_each( aBegin, aEnd, lcl_modifySeqMapValue()); + ::std::for_each( aBegin, aEnd, lcl_setModified()); tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); - ::std::for_each( aRange.first, aRange.second, lcl_modifySeqMapValue()); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); } void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex ) @@ -1314,46 +965,49 @@ void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 sal_Int32 nMaxRep = 0; if( m_bDataInColumns ) { - getInternalData().deleteRow( nAtIndex ); - nMaxRep = getInternalData().getColumnCount(); + m_aInternalData.deleteRow( nAtIndex ); + nMaxRep = m_aInternalData.getColumnCount(); } else { - getInternalData().deleteColumn( nAtIndex ); - nMaxRep = getInternalData().getRowCount(); + m_aInternalData.deleteColumn( nAtIndex ); + nMaxRep = m_aInternalData.getRowCount(); } // notify change to all affected ranges tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0"))); tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep ))); - ::std::for_each( aBegin, aEnd, lcl_modifySeqMapValue()); + ::std::for_each( aBegin, aEnd, lcl_setModified()); tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); - ::std::for_each( aRange.first, aRange.second, lcl_modifySeqMapValue()); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); } void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex ) throw (uno::RuntimeException) { - getInternalData().swapAllDataAtIndexWithNext( nAtIndex, m_bDataInColumns ); + if( m_bDataInColumns ) + m_aInternalData.swapRowWithNext( nAtIndex ); + else + m_aInternalData.swapColumnWithNext( nAtIndex ); sal_Int32 nMaxRep = (m_bDataInColumns - ? getInternalData().getColumnCount() - : getInternalData().getRowCount()); + ? m_aInternalData.getColumnCount() + : m_aInternalData.getRowCount()); // notify change to all affected ranges tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0"))); tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep ))); - ::std::for_each( aBegin, aEnd, lcl_modifySeqMapValue()); + ::std::for_each( aBegin, aEnd, lcl_setModified()); tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); - ::std::for_each( aRange.first, aRange.second, lcl_modifySeqMapValue()); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); } void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq ) throw (uno::RuntimeException) { if( xSeq.is()) - addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq ); + lcl_addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq ); } @@ -1364,28 +1018,28 @@ OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRang { XMLRangeHelper::CellRange aRange; aRange.aTableName = OUString(RTL_CONSTASCII_USTRINGPARAM("local-table")); - impl::InternalData & rData( getInternalData()); // attention: this data provider has the limitation that it stores // internally if data comes from columns or rows. It is intended for // creating only one used data source. // @todo: add this information in the range representation strings - if( aRangeRepresentation.equals( lcl_aCategoriesRangeName )) + if( aRangeRepresentation.match( lcl_aCategoriesRangeName )) { + OSL_ASSERT( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implmented that only parts of the categories are really requested aRange.aUpperLeft.bIsEmpty = false; if( m_bDataInColumns ) { aRange.aUpperLeft.nColumn = 0; aRange.aUpperLeft.nRow = 1; aRange.aLowerRight = aRange.aUpperLeft; - aRange.aLowerRight.nRow = rData.getRowCount(); + aRange.aLowerRight.nRow = m_aInternalData.getRowCount(); } else { aRange.aUpperLeft.nColumn = 1; aRange.aUpperLeft.nRow = 0; aRange.aLowerRight = aRange.aUpperLeft; - aRange.aLowerRight.nColumn = rData.getColumnCount(); + aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount(); } } else if( aRangeRepresentation.match( lcl_aLabelRangePrefix )) @@ -1410,8 +1064,8 @@ OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRang aRange.aLowerRight.bIsEmpty = false; aRange.aUpperLeft.nColumn = 0; aRange.aUpperLeft.nRow = 0; - aRange.aLowerRight.nColumn = rData.getColumnCount(); - aRange.aLowerRight.nRow = rData.getRowCount(); + aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount(); + aRange.aLowerRight.nRow = m_aInternalData.getRowCount(); } else { @@ -1422,14 +1076,14 @@ OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRang aRange.aUpperLeft.nColumn = nIndex + 1; aRange.aUpperLeft.nRow = 1; aRange.aLowerRight = aRange.aUpperLeft; - aRange.aLowerRight.nRow = rData.getRowCount(); + aRange.aLowerRight.nRow = m_aInternalData.getRowCount(); } else { aRange.aUpperLeft.nColumn = 1; aRange.aUpperLeft.nRow = nIndex + 1; aRange.aLowerRight = aRange.aUpperLeft; - aRange.aLowerRight.nColumn = rData.getColumnCount(); + aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount(); } } @@ -1478,46 +1132,130 @@ OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXM return OUString::valueOf( aRange.aUpperLeft.nRow - 1 ); } +namespace +{ +Sequence< Sequence< OUString > > lcl_convertComplexVectorToSequence( const vector< vector< OUString > >& rIn ) +{ + Sequence< Sequence< OUString > > aRet; + sal_Int32 nOuterCount = rIn.size(); + if( nOuterCount ) + { + aRet.realloc(nOuterCount); + for( sal_Int32 nN=0; nN<nOuterCount; nN++) + aRet[nN]=ContainerHelper::ContainerToSequence( rIn[nN] ); + } + return aRet; +} + +vector< vector< OUString > > lcl_convertComplexSequenceToVector( const Sequence< Sequence< OUString > >& rIn ) +{ + vector< vector< OUString > > aRet; + sal_Int32 nOuterCount = rIn.getLength(); + for( sal_Int32 nN=0; nN<nOuterCount; nN++) + aRet.push_back( ContainerHelper::SequenceToVector( rIn[nN] ) ); + return aRet; +} + +class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider +{ +public: + + explicit SplitCategoriesProvider_ForComplexDescriptions( const ::std::vector< ::std::vector< ::rtl::OUString > >& rComplexDescriptions ) + : m_rComplexDescriptions( rComplexDescriptions ) + {} + virtual ~SplitCategoriesProvider_ForComplexDescriptions() + {} + + virtual sal_Int32 getLevelCount() const; + virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const; + +private: + const ::std::vector< ::std::vector< ::rtl::OUString > >& m_rComplexDescriptions; +}; + +sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const +{ + return lcl_getInnerLevelCount( m_rComplexDescriptions ); +} +uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const +{ + uno::Sequence< rtl::OUString > aResult; + if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) ) + { + aResult.realloc( m_rComplexDescriptions.size() ); + transform( m_rComplexDescriptions.begin(), m_rComplexDescriptions.end(), + aResult.getArray(), lcl_getStringFromLevelVector(nLevel) ); + } + return aResult; +} + +}//anonymous namespace + +// ____ XComplexDescriptionAccess ____ +Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions() throw (uno::RuntimeException) +{ + return lcl_convertComplexVectorToSequence( m_aInternalData.getComplexRowLabels() ); +} +void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aRowDescriptions ) throw (uno::RuntimeException) +{ + m_aInternalData.setComplexRowLabels( lcl_convertComplexSequenceToVector(aRowDescriptions) ); +} +Sequence< Sequence< ::rtl::OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions() throw (uno::RuntimeException) +{ + return lcl_convertComplexVectorToSequence( m_aInternalData.getComplexColumnLabels() ); +} +void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aColumnDescriptions ) throw (uno::RuntimeException) +{ + m_aInternalData.setComplexColumnLabels( lcl_convertComplexSequenceToVector(aColumnDescriptions) ); +} + // ____ XChartDataArray ____ -// note: do not use m_bDataInColumns for all XChartDataArray-specific code -// the chart-API assumes data is always in rows Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData() throw (uno::RuntimeException) { - return getInternalData().getData( false ); + return m_aInternalData.getData(); } -void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& aData ) +void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows ) throw (uno::RuntimeException) { - return getInternalData().setData( aData, false ); + return m_aInternalData.setData( rDataInRows ); } -Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions() +void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions ) throw (uno::RuntimeException) { - return ContainerHelper::ContainerToSequence( getInternalData().getRowLabels()); + vector< vector< OUString > > aComplexDescriptions( aRowDescriptions.getLength() ); + transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(), + aComplexDescriptions.begin(), lcl_setStringAtLevel(0) ); + m_aInternalData.setComplexRowLabels( aComplexDescriptions ); } -void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions ) +void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions ) throw (uno::RuntimeException) { - getInternalData().setRowLabels( ContainerHelper::SequenceToVector( aRowDescriptions )); + vector< vector< OUString > > aComplexDescriptions( aColumnDescriptions.getLength() ); + transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(), + aComplexDescriptions.begin(), lcl_setStringAtLevel(0) ); + m_aInternalData.setComplexColumnLabels( aComplexDescriptions ); } -Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions() +Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions() throw (uno::RuntimeException) { - return ContainerHelper::ContainerToSequence( getInternalData().getColumnLabels()); + vector< vector< OUString > > aComplexLabels( m_aInternalData.getComplexRowLabels() ); + SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels ); + return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider ); } -void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions ) +Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions() throw (uno::RuntimeException) { - getInternalData().setColumnLabels( ContainerHelper::SequenceToVector( aColumnDescriptions )); + vector< vector< OUString > > aComplexLabels( m_aInternalData.getComplexColumnLabels() ); + SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels ); + return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider ); } - // ____ XChartData (base of XChartDataArray) ____ void SAL_CALL InternalDataProvider::addChartDataChangeEventListener( const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& ) diff --git a/chart2/source/tools/makefile.mk b/chart2/source/tools/makefile.mk index 2b6e0cf518c1..2f990af7adb0 100644 --- a/chart2/source/tools/makefile.mk +++ b/chart2/source/tools/makefile.mk @@ -64,6 +64,7 @@ SLOFILES= \ $(SLO)$/DiagramHelper.obj \ $(SLO)$/ExponentialRegressionCurveCalculator.obj \ $(SLO)$/ImplOPropertySet.obj \ + $(SLO)$/InternalData.obj \ $(SLO)$/InternalDataProvider.obj \ $(SLO)$/LabeledDataSequence.obj \ $(SLO)$/LinearRegressionCurveCalculator.obj \ diff --git a/chart2/source/view/axes/TickmarkHelper.cxx b/chart2/source/view/axes/TickmarkHelper.cxx index 20f452431492..4d1f48795fa7 100644 --- a/chart2/source/view/axes/TickmarkHelper.cxx +++ b/chart2/source/view/axes/TickmarkHelper.cxx @@ -48,6 +48,7 @@ TickInfo::TickInfo() , aTickScreenPosition(0.0,0.0) , bPaintIt( true ) , xTextShape( NULL ) +, nFactorForLimitedTextWidth(1) { } @@ -59,10 +60,45 @@ void TickInfo::updateUnscaledValue( const uno::Reference< XScaling >& xInverseSc this->fUnscaledTickValue = this->fScaledTickValue; } -TickIter::TickIter( const uno::Sequence< uno::Sequence< double > >& rTicks +sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const +{ + //return the positive distance between the two first tickmarks in screen values + + B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition; + sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength()); + if(nRet<0) + nRet *= -1; + return nRet; +} + +PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ) + : m_rTickVector(rTickInfoVector) + , m_aTickIter(m_rTickVector.begin()) +{ +} +PureTickIter::~PureTickIter() +{ +} +TickInfo* PureTickIter::firstInfo() +{ + m_aTickIter = m_rTickVector.begin(); + if(m_aTickIter!=m_rTickVector.end()) + return &*m_aTickIter; + return 0; +} +TickInfo* PureTickIter::nextInfo() +{ + m_aTickIter++; + if(m_aTickIter!=m_rTickVector.end()) + return &*m_aTickIter; + return 0; +} + +EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : m_pSimpleTicks(&rTicks), m_pInfoTicks(NULL) + : m_pSimpleTicks(&rTicks) + , m_pInfoTicks(0) , m_rIncrement(rIncrement) , m_nMinDepth(0), m_nMaxDepth(0) , m_nTickCount(0), m_pnPositions(NULL) @@ -72,10 +108,11 @@ TickIter::TickIter( const uno::Sequence< uno::Sequence< double > >& rTicks initIter( nMinDepth, nMaxDepth ); } -TickIter::TickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks +EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : m_pSimpleTicks(NULL), m_pInfoTicks(&rTicks) + : m_pSimpleTicks(NULL) + , m_pInfoTicks(&rTicks) , m_rIncrement(rIncrement) , m_nMinDepth(0), m_nMaxDepth(0) , m_nTickCount(0), m_pnPositions(NULL) @@ -85,7 +122,7 @@ TickIter::TickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks initIter( nMinDepth, nMaxDepth ); } -void TickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) +void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) { m_nMaxDepth = nMaxDepth; if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth()) @@ -128,14 +165,14 @@ void TickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) } } -TickIter::~TickIter() +EquidistantTickIter::~EquidistantTickIter() { delete[] m_pnPositions; delete[] m_pnPreParentCount; delete[] m_pbIntervalFinished; } -sal_Int32 TickIter::getStartDepth() const +sal_Int32 EquidistantTickIter::getStartDepth() const { //find the depth of the first visible tickmark: //it is the depth of the smallest value @@ -156,7 +193,7 @@ sal_Int32 TickIter::getStartDepth() const return nReturnDepth; } -double* TickIter::firstValue() +double* EquidistantTickIter::firstValue() { if( gotoFirst() ) { @@ -166,14 +203,14 @@ double* TickIter::firstValue() return NULL; } -TickInfo* TickIter::firstInfo() +TickInfo* EquidistantTickIter::firstInfo() { if( m_pInfoTicks && gotoFirst() ) return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; return NULL; } -sal_Int32 TickIter::getIntervalCount( sal_Int32 nDepth ) +sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth ) { if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<0) return 0; @@ -184,7 +221,7 @@ sal_Int32 TickIter::getIntervalCount( sal_Int32 nDepth ) return m_rIncrement.SubIncrements[nDepth-1].IntervalCount; } -bool TickIter::isAtLastPartTick() +bool EquidistantTickIter::isAtLastPartTick() { if(!m_nCurrentDepth) return false; @@ -203,7 +240,7 @@ bool TickIter::isAtLastPartTick() return bRet; } -bool TickIter::gotoFirst() +bool EquidistantTickIter::gotoFirst() { if( m_nMaxDepth<0 ) return false; @@ -219,7 +256,7 @@ bool TickIter::gotoFirst() return true; } -bool TickIter::gotoNext() +bool EquidistantTickIter::gotoNext() { if( m_nCurrentPos < 0 ) return false; @@ -250,7 +287,7 @@ bool TickIter::gotoNext() return true; } -bool TickIter::gotoIndex( sal_Int32 nTickIndex ) +bool EquidistantTickIter::gotoIndex( sal_Int32 nTickIndex ) { if( nTickIndex < 0 ) return false; @@ -268,16 +305,16 @@ bool TickIter::gotoIndex( sal_Int32 nTickIndex ) return true; } -sal_Int32 TickIter::getCurrentIndex() const +sal_Int32 EquidistantTickIter::getCurrentIndex() const { return m_nCurrentPos; } -sal_Int32 TickIter::getMaxIndex() const +sal_Int32 EquidistantTickIter::getMaxIndex() const { return m_nTickCount-1; } -double* TickIter::nextValue() +double* EquidistantTickIter::nextValue() { if( gotoNext() ) { @@ -287,7 +324,7 @@ double* TickIter::nextValue() return NULL; } -TickInfo* TickIter::nextInfo() +TickInfo* EquidistantTickIter::nextInfo() { if( m_pInfoTicks && gotoNext() && static_cast< sal_Int32 >( @@ -646,7 +683,7 @@ void TickmarkHelper::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo void TickmarkHelper::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const { - TickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); + EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); double* pfNextParentTick = aIter.firstValue(); if(!pfNextParentTick) return; @@ -753,11 +790,7 @@ sal_Int32 TickmarkHelper_2D::getTickScreenDistance( TickIter& rIter ) if(!pSecondTickInfo || !pFirstTickInfo) return -1; - B2DVector aDistance = pSecondTickInfo->aTickScreenPosition-pFirstTickInfo->aTickScreenPosition; - sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength()); - if(nRet<0) - nRet *= -1; - return nRet; + return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo ); } B2DVector TickmarkHelper_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const @@ -797,7 +830,7 @@ void TickmarkHelper_2D::addPointSequenceForTickLine( drawing::PointSequenceSeque rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY()); } -B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties ) const +B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const { bool bFarAwayLabels = false; if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos @@ -843,8 +876,9 @@ B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rA if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) aOrthoLabelDirection*=-1.0; aOrthoLabelDirection.normalize(); - aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; - if( bFarAwayLabels ) + if( bIncludeSpaceBetweenTickAndText ) + aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; + if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo ) aLabelDirection += m_aAxisLineToLabelLineShift; return aLabelDirection; } @@ -876,27 +910,6 @@ void TickmarkHelper_2D::updateScreenValues( ::std::vector< ::std::vector< TickIn } } -//'hide' tickmarks with identical screen values in aAllTickInfos -void TickmarkHelper_2D::hideIdenticalScreenValues( - ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const -{ - TickIter aIter( rAllTickInfos, m_rIncrement ); - - TickInfo* pPreviousTickInfo = aIter.firstInfo(); - if(!pPreviousTickInfo) - return; - pPreviousTickInfo->bPaintIt = true; - for( TickInfo* pTickInfo = aIter.nextInfo(); pTickInfo; pTickInfo = aIter.nextInfo()) - { - pTickInfo->bPaintIt = - ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX()) - != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) ) - || - ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY()) - != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) ); - pPreviousTickInfo = pTickInfo; - } -} //----------------------------------------------------------------------------- // ___TickmarkHelper_3D___ //----------------------------------------------------------------------------- diff --git a/chart2/source/view/axes/TickmarkHelper.hxx b/chart2/source/view/axes/TickmarkHelper.hxx index 01ca56982b3e..78fc2fe1c502 100644 --- a/chart2/source/view/axes/TickmarkHelper.hxx +++ b/chart2/source/view/axes/TickmarkHelper.hxx @@ -59,23 +59,48 @@ struct TickInfo ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xTextShape; + rtl::OUString aText;//used only for complex categories so far + sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category + //methods: TickInfo(); void updateUnscaledValue( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >& xInverseScaling ); -}; + sal_Int32 getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const; +}; class TickIter { public: - TickIter( const ::com::sun::star::uno::Sequence< + virtual ~TickIter(){}; + virtual TickInfo* firstInfo()=0; + virtual TickInfo* nextInfo()=0; +}; + +class PureTickIter : public TickIter +{ +public: + PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ); + virtual ~PureTickIter(); + virtual TickInfo* firstInfo(); + virtual TickInfo* nextInfo(); + +private: + ::std::vector< TickInfo >& m_rTickVector; + ::std::vector< TickInfo >::iterator m_aTickIter; +}; + +class EquidistantTickIter : public TickIter +{ +public: + EquidistantTickIter( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& rTicks , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); - TickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos + EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); - virtual ~TickIter(); + virtual ~EquidistantTickIter(); virtual double* firstValue(); virtual double* nextValue(); @@ -171,7 +196,6 @@ protected: //methods bool isWithinOuterBorder( double fScaledValue ) const; //all within the outer major tick marks virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {} - virtual void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {} protected: //member ::com::sun::star::chart2::ExplicitScaleData m_rScale; @@ -211,10 +235,11 @@ public: , sal_Int32 nSequenceIndex , double fScaledLogicTickValue, double fInnerDirectionSign , const TickmarkProperties& rTickmarkProperties, bool bPlaceAtLabels ) const; - ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties ) const; + ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties + , bool bIncludeFarAwayDistanceIfSo = false + , bool bIncludeSpaceBetweenTickAndText = true ) const; virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; - virtual void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; bool isHorizontalAxis() const; bool isVerticalAxis() const; diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx index 79c2529873aa..0159fb20cad6 100644 --- a/chart2/source/view/axes/VAxisBase.cxx +++ b/chart2/source/view/axes/VAxisBase.cxx @@ -79,23 +79,31 @@ void SAL_CALL VAxisBase::initAxisLabelProperties( const ::com::sun::star::awt::S if( !m_aAxisProperties.m_bDisplayLabels ) return; - if( AxisType::CATEGORY==m_aAxisProperties.m_nAxisType - || AxisType::SERIES==m_aAxisProperties.m_nAxisType ) + if( AxisType::SERIES==m_aAxisProperties.m_nAxisType ) { if( m_aAxisProperties.m_xAxisTextProvider.is() ) m_aTextLabels = m_aAxisProperties.m_xAxisTextProvider->getTextualData(); m_bUseTextLabels = true; - if( m_aTextLabels.getLength() == 1 && AxisType::SERIES==m_aAxisProperties.m_nAxisType ) + if( m_aTextLabels.getLength() == 1 ) { //don't show a single series name m_aAxisProperties.m_bDisplayLabels = false; return; } } + else if( AxisType::CATEGORY==m_aAxisProperties.m_nAxisType ) + { + if( m_aAxisProperties.m_pExplicitCategoriesProvider ) + m_aTextLabels = m_aAxisProperties.m_pExplicitCategoriesProvider->getSimpleCategories(); + + m_bUseTextLabels = true; + } m_aAxisLabelProperties.nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey; m_aAxisLabelProperties.init(m_aAxisProperties.m_xAxisModel); + if( m_aAxisProperties.m_bComplexCategories && AxisType::CATEGORY == m_aAxisProperties.m_nAxisType ) + m_aAxisLabelProperties.eStaggering = SIDE_BY_SIDE; } void VAxisBase::recordMaximumTextSize( const Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) @@ -152,6 +160,12 @@ void SAL_CALL VAxisBase::setExplicitScaleAndIncrement( m_aIncrement = rIncrement; } +void VAxisBase::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) +{ + std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); + apTickmarkHelper->getAllTicks( rAllTickInfos ); +} + bool VAxisBase::prepareShapeCreation() { //returns true if all is ready for further shape creation and any shapes need to be created @@ -162,14 +176,9 @@ bool VAxisBase::prepareShapeCreation() { //----------------------------------------- //create all scaled tickmark values - if( m_xTextTarget.is() ) - { - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeTextShapesFromTicks( aRemoveIter, m_xTextTarget ); - } + removeTextShapesFromTicks(); - std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); - apTickmarkHelper->getAllTicks( m_aAllTickInfos ); + createAllTickInfos(m_aAllTickInfos); m_bReCreateAllTickInfos = false; } @@ -203,15 +212,25 @@ sal_Int32 VAxisBase::getIndexOfLongestLabel( const uno::Sequence< rtl::OUString return nRet; } -void VAxisBase::removeTextShapesFromTicks( TickIter& rIter, const Reference< drawing::XShapes >& xTarget ) +void VAxisBase::removeTextShapesFromTicks() { - for( TickInfo* pTickInfo = rIter.firstInfo() - ; pTickInfo; pTickInfo = rIter.nextInfo() ) + if( m_xTextTarget.is() ) { - if(pTickInfo->xTextShape.is()) + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end(); + for( ; aDepthIter != aDepthEnd; aDepthIter++ ) { - xTarget->remove(pTickInfo->xTextShape); - pTickInfo->xTextShape = NULL; + ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); + for( ; aTickIter != aTickEnd; aTickIter++ ) + { + TickInfo& rTickInfo = (*aTickIter); + if(rTickInfo.xTextShape.is()) + { + m_xTextTarget->remove(rTickInfo.xTextShape); + rTickInfo.xTextShape = NULL; + } + } } } } diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx index fba6d867c808..ba7e94b2070c 100644 --- a/chart2/source/view/axes/VAxisBase.hxx +++ b/chart2/source/view/axes/VAxisBase.hxx @@ -67,6 +67,7 @@ public: throw (::com::sun::star::uno::RuntimeException); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); + virtual void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ); void setExrtaLinePositionAtOtherAxis( const double& fCrossingAt ); @@ -74,7 +75,7 @@ public: //------------------------------------------------------------------------- protected: //methods sal_Int32 getIndexOfLongestLabel( const ::com::sun::star::uno::Sequence< rtl::OUString >& rLabels ); - void removeTextShapesFromTicks( TickIter& rIter, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget ); + void removeTextShapesFromTicks(); void updateUnscaledValuesAtTicks( TickIter& rIter ); virtual bool prepareShapeCreation(); diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx index e5c90f0eda4d..436541ef27ee 100644 --- a/chart2/source/view/axes/VAxisProperties.cxx +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -144,6 +144,18 @@ TickmarkProperties AxisProperties::makeTickmarkProperties( return aTickmarkProperties; } +TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories( + sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 /*nTextLevel*/ ) const +{ + sal_Int32 nTickmarkStyle = (m_fLabelDirectionSign==m_fInnerDirectionSign) ? 2/*outside*/ : 1/*inside*/; + + TickmarkProperties aTickmarkProperties; + aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) ); + aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle)); + aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( 0 ); + return aTickmarkProperties; +} + //static TickmarkProperties AxisProperties::getBiggestTickmarkProperties() { @@ -158,7 +170,7 @@ TickmarkProperties AxisProperties::getBiggestTickmarkProperties() //-------------------------------------------------------------------------- AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel - , const uno::Reference< data::XTextualDataSequence >& xAxisTextProvider ) + , ExplicitCategoriesProvider* pExplicitCategoriesProvider ) : m_xAxisModel(xAxisModel) , m_nDimensionIndex(0) , m_bIsMainAxis(true) @@ -173,7 +185,6 @@ AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel , m_bAxisBetweenCategories(false) , m_fLabelDirectionSign(1.0) , m_fInnerDirectionSign(1.0) - , m_bLabelsOutside(true) , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP) , m_bDisplayLabels( true ) , m_nNumberFormatKey(0) @@ -183,8 +194,9 @@ AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel , m_aLineProperties() //for category axes , m_nAxisType(AxisType::REALNUMBER) - , m_xAxisTextProvider(xAxisTextProvider) - , m_bTickmarksAtIndicatedValue(false) + , m_bComplexCategories(false) + , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider) + , m_xAxisTextProvider(0) { } @@ -203,7 +215,6 @@ AxisProperties::AxisProperties( const AxisProperties& rAxisProperties ) , m_bAxisBetweenCategories( rAxisProperties.m_bAxisBetweenCategories ) , m_fLabelDirectionSign( rAxisProperties.m_fLabelDirectionSign ) , m_fInnerDirectionSign( rAxisProperties.m_fInnerDirectionSign ) - , m_bLabelsOutside( rAxisProperties.m_bLabelsOutside ) , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment ) , m_bDisplayLabels( rAxisProperties.m_bDisplayLabels ) , m_nNumberFormatKey( rAxisProperties.m_nNumberFormatKey ) @@ -213,8 +224,9 @@ AxisProperties::AxisProperties( const AxisProperties& rAxisProperties ) , m_aLineProperties( rAxisProperties.m_aLineProperties ) //for category axes , m_nAxisType( rAxisProperties.m_nAxisType ) + , m_bComplexCategories( rAxisProperties.m_bComplexCategories ) + , m_pExplicitCategoriesProvider( rAxisProperties.m_pExplicitCategoriesProvider ) , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider ) - , m_bTickmarksAtIndicatedValue( rAxisProperties.m_bTickmarksAtIndicatedValue ) { if( rAxisProperties.m_pfMainLinePositionAtOtherAxis ) m_pfMainLinePositionAtOtherAxis = new double(*rAxisProperties.m_pfMainLinePositionAtOtherAxis); diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx index 8a83fb6bcf7c..5b6bfe98f777 100644 --- a/chart2/source/view/axes/VAxisProperties.hxx +++ b/chart2/source/view/axes/VAxisProperties.hxx @@ -30,6 +30,7 @@ #include "TickmarkProperties.hxx" #include "PlottingPositionHelper.hxx" #include "LabelAlignment.hxx" +#include "ExplicitCategoriesProvider.hxx" #include <com/sun/star/chart/ChartAxisLabelPosition.hpp> #include <com/sun/star/chart/ChartAxisMarkPosition.hpp> @@ -84,7 +85,7 @@ struct AxisLabelProperties double fRotationAngleDegree; sal_Int32 nRhythm; //show only each nth label with n==nRhythm - bool bRhythmIsFix; //states wether the given rythm is fix or may be changed + bool bRhythmIsFix; //states wether the given rhythm is fix or may be changed //methods: void init( const ::com::sun::star::uno::Reference< @@ -116,7 +117,6 @@ struct AxisProperties double m_fLabelDirectionSign; //this direction is used to indicate in which direction inner tickmarks are to be drawn double m_fInnerDirectionSign; - bool m_bLabelsOutside; LabelAlignment m_aLabelAlignment; sal_Bool m_bDisplayLabels; @@ -133,19 +133,18 @@ struct AxisProperties VLineProperties m_aLineProperties; //for category axes -> - sal_Int32 m_nAxisType;//REALNUMBER, CATEGORY etc. type ::com::sun::star::chart2::AxisType + sal_Int32 m_nAxisType;//REALNUMBER, CATEGORY etc. type ::com::sun::star::chart2::AxisType + bool m_bComplexCategories; + ExplicitCategoriesProvider* m_pExplicitCategoriesProvider;/*no ownership here*/ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XTextualDataSequence > m_xAxisTextProvider; //for categries or series names - //position of main tickmarks in respect to the indicated value: at value or between neighboured indicated values - bool m_bTickmarksAtIndicatedValue; //<- category axes //methods: AxisProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >& xAxisModel - , const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XTextualDataSequence >& xAxisTextProvider ); + , ExplicitCategoriesProvider* pExplicitCategoriesProvider ); AxisProperties( const AxisProperties& rAxisProperties ); virtual ~AxisProperties(); virtual void init(bool bCartesian=false);//init from model data (m_xAxisModel) @@ -153,6 +152,7 @@ struct AxisProperties void initAxisPositioning( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xAxisProp ); static TickmarkProperties getBiggestTickmarkProperties(); + TickmarkProperties makeTickmarkPropertiesForComplexCategories( sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 nTextLevel ) const; private: AxisProperties(); diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx index e06360b2b1b7..caadaa554091 100644 --- a/chart2/source/view/axes/VCartesianAxis.cxx +++ b/chart2/source/view/axes/VCartesianAxis.cxx @@ -118,19 +118,19 @@ Reference< drawing::XShape > createSingleLabel( bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape , double fRotationAngleDegree , const basegfx::B2DVector& rTickScreenPosition - , TickmarkHelper_2D* pTickmarkHelper ) + , bool bIsHorizontalAxis, bool bIsVerticalAxis ) { if(!xShape.is()) return false; ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree )); - if( pTickmarkHelper->isVerticalAxis() ) + if( bIsVerticalAxis ) { return ( (rTickScreenPosition.getY() >= aShapeRect.getMinY()) && (rTickScreenPosition.getY() <= aShapeRect.getMaxY()) ); } - if( pTickmarkHelper->isHorizontalAxis() ) + if( bIsHorizontalAxis ) { return ( (rTickScreenPosition.getX() >= aShapeRect.getMinX()) && (rTickScreenPosition.getX() <= aShapeRect.getMaxX()) ); @@ -154,7 +154,7 @@ bool doesOverlap( const Reference< drawing::XShape >& xShape1 return aRect1.overlaps(aRect2); } -void removeShapesAtWrongRythm( TickIter& rIter +void removeShapesAtWrongRhythm( TickIter& rIter , sal_Int32 nCorrectRhythm , sal_Int32 nMaxTickToCheck , const Reference< drawing::XShapes >& xTarget ) @@ -164,7 +164,7 @@ void removeShapesAtWrongRythm( TickIter& rIter ; pTickInfo && nTick <= nMaxTickToCheck ; pTickInfo = rIter.nextInfo(), nTick++ ) { - //remove labels which does not fit into the rythm + //remove labels which does not fit into the rhythm if( nTick%nCorrectRhythm != 0) { if(pTickInfo->xTextShape.is()) @@ -176,7 +176,7 @@ void removeShapesAtWrongRythm( TickIter& rIter } } -class LabelIterator : private TickIter +class EquidistantLabelIterator : public EquidistantTickIter { //this Iterator iterates over existing text labels @@ -190,7 +190,7 @@ class LabelIterator : private TickIter //we iterate through all labels public: - LabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos + EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , const AxisLabelStaggering eAxisLabelStaggering , bool bInnerLine @@ -200,29 +200,29 @@ public: virtual TickInfo* nextInfo(); private: //methods - LabelIterator(); + EquidistantLabelIterator(); private: //member const AxisLabelStaggering m_eAxisLabelStaggering; bool m_bInnerLine; }; -LabelIterator::LabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos +EquidistantLabelIterator::EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , const AxisLabelStaggering eAxisLabelStaggering , bool bInnerLine , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : TickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth ) + : EquidistantTickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth ) , m_eAxisLabelStaggering(eAxisLabelStaggering) , m_bInnerLine(bInnerLine) { } -TickInfo* LabelIterator::firstInfo() +TickInfo* EquidistantLabelIterator::firstInfo() { - TickInfo* pTickInfo = TickIter::firstInfo(); + TickInfo* pTickInfo = EquidistantTickIter::firstInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ) - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); if(!pTickInfo) return NULL; if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine) @@ -232,7 +232,7 @@ TickInfo* LabelIterator::firstInfo() { //skip first label do - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); } if(!pTickInfo) @@ -240,12 +240,12 @@ TickInfo* LabelIterator::firstInfo() return pTickInfo; } -TickInfo* LabelIterator::nextInfo() +TickInfo* EquidistantLabelIterator::nextInfo() { TickInfo* pTickInfo = NULL; //get next label do - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); if( STAGGER_EVEN==m_eAxisLabelStaggering @@ -253,16 +253,16 @@ TickInfo* LabelIterator::nextInfo() { //skip one label do - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); } return pTickInfo; } -B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistanceTickToText ) +B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText ) { - //calculates the height or width of the first line of labels - //thus the second line of labels needs to be shifted for that distance + //calculates the height or width of a line of labels + //thus a following line of labels can be shifted for that distance B2DVector aRet(0,0); @@ -280,13 +280,14 @@ B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistan ; pTickInfo = rIter.nextInfo() ) { xShape2DText = pTickInfo->xTextShape; - DBG_ASSERT(xShape2DText.is(),"LabelIterator does not work correctly"); - - awt::Size aSize = xShape2DText->getSize(); - if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY())) - nDistance = ::std::max(nDistance,aSize.Width); - else - nDistance = ::std::max(nDistance,aSize.Height); + if( xShape2DText.is() ) + { + awt::Size aSize = xShape2DText->getSize(); + if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY())) + nDistance = ::std::max(nDistance,aSize.Width); + else + nDistance = ::std::max(nDistance,aSize.Height); + } } aRet = aStaggerDirection*nDistance; @@ -298,7 +299,7 @@ B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistan return aRet; } -void lcl_correctPositionForStaggering( LabelIterator& rIter, const B2DVector& rStaggerDistance ) +void lcl_shiftLables( TickIter& rIter, const B2DVector& rStaggerDistance ) { if(rStaggerDistance.getLength()==0.0) return; @@ -308,23 +309,24 @@ void lcl_correctPositionForStaggering( LabelIterator& rIter, const B2DVector& rS ; pTickInfo = rIter.nextInfo() ) { xShape2DText = pTickInfo->xTextShape; - DBG_ASSERT(xShape2DText.is(),"LabelIterator does not work correctly"); - - awt::Point aPos = xShape2DText->getPosition(); - aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX()); - aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY()); - xShape2DText->setPosition( aPos ); + if( xShape2DText.is() ) + { + awt::Point aPos = xShape2DText->getPosition(); + aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX()); + aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY()); + xShape2DText->setPosition( aPos ); + } } } -class MaxLabelTickIter : public TickIter +class MaxLabelEquidistantTickIter : public EquidistantTickIter { //iterate over first two and last two labels and the longest label public: - MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos + MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nLongestLabelIndex ); - virtual ~MaxLabelTickIter(); + virtual ~MaxLabelEquidistantTickIter(); virtual TickInfo* nextInfo(); @@ -332,10 +334,10 @@ private: sal_Int32 m_nLongestLabelIndex; }; -MaxLabelTickIter::MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos +MaxLabelEquidistantTickIter::MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nLongestLabelIndex ) - : TickIter( rTickInfos, rIncrement, 0//nMinDepth + : EquidistantTickIter( rTickInfos, rIncrement, 0//nMinDepth , 0//nMaxDepth ) , m_nLongestLabelIndex( nLongestLabelIndex ) @@ -353,11 +355,11 @@ MaxLabelTickIter::MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& if( m_nLongestLabelIndex+1==nMaxIndex ) m_nLongestLabelIndex = 0; } -MaxLabelTickIter::~MaxLabelTickIter() +MaxLabelEquidistantTickIter::~MaxLabelEquidistantTickIter() { } -TickInfo* MaxLabelTickIter::nextInfo() +TickInfo* MaxLabelEquidistantTickIter::nextInfo() { sal_Int32 nCurrentPos = getCurrentIndex(); sal_Int32 nMaxIndex = getMaxIndex(); @@ -374,11 +376,11 @@ TickInfo* MaxLabelTickIter::nextInfo() } } - return TickIter::nextInfo(); + return EquidistantTickIter::nextInfo(); } bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ) + , bool bIsHorizontalAxis ) { if( m_aTextLabels.getLength() > 100 ) return false; @@ -392,13 +394,11 @@ bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLab if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) ) return false; //break only for horizontal axis - if( pTickmarkHelper ) - return pTickmarkHelper->isHorizontalAxis(); - return false; + return bIsHorizontalAxis; } bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ) + , bool bIsHorizontalAxis, bool bIsVerticalAxis ) { if( rAxisLabelProperties.eStaggering != STAGGER_AUTO ) return false; @@ -410,28 +410,163 @@ bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& return false; //automatic staggering only for horizontal axis with horizontal text //or vertical axis with vertical text - if( pTickmarkHelper ) + if( bIsHorizontalAxis ) + return !rAxisLabelProperties.bStackCharacters; + if( bIsVerticalAxis ) + return rAxisLabelProperties.bStackCharacters; + return false; +} + +struct ComplexCategoryPlacement +{ + rtl::OUString Text; + sal_Int32 Count; + double TickValue; + + ComplexCategoryPlacement( const rtl::OUString& rText, sal_Int32 nCount, double fTickValue ) + : Text(rText), Count(nCount), TickValue(fTickValue) + {} +}; + +void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition ) +{ + //no minor tickmarks will be generated! + //order is: inner labels first , outer labels last (that is different to all other TickIter cases) + if(!bShiftedPosition) { - if( pTickmarkHelper->isHorizontalAxis() ) - return !rAxisLabelProperties.bStackCharacters; - if( pTickmarkHelper->isVerticalAxis() ) - return rAxisLabelProperties.bStackCharacters; + rAllTickInfos.clear(); + sal_Int32 nLevel=0; + sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); + for( ; nLevel<nLevelCount; nLevel++ ) + { + ::std::vector< TickInfo > aTickInfoVector; + std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) ); + sal_Int32 nCatIndex = 0; + std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin()); + std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end()); + for(;aIt!=aEnd;++aIt) + { + TickInfo aTickInfo; + ComplexCategory aCat(*aIt); + sal_Int32 nCount = aCat.Count; + if( nCatIndex + 0.5 + nCount >= m_aScale.Maximum ) + { + nCount = m_aScale.Maximum - 0.5 - nCatIndex; + if( nCount <= 0 ) + nCount = 1; + } + aTickInfo.fScaledTickValue = nCatIndex + 0.5 + nCount/2.0; + aTickInfo.nFactorForLimitedTextWidth = nCount; + aTickInfo.aText = aCat.Text; + aTickInfoVector.push_back(aTickInfo); + nCatIndex += nCount; + if( nCatIndex + 0.5 >= m_aScale.Maximum ) + break; + } + rAllTickInfos.push_back(aTickInfoVector); + } } - return false; + else //bShiftedPosition==true + { + rAllTickInfos.clear(); + sal_Int32 nLevel=0; + sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); + for( ; nLevel<nLevelCount; nLevel++ ) + { + ::std::vector< TickInfo > aTickInfoVector; + std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) ); + sal_Int32 nCatIndex = 0; + std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin()); + std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end()); + for(;aIt!=aEnd;++aIt) + { + TickInfo aTickInfo; + ComplexCategory aCat(*aIt); + aTickInfo.fScaledTickValue = nCatIndex + 0.5; + aTickInfoVector.push_back(aTickInfo); + nCatIndex += aCat.Count; + if( nCatIndex + 0.5 > m_aScale.Maximum ) + break; + } + //fill up with single ticks until maximum scale + while( nCatIndex + 0.5 < m_aScale.Maximum ) + { + TickInfo aTickInfo; + aTickInfo.fScaledTickValue = nCatIndex + 0.5; + aTickInfoVector.push_back(aTickInfo); + nCatIndex ++; + if( nLevel>0 ) + break; + } + //add an additional tick at the end + { + TickInfo aTickInfo; + aTickInfo.fScaledTickValue = m_aScale.Maximum; + aTickInfoVector.push_back(aTickInfo); + } + rAllTickInfos.push_back(aTickInfoVector); + } + } +} + +void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + createAllTickInfosFromComplexCategories( rAllTickInfos, false ); + else + VAxisBase::createAllTickInfos(rAllTickInfos); +} + +::std::auto_ptr< TickIter > VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel ) +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) ) + return ::std::auto_ptr< TickIter >( new PureTickIter( m_aAllTickInfos[nTextLevel] ) ); + } + else + { + if(nTextLevel==0) + return ::std::auto_ptr< TickIter >( new EquidistantTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ) ); + } + return ::std::auto_ptr< TickIter >(); +} +::std::auto_ptr< TickIter > VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel ) +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here + } + else + { + if(nTextLevel==0) + { + sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0; + return ::std::auto_ptr< TickIter >( new MaxLabelEquidistantTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex ) ); + } + } + return ::std::auto_ptr< TickIter >(); +} + +sal_Int32 VCartesianAxis::getTextLevelCount() const +{ + sal_Int32 nTextLevelCount = 1; + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); + return nTextLevelCount; } bool VCartesianAxis::createTextShapes( const Reference< drawing::XShapes >& xTarget , TickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ) + , TickmarkHelper_2D* pTickmarkHelper + , sal_Int32 nScreenDistanceBetweenTicks ) { //returns true if the text shapes have been created succesfully //otherwise false - in this case the AxisLabelProperties have changed //and contain new instructions for the next try for text shape creation - uno::Sequence< rtl::OUString >* pCategories = m_bUseTextLabels? &m_aTextLabels : 0; - Reference< XScaling > xInverseScaling( NULL ); if( m_aScale.Scaling.is() ) xInverseScaling = m_aScale.Scaling->getInverseScaling(); @@ -439,40 +574,44 @@ bool VCartesianAxis::createTextShapes( FixedNumberFormatter aFixedNumberFormatter( m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); - B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties ) ); - - TickInfo* pPreviousVisibleTickInfo = NULL; - TickInfo* pPREPreviousVisibleTickInfo = NULL; - TickInfo* pLastVisibleNeighbourTickInfo = NULL; + const bool bIsHorizontalAxis = pTickmarkHelper->isHorizontalAxis(); + const bool bIsVerticalAxis = pTickmarkHelper->isVerticalAxis(); bool bIsStaggered = rAxisLabelProperties.getIsStaggered(); - sal_Int32 nLimitedSpace = -1; - if( isBreakOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) ) + B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + sal_Int32 nLimitedSpaceForText = -1; + if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) ) { - nLimitedSpace = TickmarkHelper_2D::getTickScreenDistance( rTickIter ); + nLimitedSpaceForText = nScreenDistanceBetweenTicks; if( bIsStaggered ) - nLimitedSpace *= 2; + nLimitedSpaceForText *= 2; - if( nLimitedSpace > 0 ) + if( nLimitedSpaceForText > 0 ) { //reduce space for a small amount to have a visible distance between the labels: - sal_Int32 nReduce = (nLimitedSpace*5)/100; + sal_Int32 nReduce = (nLimitedSpaceForText*5)/100; if(!nReduce) nReduce = 1; - nLimitedSpace -= nReduce; + nLimitedSpaceForText -= nReduce; } - //maybe @todo in future: - //if the labeled tickmarks are not equidistant [this is not considered to be a relevant case so far] - //the limited space maybe needs to be calculated for each tickmark seperatly - //or the staggering could be ignored in that case } + std::vector< ComplexCategoryPlacement > aComplexCategoryPlacements; + uno::Sequence< rtl::OUString >* pCategories = 0; + if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories ) + pCategories = &m_aTextLabels; + + TickInfo* pPreviousVisibleTickInfo = NULL; + TickInfo* pPREPreviousVisibleTickInfo = NULL; + TickInfo* pLastVisibleNeighbourTickInfo = NULL; + //------------------------------------------------ //prepare properties for multipropertyset-interface of shape tNameSequence aPropNames; tAnySequence aPropValues; + bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY()); Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY ); PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false - , nLimitedSpace, fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY()) ); + , nLimitedSpaceForText, bLimitedHeight ); LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps , m_aAxisLabelProperties.m_aFontReferenceSize ); LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.m_aLabelAlignment ); @@ -481,6 +620,8 @@ bool VCartesianAxis::createTextShapes( sal_Int32 nColor = Color( COL_AUTO ).GetColor(); if(pColorAny) *pColorAny >>= nColor; + + uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight); //------------------------------------------------ sal_Int32 nTick = 0; @@ -491,7 +632,7 @@ bool VCartesianAxis::createTextShapes( pLastVisibleNeighbourTickInfo = bIsStaggered ? pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo; - //don't create labels which does not fit into the rythm + //don't create labels which does not fit into the rhythm if( nTick%rAxisLabelProperties.nRhythm != 0) continue; @@ -505,10 +646,11 @@ bool VCartesianAxis::createTextShapes( { if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape , rAxisLabelProperties.fRotationAngleDegree - , pTickInfo->aTickScreenPosition, pTickmarkHelper ) ) + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) { bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true; - if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) ) + if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) { bIsStaggered = true; rAxisLabelProperties.eStaggering = STAGGER_EVEN; @@ -516,7 +658,8 @@ bool VCartesianAxis::createTextShapes( if( !pLastVisibleNeighbourTickInfo || !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape , rAxisLabelProperties.fRotationAngleDegree - , pTickInfo->aTickScreenPosition, pTickmarkHelper ) ) + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) bOverlapAlsoAfterSwitchingOnAutoStaggering = false; } if( bOverlapAlsoAfterSwitchingOnAutoStaggering ) @@ -524,8 +667,7 @@ bool VCartesianAxis::createTextShapes( if( rAxisLabelProperties.bRhythmIsFix ) continue; rAxisLabelProperties.nRhythm++; - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeShapesAtWrongRythm( aRemoveIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); return false; } } @@ -543,11 +685,17 @@ bool VCartesianAxis::createTextShapes( if( nIndex>=0 && nIndex<pCategories->getLength() ) aLabel = (*pCategories)[nIndex]; } + else if( m_aAxisProperties.m_bComplexCategories ) + { + aLabel = pTickInfo->aText; + } else aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor ); if(pColorAny) *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor); + if(pLimitedSpaceAny) + *pLimitedSpaceAny = uno::makeAny(sal_Int32(nLimitedSpaceForText*pTickInfo->nFactorForLimitedTextWidth)); B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition ); aTickScreenPos2D += aTextToTickDistance; @@ -572,7 +720,7 @@ bool VCartesianAxis::createTextShapes( if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, m_aAxisLabelProperties.fRotationAngleDegree ) ) { bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true; - if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) ) + if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) { bIsStaggered = true; rAxisLabelProperties.eStaggering = STAGGER_EVEN; @@ -580,7 +728,8 @@ bool VCartesianAxis::createTextShapes( if( !pLastVisibleNeighbourTickInfo || !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape , rAxisLabelProperties.fRotationAngleDegree - , pTickInfo->aTickScreenPosition, pTickmarkHelper ) ) + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) bOverlapAlsoAfterSwitchingOnAutoStaggering = false; } if( bOverlapAlsoAfterSwitchingOnAutoStaggering ) @@ -592,8 +741,7 @@ bool VCartesianAxis::createTextShapes( continue; } rAxisLabelProperties.nRhythm++; - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeShapesAtWrongRythm( aRemoveIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); return false; } } @@ -1057,6 +1205,43 @@ TickmarkHelper_2D* VCartesianAxis::createTickmarkHelper2D() return new TickmarkHelper_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart ); } +void lcl_hideIdenticalScreenValues( TickIter& rTickIter ) +{ + TickInfo* pPreviousTickInfo = rTickIter.firstInfo(); + if(!pPreviousTickInfo) + return; + pPreviousTickInfo->bPaintIt = true; + for( TickInfo* pTickInfo = rTickIter.nextInfo(); pTickInfo; pTickInfo = rTickIter.nextInfo()) + { + pTickInfo->bPaintIt = + ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX()) + != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) ) + || + ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY()) + != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) ); + pPreviousTickInfo = pTickInfo; + } +} + +//'hide' tickmarks with identical screen values in aAllTickInfos +void VCartesianAxis::hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + sal_Int32 nCount = rTickInfos.size(); + for( sal_Int32 nN=0; nN<nCount; nN++ ) + { + PureTickIter aTickIter( rTickInfos[nN] ); + lcl_hideIdenticalScreenValues( aTickIter ); + } + } + else + { + EquidistantTickIter aTickIter( rTickInfos, m_aIncrement, 0, -1 ); + lcl_hideIdenticalScreenValues( aTickIter ); + } +} + sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount() { sal_Int32 nRet = 10; @@ -1092,15 +1277,31 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel if( !pTickmarkHelper2D ) return; - if( rAxisLabelProperties.getIsStaggered() ) + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) { - LabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement + sal_Int32 nTextLevelCount = getTextLevelCount(); + B2DVector aCummulatedLabelsDistance(0,0); + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) + { + ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); + if(apTickIter.get()) + { + if( nTextLevel>0 ) + lcl_shiftLables( *apTickIter.get(), aCummulatedLabelsDistance ); + aCummulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter.get() + , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ); + } + } + } + else if( rAxisLabelProperties.getIsStaggered() ) + { + EquidistantLabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement , rAxisLabelProperties.eStaggering, true, 0, 0 ); - LabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement + EquidistantLabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement , rAxisLabelProperties.eStaggering, false, 0, 0 ); - lcl_correctPositionForStaggering( aOuterIter - , lcl_getStaggerDistance( aInnerIter + lcl_shiftLables( aOuterIter + , lcl_getLabelsDistance( aInnerIter , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ) ); } } @@ -1124,18 +1325,34 @@ void SAL_CALL VCartesianAxis::createLabels() pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); //----------------------------------------- //'hide' tickmarks with identical screen values in aAllTickInfos - pTickmarkHelper2D->hideIdenticalScreenValues( m_aAllTickInfos ); + hideIdenticalScreenValues( m_aAllTickInfos ); - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeTextShapesFromTicks( aRemoveIter, m_xTextTarget ); + removeTextShapesFromTicks(); //create tick mark text shapes - TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - while( !createTextShapes( m_xTextTarget, aTickIter - , m_aAxisLabelProperties, pTickmarkHelper2D ) ) + sal_Int32 nTextLevelCount = getTextLevelCount(); + sal_Int32 nScreenDistanceBetweenTicks = -1; + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { - }; + ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); + if(apTickIter.get()) + { + if(nTextLevel==0) + { + nScreenDistanceBetweenTicks = TickmarkHelper_2D::getTickScreenDistance( *apTickIter.get() ); + if( nTextLevelCount>1 ) + nScreenDistanceBetweenTicks*=2; //the above used tick iter does contain also the sub ticks -> thus the given distance is only the half + } + AxisLabelProperties aCopy(m_aAxisLabelProperties); + aCopy.bRhythmIsFix = true; + aCopy.nRhythm = 1; + AxisLabelProperties& rAxisLabelProperties = nTextLevel==0 ? m_aAxisLabelProperties : aCopy; + while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickmarkHelper2D, nScreenDistanceBetweenTicks ) ) + { + }; + } + } doStaggeringOfLabels( m_aAxisLabelProperties, pTickmarkHelper2D ); } } @@ -1163,19 +1380,22 @@ void SAL_CALL VCartesianAxis::createMaximumLabels() //create tick mark text shapes //@todo: iterate through all tick depth wich should be labeled - sal_Int32 nLongestLabelIndex = m_bUseTextLabels - ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0; - MaxLabelTickIter aTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex ); AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); - if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D ) ) + if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D->isHorizontalAxis(), pTickmarkHelper2D->isVerticalAxis() ) ) aAxisLabelProperties.eStaggering = STAGGER_EVEN; aAxisLabelProperties.bOverlapAllowed = true; aAxisLabelProperties.bLineBreakAllowed = false; - while( !createTextShapes( m_xTextTarget, aTickIter - , aAxisLabelProperties, pTickmarkHelper2D ) ) + sal_Int32 nTextLevelCount = getTextLevelCount(); + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { - }; - + ::std::auto_ptr< TickIter > apTickIter = createMaximumLabelTickIterator( nTextLevel ); + if(apTickIter.get()) + { + while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickmarkHelper2D, -1 ) ) + { + }; + } + } doStaggeringOfLabels( aAxisLabelProperties, pTickmarkHelper2D ); } } @@ -1195,46 +1415,47 @@ void SAL_CALL VCartesianAxis::updatePositions() //update positions of all existing text shapes pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); - TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - - Reference< drawing::XShape > xShape2DText; - for( TickInfo* pTickInfo = aTickIter.firstInfo() - ; pTickInfo; pTickInfo = aTickIter.nextInfo() ) + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end(); + for( ; aDepthIter != aDepthEnd; aDepthIter++ ) { - if( !pTickInfo ) - continue; - - xShape2DText = pTickInfo->xTextShape; - if( xShape2DText.is() ) + ::std::vector< TickInfo >::iterator aTickIter = aDepthIter->begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = aDepthIter->end(); + for( ; aTickIter != aTickEnd; aTickIter++ ) { - B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ); - B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition ); - aTickScreenPos2D += aTextToTickDistance; - awt::Point aAnchorScreenPosition2D( - static_cast<sal_Int32>(aTickScreenPos2D.getX()) - ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); - - // #i78696# use mathematically correct rotation now - const double fRotationAnglePi(m_aAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0)); - uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi); - - //set new position - uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY ); - if( xProp.is() ) + TickInfo& rTickInfo = (*aTickIter); + Reference< drawing::XShape > xShape2DText( rTickInfo.xTextShape ); + if( xShape2DText.is() ) { - try + B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + B2DVector aTickScreenPos2D( rTickInfo.aTickScreenPosition ); + aTickScreenPos2D += aTextToTickDistance; + awt::Point aAnchorScreenPosition2D( + static_cast<sal_Int32>(aTickScreenPos2D.getX()) + ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); + + // #i78696# use mathematically correct rotation now + const double fRotationAnglePi(m_aAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0)); + uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi); + + //set new position + uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY ); + if( xProp.is() ) { - xProp->setPropertyValue( C2U( "Transformation" ), aATransformation ); + try + { + xProp->setPropertyValue( C2U( "Transformation" ), aATransformation ); + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } } - catch( uno::Exception& e ) - { - ASSERT_EXCEPTION( e ); - } - } - //correctPositionForRotation - LabelPositionHelper::correctPositionForRotation( xShape2DText - , m_aAxisProperties.m_aLabelAlignment, m_aAxisLabelProperties.fRotationAngleDegree, false ); + //correctPositionForRotation + LabelPositionHelper::correctPositionForRotation( xShape2DText + , m_aAxisProperties.m_aLabelAlignment, m_aAxisLabelProperties.fRotationAngleDegree, false ); + } } } @@ -1242,6 +1463,37 @@ void SAL_CALL VCartesianAxis::updatePositions() } } +void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels ) +{ + sal_Int32 nPointCount = rTickInfos.size(); + drawing::PointSequenceSequence aPoints(2*nPointCount); + + ::std::vector< TickInfo >::const_iterator aTickIter = rTickInfos.begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = rTickInfos.end(); + sal_Int32 nN = 0; + for( ; aTickIter != aTickEnd; aTickIter++ ) + { + if( !(*aTickIter).bPaintIt ) + continue; + + bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS ); + double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign; + if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END ) + fInnerDirectionSign *= -1.0; + bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels; + //add ticks at labels: + rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue + , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels ); + //add ticks at axis (without lables): + if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) + rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue + , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels ); + } + aPoints.realloc(nN); + m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints + , &rTickmarkProperties.aLineProperties ); +} + void SAL_CALL VCartesianAxis::createShapes() { if( !prepareShapeCreation() ) @@ -1253,55 +1505,64 @@ void SAL_CALL VCartesianAxis::createShapes() return; //----------------------------------------- - //create tick mark line shapes + //create line shapes if(2==m_nDimension) { - ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos; - if( m_aIncrement.ShiftedPosition ) - { - pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos ); - pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos ); - pTickmarkHelper2D->hideIdenticalScreenValues( aAllShiftedTickInfos ); - } - ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aIncrement.ShiftedPosition ? aAllShiftedTickInfos : m_aAllTickInfos; - - ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); - const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); - - if(aDepthIter == aDepthEnd)//no tickmarks at all - return; - - sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size(); - for( sal_Int32 nDepth=0 - ; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount - ; aDepthIter++, nDepth++ ) + //----------------------------------------- + //create extra long ticks to separate complex categories (create them only there where the labels are) + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) { - const TickmarkProperties& rTickmarkProperties = m_aAxisProperties.m_aTickmarkPropertiesList[nDepth]; - - sal_Int32 nPointCount = (*aDepthIter).size(); - drawing::PointSequenceSequence aPoints(2*nPointCount); + ::std::vector< ::std::vector< TickInfo > > aComplexTickInfos; + createAllTickInfosFromComplexCategories( aComplexTickInfos, true ); + pTickmarkHelper2D->updateScreenValues( aComplexTickInfos ); + hideIdenticalScreenValues( aComplexTickInfos ); + + ::std::vector<TickmarkProperties> aTickmarkPropertiesList; + static bool bIncludeSpaceBetweenTickAndText = false; + sal_Int32 nOffset = pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength(); + sal_Int32 nTextLevelCount = getTextLevelCount(); + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) + { + ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); + if( apTickIter.get() ) + { + B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false ) ) ); + sal_Int32 nCurrentLength = aLabelsDistance.getLength(); + aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0, nTextLevel ) ); + nOffset += nCurrentLength; + } + } - ::std::vector< TickInfo >::const_iterator aTickIter = (*aDepthIter).begin(); - const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); - sal_Int32 nN = 0; - for( ; aTickIter != aTickEnd; aTickIter++ ) + sal_Int32 nTickmarkPropertiesCount = aTickmarkPropertiesList.size(); + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = aComplexTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = aComplexTickInfos.end(); + for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; aDepthIter++, nDepth++ ) { - if( !(*aTickIter).bPaintIt ) + if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks) continue; - - bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS ); - double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign; - if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END ) - fInnerDirectionSign *= -1.0; - apTickmarkHelper2D->addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue - , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels ); - if( m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) - apTickmarkHelper2D->addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue - , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels ); + createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, true /*bOnlyAtLabels*/ ); + } + } + //----------------------------------------- + //create normal ticks for major and minor intervals + { + ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos; + if( m_aIncrement.ShiftedPosition || ( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) ) + { + pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos ); + pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos ); + hideIdenticalScreenValues( aAllShiftedTickInfos ); } - aPoints.realloc(nN); - m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints - , &rTickmarkProperties.aLineProperties ); + ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aIncrement.ShiftedPosition ? aAllShiftedTickInfos : m_aAllTickInfos; + + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); + if(aDepthIter == aDepthEnd)//no tickmarks at all + return; + + sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size(); + for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; aDepthIter++, nDepth++ ) + createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, false /*bOnlyAtLabels*/ ); } //----------------------------------------- //create axis main lines diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx index f23560eaad9c..4fbcd2409196 100644 --- a/chart2/source/view/axes/VCartesianAxis.hxx +++ b/chart2/source/view/axes/VCartesianAxis.hxx @@ -30,6 +30,8 @@ #include "VAxisBase.hxx" #include <basegfx/vector/b2dvector.hxx> +#include <memory> + //............................................................................. namespace chart { @@ -69,6 +71,12 @@ public: virtual void SAL_CALL createShapes(); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); + virtual void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ); + void createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition ); + + ::std::auto_ptr< TickIter > createLabelTickIterator( sal_Int32 nTextLevel ); + ::std::auto_ptr< TickIter > createMaximumLabelTickIterator( sal_Int32 nTextLevel ); + sal_Int32 getTextLevelCount() const; //------------------------------------------------------------------------- virtual TickmarkHelper* createTickmarkHelper(); @@ -114,16 +122,19 @@ protected: //methods ::com::sun::star::drawing::XShapes >& xTarget , TickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ); + , TickmarkHelper_2D* pTickmarkHelper + , sal_Int32 nScreenDistanceBetweenTicks ); + + void createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels ); TickmarkHelper_2D* createTickmarkHelper2D(); + void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const; void doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties , TickmarkHelper_2D* pTickmarkHelper2D ); bool isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper); - bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ); + , bool bIsHorizontalAxis, bool bIsVerticalAxis ); + bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis ); ::basegfx::B2DVector getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const; ScreenPosAndLogicPos getScreenPosAndLogicPos( double fLogicX, double fLogicY, double fLogicZ ) const; diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx index 01358b3a932f..a196397e0e9f 100644 --- a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx @@ -153,7 +153,8 @@ void VCartesianCoordinateSystem::createVAxisList( if( aCrossingScale.AxisType == AxisType::CATEGORY ) { aAxisProperties.m_bCrossingAxisIsCategoryAxes = true; - aAxisProperties.m_bAxisBetweenCategories = ChartTypeHelper::shiftTicksAtXAxisPerDefault( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ) ); + aAxisProperties.m_bAxisBetweenCategories = ChartTypeHelper::shiftTicksAtXAxisPerDefault( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ) ) + || ( aAxisProperties.m_pExplicitCategoriesProvider && aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() ); } } @@ -168,6 +169,13 @@ void VCartesianCoordinateSystem::createVAxisList( aAxisProperties.init(true); if(aAxisProperties.m_bDisplayLabels) aAxisProperties.m_nNumberFormatKey = this->getNumberFormatKeyForAxis( xAxis, xNumberFormatsSupplier ); + + if( nDimensionIndex == 0 && aAxisProperties.m_nAxisType == AxisType::CATEGORY + && aAxisProperties.m_pExplicitCategoriesProvider ) + { + if( aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() ) + aAxisProperties.m_bComplexCategories = true; + } //------------------- ::boost::shared_ptr< VAxisBase > apVAxis( new VCartesianAxis(aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) ); tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); diff --git a/chart2/source/view/axes/VCoordinateSystem.cxx b/chart2/source/view/axes/VCoordinateSystem.cxx index 22ec914fa938..bc908acdf85a 100644 --- a/chart2/source/view/axes/VCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCoordinateSystem.cxx @@ -94,7 +94,7 @@ VCoordinateSystem::VCoordinateSystem( const Reference< XCoordinateSystem >& xCoo , m_aMergedMinimumAndMaximumSupplier() , m_aExplicitScales(3) , m_aExplicitIncrements(3) - , m_aExplicitCategoriesProvider( new ExplicitCategoriesProvider( m_xCooSysModel ) ) + , m_apExplicitCategoriesProvider(NULL) { if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 ) { @@ -261,10 +261,14 @@ void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex rAxisIndex = 0; } +void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider /*takes ownership*/ ) +{ + m_apExplicitCategoriesProvider = ::std::auto_ptr< ExplicitCategoriesProvider >(pExplicitCategoriesProvider); +} -Reference< data::XTextualDataSequence > VCoordinateSystem::getExplicitCategoriesProvider() +ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider() { - return m_aExplicitCategoriesProvider.getRef(); + return m_apExplicitCategoriesProvider.get(); } Sequence< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const diff --git a/chart2/source/view/axes/VPolarAngleAxis.cxx b/chart2/source/view/axes/VPolarAngleAxis.cxx index 7a273e22f128..865a7848aa9a 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.cxx +++ b/chart2/source/view/axes/VPolarAngleAxis.cxx @@ -62,7 +62,7 @@ VPolarAngleAxis::~VPolarAngleAxis() bool VPolarAngleAxis::createTextShapes_ForAngleAxis( const uno::Reference< drawing::XShapes >& xTarget - , TickIter& rTickIter + , EquidistantTickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties , double fLogicRadius , double fLogicZ ) @@ -99,7 +99,7 @@ bool VPolarAngleAxis::createTextShapes_ForAngleAxis( ; pTickInfo ; pTickInfo = rTickIter.nextInfo(), nTick++ ) { - //don't create labels which does not fit into the rythm + //don't create labels which does not fit into the rhythm if( nTick%rAxisLabelProperties.nRhythm != 0) continue; @@ -189,11 +189,10 @@ void SAL_CALL VPolarAngleAxis::createLabels() //create tick mark text shapes //@todo: iterate through all tick depth wich should be labeled - TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); + EquidistantTickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); this->updateUnscaledValuesAtTicks( aTickIter ); - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeTextShapesFromTicks( aRemoveIter, m_xTextTarget ); + removeTextShapesFromTicks(); AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); aAxisLabelProperties.bOverlapAllowed = true; diff --git a/chart2/source/view/axes/VPolarAngleAxis.hxx b/chart2/source/view/axes/VPolarAngleAxis.hxx index 9a27c94e3095..c03cf533e22c 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.hxx +++ b/chart2/source/view/axes/VPolarAngleAxis.hxx @@ -55,7 +55,7 @@ public: private: //methods bool createTextShapes_ForAngleAxis( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget - , TickIter& rTickIter + , EquidistantTickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties , double fLogicRadius, double fLogicZ ); }; diff --git a/chart2/source/view/axes/VPolarGrid.cxx b/chart2/source/view/axes/VPolarGrid.cxx index b9099906deb0..0bd98b642acb 100644 --- a/chart2/source/view/axes/VPolarGrid.cxx +++ b/chart2/source/view/axes/VPolarGrid.cxx @@ -90,7 +90,7 @@ void VPolarGrid::createLinePointSequence_ForAngleAxis( xInverseScaling = rScale.Scaling->getInverseScaling(); sal_Int32 nTick = 0; - TickIter aIter( rAllTickInfos, rIncrement, 0, 0 ); + EquidistantTickIter aIter( rAllTickInfos, rIncrement, 0, 0 ); for( TickInfo* pTickInfo = aIter.firstInfo() ; pTickInfo ; pTickInfo = aIter.nextInfo(), nTick++ ) diff --git a/chart2/source/view/axes/VPolarRadiusAxis.cxx b/chart2/source/view/axes/VPolarRadiusAxis.cxx index 7970d051e7b1..2206d4d8f559 100644 --- a/chart2/source/view/axes/VPolarRadiusAxis.cxx +++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx @@ -49,7 +49,6 @@ VPolarRadiusAxis::VPolarRadiusAxis( const AxisProperties& rAxisProperties { m_aAxisProperties.m_fLabelDirectionSign=0.0; m_aAxisProperties.m_fInnerDirectionSign=0.0; - m_aAxisProperties.m_bLabelsOutside=true; m_aAxisProperties.m_bIsMainAxis=false; m_aAxisProperties.m_aLabelAlignment=LABEL_ALIGN_RIGHT; m_aAxisProperties.init(); @@ -156,7 +155,7 @@ void SAL_CALL VPolarRadiusAxis::createShapes() AxisProperties aAxisProperties(m_aAxisProperties); sal_Int32 nTick = 0; - TickIter aIter( aAngleTickInfos, rAngleIncrement, 0, 0 ); + EquidistantTickIter aIter( aAngleTickInfos, rAngleIncrement, 0, 0 ); for( TickInfo* pTickInfo = aIter.firstInfo() ; pTickInfo; pTickInfo = aIter.nextInfo(), nTick++ ) { diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx index 1774d9828e91..67914f47bac0 100644 --- a/chart2/source/view/charttypes/AreaChart.cxx +++ b/chart2/source/view/charttypes/AreaChart.cxx @@ -72,7 +72,6 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel , bool bNoArea , PlottingPositionHelper* pPlottingPositionHelper , bool bConnectLastToFirstPoint - , bool bAddOneToXMax , bool bExpandIfValuesCloseToBorder , sal_Int32 nKeepAspectRatio , const drawing::Direction3D& rAspectRatio @@ -84,7 +83,6 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel , m_bSymbol( ChartTypeHelper::isSupportingSymbolProperties(xChartTypeModel,nDimensionCount) ) , m_bIsPolarCooSys( bConnectLastToFirstPoint ) , m_bConnectLastToFirstPoint( bConnectLastToFirstPoint ) - , m_bAddOneToXMax(bAddOneToXMax) , m_bExpandIfValuesCloseToBorder( bExpandIfValuesCloseToBorder ) , m_nKeepAspectRatio(nKeepAspectRatio) , m_aGivenAspectRatio(rAspectRatio) @@ -123,14 +121,17 @@ AreaChart::~AreaChart() delete m_pMainPosHelper; } +double AreaChart::getMinimumX() +{ + if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling + return 1.0;//first category (index 0) matches with real number 1.0 + return VSeriesPlotter::getMinimumX(); +} + double AreaChart::getMaximumX() { - if( m_bAddOneToXMax ) - { - //return category count - sal_Int32 nPointCount = getPointCount(); - return nPointCount+1; - } + if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling + return getPointCount()+1; return VSeriesPlotter::getMaximumX(); } diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx index afe9908b3bfe..6924509a62a1 100644 --- a/chart2/source/view/charttypes/AreaChart.hxx +++ b/chart2/source/view/charttypes/AreaChart.hxx @@ -49,7 +49,6 @@ public: , bool bCategoryXAxis, bool bNoArea=false , PlottingPositionHelper* pPlottingPositionHelper=NULL //takes owner ship , bool bConnectLastToFirstPoint=false - , bool bAddOneToXMax=false , bool bExpandIfValuesCloseToBorder=true , sal_Int32 nKeepAspectRatio=-1 //0->no 1->yes other value->automatic , const ::com::sun::star::drawing::Direction3D& rAspectRatio=::com::sun::star::drawing::Direction3D(1,1,1)//only taken into account if nKeepAspectRatio==1 @@ -76,6 +75,7 @@ public: //------------------------------------------------------------------------- // MinimumAndMaximumSupplier //------------------------------------------------------------------------- + virtual double getMinimumX(); virtual double getMaximumX(); virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ); virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex ); @@ -109,7 +109,6 @@ private: //member bool m_bSymbol; bool m_bIsPolarCooSys;//used e.g. for net chart (the data labels need to be placed different) bool m_bConnectLastToFirstPoint;//used e.g. for net chart - bool m_bAddOneToXMax;//used e.g. for net chart (the angle axis needs a different autoscaling) bool m_bExpandIfValuesCloseToBorder; // e.g. false for net charts sal_Int32 m_nKeepAspectRatio; //0->no 1->yes other value->automatic diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index a6ab71df15f5..ccba1fdc4106 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -156,7 +156,7 @@ VSeriesPlotter::VSeriesPlotter( const uno::Reference<XChartType>& xChartTypeMode , m_aZSlots() , m_bCategoryXAxis(bCategoryXAxis) , m_xColorScheme() - , m_xExplicitCategoriesProvider() + , m_pExplicitCategoriesProvider(0) , m_bPointsWereSkipped(false) { DBG_ASSERT(m_xChartTypeModel.is(),"no XChartType available in view, fallback to default values may be wrong"); @@ -477,9 +477,9 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re { if(pLabel->ShowCategoryName) { - if( m_xExplicitCategoriesProvider.is() ) + if( m_pExplicitCategoriesProvider ) { - Sequence< OUString > aCategories( m_xExplicitCategoriesProvider->getTextualData() ); + Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() ); if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() ) { aText.append( aCategories[nPointIndex] ); @@ -1127,7 +1127,12 @@ void VSeriesPlotter::setMappedProperties( double VSeriesPlotter::getMinimumX() { if( m_bCategoryXAxis ) - return 1.0;//first category (index 0) matches with real number 1.0 + { + double fRet = 1.0;//first category (index 0) matches with real number 1.0 + if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) + fRet -= 0.5; + return fRet; + } double fMinimum, fMaximum; this->getMinimumAndMaximiumX( fMinimum, fMaximum ); @@ -1138,8 +1143,10 @@ double VSeriesPlotter::getMaximumX() if( m_bCategoryXAxis ) { //return category count - sal_Int32 nPointCount = getPointCount(); - return nPointCount;//first category (index 0) matches with real number 1.0 + double fRet = getPointCount();//first category (index 0) matches with real number 1.0 + if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) + fRet += 0.5; + return fRet; } double fMinimum, fMaximum; @@ -1356,9 +1363,9 @@ void VSeriesPlotter::setColorScheme( const uno::Reference< XColorScheme >& xColo m_xColorScheme = xColorScheme; } -void VSeriesPlotter::setExplicitCategoriesProvider( const uno::Reference< data::XTextualDataSequence >& xExplicitCategoriesProvider ) +void VSeriesPlotter::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider ) { - m_xExplicitCategoriesProvider = xExplicitCategoriesProvider; + m_pExplicitCategoriesProvider = pExplicitCategoriesProvider; } sal_Int32 VDataSeriesGroup::getPointCount() const @@ -1929,8 +1936,8 @@ std::vector< ViewLegendEntry > SAL_CALL VSeriesPlotter::createLegendEntriesForSe if( bVaryColorsByPoint ) { Sequence< OUString > aCategoryNames; - if( m_xExplicitCategoriesProvider.is() ) - aCategoryNames = m_xExplicitCategoriesProvider->getTextualData(); + if( m_pExplicitCategoriesProvider ) + aCategoryNames = m_pExplicitCategoriesProvider->getSimpleCategories(); for( sal_Int32 nIdx=0; nIdx<aCategoryNames.getLength(); ++nIdx ) { @@ -2074,9 +2081,9 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) pRet = new PieChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) - pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true,new PolarPlottingPositionHelper(),true,true,false,1,drawing::Direction3D(1,1,1) ); + pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) ); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) - pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,false,new PolarPlottingPositionHelper(),true,true,false,1,drawing::Direction3D(1,1,1) ); + pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,false,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) ); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) pRet = new CandleStickChart(xChartTypeModel,nDimensionCount); else diff --git a/chart2/source/view/inc/PropertyMapper.hxx b/chart2/source/view/inc/PropertyMapper.hxx index fbdebb4fa1a2..c0871b94f835 100644 --- a/chart2/source/view/inc/PropertyMapper.hxx +++ b/chart2/source/view/inc/PropertyMapper.hxx @@ -88,6 +88,11 @@ public: , const tNameSequence& rPropNames , const rtl::OUString& rPropName ); + static ::com::sun::star::uno::Any* + getValuePointerForLimitedSpace( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , bool bLimitedHeight ); + static void setMultiProperties( const tNameSequence& rNames , const tAnySequence& rValues diff --git a/chart2/source/view/inc/VCoordinateSystem.hxx b/chart2/source/view/inc/VCoordinateSystem.hxx index 4a3d52203545..e884af865d6e 100644 --- a/chart2/source/view/inc/VCoordinateSystem.hxx +++ b/chart2/source/view/inc/VCoordinateSystem.hxx @@ -30,11 +30,11 @@ #include "MinimumAndMaximumSupplier.hxx" #include "ScaleAutomatism.hxx" #include "ThreeDHelper.hxx" +#include "ExplicitCategoriesProvider.hxx" #include <com/sun/star/chart2/ExplicitIncrementData.hpp> #include <com/sun/star/chart2/ExplicitScaleData.hpp> #include <com/sun/star/chart2/XCoordinateSystem.hpp> -#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> #include "comphelper/implementationreference.hxx" #include <com/sun/star/awt/Rectangle.hpp> #include <com/sun/star/drawing/HomogenMatrix.hpp> @@ -51,8 +51,6 @@ namespace chart { //............................................................................. -class ExplicitCategoriesProvider; - //----------------------------------------------------------------------------- /** */ @@ -87,7 +85,9 @@ public: ::com::sun::star::chart2::ExplicitScaleData getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const; ::com::sun::star::chart2::ExplicitIncrementData getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const; - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XTextualDataSequence > getExplicitCategoriesProvider(); + + void setExplicitCategoriesProvider( ExplicitCategoriesProvider* /*takes ownership*/ ); + ExplicitCategoriesProvider* getExplicitCategoriesProvider(); // returns a coplete scale set for a given dimension and index; for example if nDimensionIndex==1 and nAxisIndex==2 you get returned the secondary x axis, main y axis and main z axis ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData > getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const; @@ -203,8 +203,7 @@ private: tFullExplicitScaleMap m_aSecondaryExplicitScales; tFullExplicitIncrementMap m_aSecondaryExplicitIncrements; - comphelper::ImplementationReference< ExplicitCategoriesProvider, ::com::sun::star::chart2::data::XTextualDataSequence > - m_aExplicitCategoriesProvider; + ::std::auto_ptr< ExplicitCategoriesProvider > m_apExplicitCategoriesProvider; }; //............................................................................. diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx index 95093db1bfaf..02c1f3b044e9 100644 --- a/chart2/source/view/inc/VSeriesPlotter.hxx +++ b/chart2/source/view/inc/VSeriesPlotter.hxx @@ -32,9 +32,9 @@ #include "LabelAlignment.hxx" #include "MinimumAndMaximumSupplier.hxx" #include "LegendEntryProvider.hxx" +#include "ExplicitCategoriesProvider.hxx" #include <com/sun/star/chart2/LegendSymbolStyle.hpp> #include <com/sun/star/chart2/XChartType.hpp> -#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> #include <com/sun/star/drawing/Direction3D.hpp> @@ -275,8 +275,7 @@ public: void setColorScheme( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XColorScheme >& xColorScheme ); - void setExplicitCategoriesProvider( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XTextualDataSequence >& xExplicitCategoriesProvider ); + void setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider ); //get series names for the z axis labels ::com::sun::star::uno::Sequence< rtl::OUString > getSeriesNames() const; @@ -431,8 +430,7 @@ protected: //member ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XColorScheme > m_xColorScheme; - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XTextualDataSequence > m_xExplicitCategoriesProvider; + ExplicitCategoriesProvider* m_pExplicitCategoriesProvider; //better performance for big data ::com::sun::star::uno::Sequence< sal_Int32 > m_aCoordinateSystemResolution; diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index 0e954b7c7a85..da8798fe31b6 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -424,6 +424,8 @@ VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysL rtl::OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, xChartModel ) ); pVCooSys->setParticle(aCooSysParticle); + pVCooSys->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys,xChartModel) ); + rVCooSysList.push_back( pVCooSys ); } } @@ -574,13 +576,13 @@ private: std::vector< VCoordinateSystem* >& m_rVCooSysList; ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList; sal_Int32 m_nMaxAxisIndex; - bool m_bShiftXAxisTicks; + bool m_bChartTypeUsesShiftedXAxisTicksPerDefault; }; SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList ) : m_rVCooSysList( rVCooSysList ) , m_nMaxAxisIndex(0) - , m_bShiftXAxisTicks(false) + , m_bChartTypeUsesShiftedXAxisTicksPerDefault(false) { } @@ -675,7 +677,7 @@ void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter( uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); if(nT==0) - m_bShiftXAxisTicks = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType ); + m_bChartTypeUsesShiftedXAxisTicksPerDefault = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType ); VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount ); if( !pPlotter ) @@ -929,7 +931,9 @@ void SeriesPlotterContainer::doAutoScaling( const uno::Reference< frame::XModel for( nC=0; nC < aVCooSysList_X.size(); nC++) { - if( m_bShiftXAxisTicks ) + ExplicitCategoriesProvider* pExplicitCategoriesProvider = aVCooSysList_X[nC]->getExplicitCategoriesProvider(); + + if( m_bChartTypeUsesShiftedXAxisTicksPerDefault || (aExplicitScale.AxisType==AxisType::CATEGORY && pExplicitCategoriesProvider && pExplicitCategoriesProvider->hasComplexCategories() ) ) aExplicitIncrement.ShiftedPosition = true; aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement ); } @@ -1775,7 +1779,8 @@ sal_Int32 lcl_getExplicitNumberFormatKeyForAxis( if(!aLabeledSeq[nLSeqIdx].is()) continue; Reference< data::XDataSequence > xSeq( aLabeledSeq[nLSeqIdx]->getValues()); - OSL_ASSERT( xSeq.is()); + if(!xSeq.is()) + continue; Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY ); ::rtl::OUString aRole; bool bTakeIntoAccount = diff --git a/chart2/source/view/main/PropertyMapper.cxx b/chart2/source/view/main/PropertyMapper.cxx index 68368808f66a..6e53ce22aff7 100644 --- a/chart2/source/view/main/PropertyMapper.cxx +++ b/chart2/source/view/main/PropertyMapper.cxx @@ -165,6 +165,14 @@ uno::Any* PropertyMapper::getValuePointer( tAnySequence& rPropValues return NULL; } +uno::Any* PropertyMapper::getValuePointerForLimitedSpace( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , bool bLimitedHeight) +{ + return PropertyMapper::getValuePointer( rPropValues, rPropNames + , bLimitedHeight ? C2U("TextMaximumFrameHeight") : C2U("TextMaximumFrameWidth") ); +} + /* //set some properties from service style::CharacterProperties: //-------- tabpage: Zeichen ----------- diff --git a/configmgr/source/xcdparser.cxx b/configmgr/source/xcdparser.cxx index 2f860f805487..8306c692c30f 100644 --- a/configmgr/source/xcdparser.cxx +++ b/configmgr/source/xcdparser.cxx @@ -28,7 +28,7 @@ #include "precompiled_configmgr.hxx" #include "sal/config.h" -#include <cstddef> +#include <climits> #include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/RuntimeException.hpp" diff --git a/default_images/chart2/res/dataeditor_icon07.png b/default_images/chart2/res/dataeditor_icon07.png Binary files differindex 759d616ff874..09434542a07c 100644 --- a/default_images/chart2/res/dataeditor_icon07.png +++ b/default_images/chart2/res/dataeditor_icon07.png diff --git a/default_images/chart2/res/dataeditor_icon_h07.png b/default_images/chart2/res/dataeditor_icon_h07.png Binary files differindex f3e4bfbf5dea..b079ecc9456c 100644 --- a/default_images/chart2/res/dataeditor_icon_h07.png +++ b/default_images/chart2/res/dataeditor_icon_h07.png diff --git a/embedserv/source/embed/intercept.cxx b/embedserv/source/embed/intercept.cxx index fc33bfc9f371..905642a49b70 100644 --- a/embedserv/source/embed/intercept.cxx +++ b/embedserv/source/embed/intercept.cxx @@ -174,7 +174,7 @@ Interceptor::~Interceptor() void Interceptor::DisconnectDocHolder() { osl::MutexGuard aGuard(m_aMutex); - m_xDocHLocker = uno::Reference< uno::XInterface >(); + m_xDocHLocker.clear(); m_pDocH = NULL; m_xOleAccess = NULL; } diff --git a/instsetoo_native/util/pack.lst b/instsetoo_native/util/pack.lst index 9f5fbfd93246..c19039118909 100755 --- a/instsetoo_native/util/pack.lst +++ b/instsetoo_native/util/pack.lst @@ -19,6 +19,6 @@ OpenOffice_Dev_SDK unxlngi6.pro,unxmacxi.pro,unxsoli4.pro,unxsols4.pro,wntmsci1 #URE unxlngi6.pro,unxsoli4.pro,unxsols4.pro,wntmsci12.pro,unxlngi6,unxsoli4,unxsols4,wntmsci12 en-US ure OpenOfficeLanguagepack unxlngi6.pro,unxsoli4.pro,unxsols4.pro,wntmsci12.pro,unxlngx6.pro,unxmacxi.pro de ooolanguagepack OpenOfficeLanguagepack unxlngi6,unxsoli4,unxsols4,wntmsci12,unxmacxi de ooolanguagepack -OpenOfficeDevLanguagepack unxlngi6.pro,unxsoli4.pro,unxsols4.pro,wntmsci12.pro,unxlngx6.pro,unxmacxi.pro de|fr|ja|ar ooodevlanguagepack +OpenOfficeDevLanguagepack unxlngi6.pro,unxsoli4.pro,unxsols4.pro,wntmsci12.pro,unxlngx6.pro,unxmacxi.pro de|fr|ja|ar|ru ooodevlanguagepack #BrOfficeLanguagepack unxlngi6.pro,unxsoli4.pro,unxsols4.pro,wntmsci12.pro,unxlngx6.pro pt-BR broolanguagepack diff --git a/moz/makefile.mk b/moz/makefile.mk index 96ea794e8532..2eeda8c08928 100644 --- a/moz/makefile.mk +++ b/moz/makefile.mk @@ -84,6 +84,7 @@ PATCH_FILES = \ seamonkey-source-$(MOZILLA_VERSION).patch \ patches/dtoa.patch \ patches/respect_disable_pango.patch \ + patches/arm_build_fix.patch # This file is needed for the W32 build when BUILD_MOZAB is set # (currently only vc8/vs2005 is supported when BUILD_MOZAB is set) diff --git a/moz/patches/arm_build_fix.patch b/moz/patches/arm_build_fix.patch new file mode 100644 index 000000000000..79368e5fe6db --- /dev/null +++ b/moz/patches/arm_build_fix.patch @@ -0,0 +1,189 @@ +--- misc/mozilla/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp 2010-01-29 08:39:01.000000000 +0000 ++++ misc/build/mozilla/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp 2010-01-29 08:41:01.000000000 +0000 +@@ -44,8 +44,21 @@ + #error "This code is for Linux ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour." + #endif + ++#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) ++/* This tells gcc3.4+ not to optimize away symbols. ++ * * @see http://gcc.gnu.org/gcc-3.4/changes.html ++ * */ ++#define DONT_DROP_OR_WARN __attribute__((used)) ++#else ++/* This tells older gccs not to warn about unused vairables. ++ * * @see http://docs.freebsd.org/info/gcc/gcc.info.Variable_Attributes.html ++ * */ ++#define DONT_DROP_OR_WARN __attribute__((unused)) ++#endif ++ + /* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */ +-static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args) asm("_PrepareAndDispatch"); ++static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args) asm("_PrepareAndDispatch") ++DONT_DROP_OR_WARN; + + static nsresult + PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args) +--- misc/mozilla/security/nss/cmd/shlibsign/Makefile 2010-02-05 13:13:56.000000000 +0000 ++++ misc/build/mozilla/security/nss/cmd/shlibsign/Makefile 2010-02-05 13:14:16.000000000 +0000 +@@ -124,5 +124,5 @@ + endif + endif + +-libs install :: $(CHECKLOC) ++libs install :: + +--- misc/mozilla/security/manager/Makefile.in 2010-02-05 13:27:25.000000000 +0000 ++++ misc/build/mozilla/security/manager/Makefile.in 2010-02-05 13:28:00.000000000 +0000 +@@ -53,7 +53,6 @@ + SMIME3_LIB \ + SSL3_LIB \ + SOFTOKEN3_LIB \ +- SOFTOKEN3_CHK \ + LOADABLE_ROOT_MODULE \ + HAVE_FREEBL_LIBS \ + HAVE_FREEBL_LIBS_32 \ +@@ -68,7 +67,6 @@ + SMIME3_LIB = $(DLL_PREFIX)smime3$(DLL_SUFFIX) + SSL3_LIB = $(DLL_PREFIX)ssl3$(DLL_SUFFIX) + SOFTOKEN3_LIB = $(DLL_PREFIX)softokn3$(DLL_SUFFIX) +-SOFTOKEN3_CHK = $(DLL_PREFIX)softokn3.chk + + # Default + HAVE_FREEBL_LIBS = 1 +@@ -99,23 +97,17 @@ + + ifdef HAVE_FREEBL_LIBS + FREEBL_LIB = $(DLL_PREFIX)freebl3$(DLL_SUFFIX) +-FREEBL_CHK = $(DLL_PREFIX)freebl3.chk + endif + ifdef HAVE_FREEBL_LIBS_32 + FREEBL_32INT_LIB = libfreebl_32int_3$(DLL_SUFFIX) +-FREEBL_32INT_CHK = libfreebl_32int_3.chk + FREEBL_32FPU_LIB = libfreebl_32fpu_3$(DLL_SUFFIX) +-FREEBL_32FPU_CHK = libfreebl_32fpu_3.chk + endif + ifdef HAVE_FREEBL_LIBS_32INT64 + FREEBL_32INT64_LIB = libfreebl_32int64_3$(DLL_SUFFIX) +-FREEBL_32INT64_CHK = libfreebl_32int64_3.chk + endif + ifdef HAVE_FREEBL_LIBS_64 + FREEBL_64INT_LIB = libfreebl_64int_3$(DLL_SUFFIX) +-FREEBL_64INT_CHK = libfreebl_64int_3.chk + FREEBL_64FPU_LIB = libfreebl_64fpu_3$(DLL_SUFFIX) +-FREEBL_64FPU_CHK = libfreebl_64fpu_3.chk + endif + + ABS_DIST := $(shell cd $(DIST) && pwd) +@@ -210,7 +202,6 @@ + OS_ARCH="$(OS_ARCH)" \ + CPU_ARCH="$(TARGET_CPU)" \ + $(NULL) +-SKIP_CHK=1 + endif + SUBMAKEFILES = boot/Makefile ssl/Makefile pki/Makefile locales/Makefile + +@@ -223,10 +214,6 @@ + ifndef MOZ_NATIVE_NSS + $(MAKE) -C $(topsrcdir)/security/coreconf $(DEFAULT_GMAKE_FLAGS) clean + $(MAKE) -C $(topsrcdir)/security/nss/lib $(DEFAULT_GMAKE_FLAGS) clean +-ifndef SKIP_CHK +- $(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS) clean +- $(MAKE) -C $(topsrcdir)/security/nss/cmd/shlibsign $(DEFAULT_GMAKE_FLAGS) clean +-endif + touch $@ + endif + +@@ -262,43 +249,22 @@ + # In NSS 3.11.8-3.11.9, lib/ssl/derive.c includes cmd/lib/secutil.h. + $(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS) export + $(MAKE) -C $(topsrcdir)/security/nss/lib $(DEFAULT_GMAKE_FLAGS) DIRS="util base dev pki pki1 certdb certhigh pk11wrap cryptohi nss ssl pkcs12 pkcs7 smime crmf jar ckfw ckfw/builtins" +-ifndef SKIP_CHK +- $(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS) +- $(MAKE) -C $(topsrcdir)/security/nss/cmd/shlibsign $(DEFAULT_GMAKE_FLAGS) +-endif + $(INSTALL) -m 755 $(DIST)/lib/$(LOADABLE_ROOT_MODULE) $(DIST)/bin +-ifndef SKIP_CHK +- $(INSTALL) -m 644 $(DIST)/lib/$(SOFTOKEN3_CHK) $(DIST)/bin +-endif + $(INSTALL) -m 755 $(DIST)/lib/$(SOFTOKEN3_LIB) $(DIST)/bin + $(INSTALL) -m 755 $(DIST)/lib/$(NSS3_LIB) $(DIST)/bin + $(INSTALL) -m 755 $(DIST)/lib/$(SSL3_LIB) $(DIST)/bin + $(INSTALL) -m 755 $(DIST)/lib/$(SMIME3_LIB) $(DIST)/bin + ifdef HAVE_FREEBL_LIBS +-ifndef SKIP_CHK +- $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_CHK) $(DIST)/bin +-endif + $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_LIB) $(DIST)/bin + endif + ifdef HAVE_FREEBL_LIBS_32 +-ifndef SKIP_CHK +- $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_32INT_CHK) $(DIST)/bin +- $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_32FPU_CHK) $(DIST)/bin +-endif + $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_32INT_LIB) $(DIST)/bin + $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_32FPU_LIB) $(DIST)/bin + endif + ifdef HAVE_FREEBL_LIBS_32INT64 +-ifndef SKIP_CHK +- $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_32INT64_CHK) $(DIST)/bin +-endif + $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_32INT64_LIB) $(DIST)/bin + endif + ifdef HAVE_FREEBL_LIBS_64 +-ifndef SKIP_CHK +- $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_64INT_CHK) $(DIST)/bin +- $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_64FPU_CHK) $(DIST)/bin +-endif + $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_64INT_LIB) $(DIST)/bin + $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_64FPU_LIB) $(DIST)/bin + endif +@@ -313,38 +279,21 @@ + install:: + ifndef MOZ_NATIVE_NSS + $(SYSINSTALL) -m 755 $(DIST)/lib/$(LOADABLE_ROOT_MODULE) $(DESTDIR)$(mozappdir) +-ifndef SKIP_CHK +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(SOFTOKEN3_CHK) $(DESTDIR)$(mozappdir) +-endif + $(SYSINSTALL) -m 755 $(DIST)/lib/$(SOFTOKEN3_LIB) $(DESTDIR)$(mozappdir) + $(SYSINSTALL) -m 755 $(DIST)/lib/$(NSS3_LIB) $(DESTDIR)$(mozappdir) + $(SYSINSTALL) -m 755 $(DIST)/lib/$(SSL3_LIB) $(DESTDIR)$(mozappdir) + $(SYSINSTALL) -m 755 $(DIST)/lib/$(SMIME3_LIB) $(DESTDIR)$(mozappdir) + ifdef HAVE_FREEBL_LIBS +-ifndef SKIP_CHK +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(FREEBL_CHK) $(DESTDIR)$(mozappdir) +-endif + $(SYSINSTALL) -m 755 $(DIST)/lib/$(FREEBL_LIB) $(DESTDIR)$(mozappdir) + endif + ifdef HAVE_FREEBL_LIBS_32 +-ifndef SKIP_CHK +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(FREEBL_32INT_CHK) $(DESTDIR)$(mozappdir) +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(FREEBL_32FPU_CHK) $(DESTDIR)$(mozappdir) +-endif + $(SYSINSTALL) -m 755 $(DIST)/lib/$(FREEBL_32INT_LIB) $(DESTDIR)$(mozappdir) + $(SYSINSTALL) -m 755 $(DIST)/lib/$(FREEBL_32FPU_LIB) $(DESTDIR)$(mozappdir) + endif + ifdef HAVE_FREEBL_LIBS_32INT64 +-ifndef SKIP_CHK +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(FREEBL_32INT64_CHK) $(DESTDIR)$(mozappdir) +-endif + $(SYSINSTALL) -m 755 $(DIST)/lib/$(FREEBL_32INT64_LIB) $(DESTDIR)$(mozappdir) + endif + ifdef HAVE_FREEBL_LIBS_64 +-ifndef SKIP_CHK +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(FREEBL_64INT_CHK) $(DESTDIR)$(mozappdir) +- $(SYSINSTALL) -m 644 $(DIST)/lib/$(FREEBL_64FPU_CHK) $(DESTDIR)$(mozappdir) +-endif + $(SYSINSTALL) -m 755 $(DIST)/lib/$(FREEBL_64INT_LIB) $(DESTDIR)$(mozappdir) + $(SYSINSTALL) -m 755 $(DIST)/lib/$(FREEBL_64FPU_LIB) $(DESTDIR)$(mozappdir) + endif +@@ -366,10 +315,6 @@ + ifndef MOZ_NATIVE_NSS + $(MAKE) -C $(topsrcdir)/security/coreconf $(DEFAULT_GMAKE_FLAGS) clean + $(MAKE) -C $(topsrcdir)/security/nss/lib $(DEFAULT_GMAKE_FLAGS) clean +-ifndef SKIP_CHK +- $(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS) clean +- $(MAKE) -C $(topsrcdir)/security/nss/cmd/shlibsign $(DEFAULT_GMAKE_FLAGS) clean +-endif + endif + + echo-requires-recursive:: diff --git a/neon/makefile.mk b/neon/makefile.mk index f7dc137015c4..e545a534d50a 100644 --- a/neon/makefile.mk +++ b/neon/makefile.mk @@ -46,20 +46,20 @@ TARGET=so_neon @echo "neon disabled...." .ENDIF -NEON_NAME=neon-0.28.2 +NEON_NAME=neon-0.29.3 TARFILE_NAME=$(NEON_NAME) PATCH_FILES=neon.patch -.IF "$(GUI)"=="WNT" +.IF "$(GUI)"=="WNT" PATCH_FILES+=neon_exports_win.patch .ELSE PATCH_FILES+=neon_exports_unix.patch .ENDIF -ADDITIONAL_FILES=src$/makefile.mk src$/config.h src$/ne_ntlm.h src$/ne_ntlm.c -BUILD_DIR=src +ADDITIONAL_FILES=src$/makefile.mk src$/config.h +BUILD_DIR=src BUILD_ACTION=dmake $(MFLAGS) $(CALLMACROS) OUT2INC= \ diff --git a/neon/neon.patch b/neon/neon.patch index 09233266b292..b990411fd729 100644 --- a/neon/neon.patch +++ b/neon/neon.patch @@ -1,5 +1,5 @@ ---- misc/neon-0.28.2/src/config.h 2010-01-08 11:51:21.000000000 +0100 -+++ misc/build/neon-0.28.2/src/config.h 2010-01-08 11:53:42.000000000 +0100 +--- misc/neon-0.29.3/src/config.h 2010-01-27 12:46:23.000000000 +0100 ++++ misc/build/neon-0.29.3/src/config.h 2010-01-27 12:44:10.000000000 +0100 @@ -1 +1,488 @@ -dummy + @@ -304,7 +304,7 @@ +#define NEON_IS_LIBRARY 1 + +/* Define to be the neon version string */ -+#define NEON_VERSION "0.28.2" ++#define NEON_VERSION "0.29.3" + +/* Define to enable debugging */ +/* #undef NE_DEBUGGING */ @@ -360,10 +360,10 @@ +#define NE_VERSION_MAJOR (0) + +/* Define to be neon library minor version */ -+#define NE_VERSION_MINOR (28) ++#define NE_VERSION_MINOR (29) + +/* Define to be neon library patch version */ -+#define NE_VERSION_PATCH (2) ++#define NE_VERSION_PATCH (3) + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "neon@webdav.org" @@ -372,13 +372,13 @@ +#define PACKAGE_NAME "neon" + +/* Define to the full name and version of this package. */ -+#define PACKAGE_STRING "neon 0.28.2" ++#define PACKAGE_STRING "neon 0.29.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "neon" + +/* Define to the version of this package. */ -+#define PACKAGE_VERSION "0.28.2" ++#define PACKAGE_VERSION "0.29.3" + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 @@ -490,9 +490,9 @@ +#else +#define HAVE_NTLM 1 +#endif ---- misc/neon-0.28.2/src/makefile.mk 2010-01-08 11:51:21.000000000 +0100 -+++ misc/build/neon-0.28.2/src/makefile.mk 2010-01-08 11:53:27.000000000 +0100 -@@ -1 +1,100 @@ +--- misc/neon-0.29.3/src/makefile.mk 2010-01-27 12:46:23.000000000 +0100 ++++ misc/build/neon-0.29.3/src/makefile.mk 2010-01-27 12:44:10.000000000 +0100 +@@ -1 +1,101 @@ -dummy +PRJ=..$/..$/..$/..$/.. + @@ -531,7 +531,7 @@ + +SLOFILES= \ + $(SLO)$/ne_207.obj \ -+ $(SLO)$/ne_acl.obj \ ++ $(SLO)$/ne_acl3744.obj \ + $(SLO)$/ne_alloc.obj \ + $(SLO)$/ne_auth.obj \ + $(SLO)$/ne_basic.obj \ @@ -545,6 +545,7 @@ + $(SLO)$/ne_request.obj \ + $(SLO)$/ne_session.obj \ + $(SLO)$/ne_socket.obj \ ++ $(SLO)$/ne_socks.obj \ + $(SLO)$/ne_string.obj \ + $(SLO)$/ne_uri.obj \ + $(SLO)$/ne_utils.obj \ @@ -594,62 +595,26 @@ +# --- Targets ------------------------------------------------------ +DEF1NAME=$(SHL1TARGET) +.INCLUDE : target.mk ---- misc/neon-0.28.2/src/ne_auth.c 2008-02-29 17:30:12.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_auth.c 2010-01-08 11:30:06.000000000 +0100 -@@ -77,6 +77,10 @@ - #include "ne_sspi.h" - #endif - -+#ifdef HAVE_NTLM -+#include "ne_ntlm.h" -+#endif -+ - #define HOOK_SERVER_ID "http://webdav.org/neon/hooks/server-auth" - #define HOOK_PROXY_ID "http://webdav.org/neon/hooks/proxy-auth" - -@@ -173,6 +177,10 @@ - char *sspi_token; - void *sspi_context; - #endif -+#ifdef HAVE_NTLM -+ /* This is used for NTLM auth */ -+ ne_ntlm_context *ntlm_context; -+#endif - /* These all used for Digest auth */ - char *realm; - char *nonce; -@@ -287,6 +295,11 @@ - ne_sspi_destroy_context(sess->sspi_context); - sess->sspi_context = NULL; - #endif -+#ifdef HAVE_NTLM -+ ne_ntlm_destroy_context(sess->ntlm_context); -+ sess->ntlm_context = NULL; -+#endif -+ sess->protocol = NULL; - } - - /* Returns client nonce string. */ -@@ -351,7 +364,7 @@ +--- misc/neon-0.29.3/src/ne_auth.c 2009-12-30 22:29:30.000000000 +0100 ++++ misc/build/neon-0.29.3/src/ne_auth.c 2010-01-27 12:45:34.000000000 +0100 +@@ -367,7 +367,7 @@ static int get_credentials(auth_session *sess, ne_buffer **errmsg, int attempt, struct auth_challenge *chall, char *pwbuf) { - if (chall->handler->creds(chall->handler->userdata, sess->realm, -+ if (chall->handler->creds(chall->handler->userdata, chall->protocol->name, sess->realm, ++ if (chall->handler->creds(chall->handler->userdata, chall->protocol->name, sess->realm, chall->handler->attempt++, sess->username, pwbuf) == 0) { return 0; } else { -@@ -598,7 +611,8 @@ +@@ -617,6 +617,7 @@ int ntlm = ne_strcasecmp(parms->protocol->name, "NTLM") == 0; int status; char *response = NULL; -- -+ char password[NE_ABUFSIZ]; -+ ++ char password[NE_ABUFSIZ]; + NE_DEBUG(NE_DBG_HTTPAUTH, "auth: SSPI challenge.\n"); - if (!sess->sspi_context) { -@@ -614,8 +628,17 @@ +@@ -633,8 +634,17 @@ return status; } } @@ -668,95 +633,8 @@ if (status) { return status; } -@@ -685,6 +708,62 @@ - return invalid; - } - -+#ifdef HAVE_NTLM -+ -+static char *request_ntlm(auth_session *sess, struct auth_request *request) -+{ -+ char *token = ne_ntlm_getRequestToken(sess->ntlm_context); -+ if (token) { -+ char * req = ne_concat(sess->protocol->name, " ", token, "\r\n", NULL); -+ ne_free(token); -+ return req; -+ } else { -+ return NULL; -+ } -+} -+ -+static int ntlm_challenge(auth_session *sess, int attempt, -+ struct auth_challenge *parms, -+ ne_buffer **errmsg) -+{ -+ int status; -+ -+ NE_DEBUG(NE_DBG_HTTPAUTH, "auth: NTLM challenge.\n"); -+ -+ if (!parms->opaque && (!sess->ntlm_context || (attempt > 1))) { -+ char password[NE_ABUFSIZ]; -+ -+ if (get_credentials(sess, errmsg, attempt, parms, password)) { -+ /* Failed to get credentials */ -+ return -1; -+ } -+ -+ if (sess->ntlm_context) { -+ status = ne_ntlm_destroy_context(sess->ntlm_context); -+ sess->ntlm_context = NULL; -+ if (status) { -+ return status; -+ } -+ } -+ -+ status = ne_ntlm_create_context(&sess->ntlm_context, -+ sess->username, -+ password); -+ if (status) { -+ return status; -+ } -+ } -+ -+ status = ne_ntlm_authenticate(sess->ntlm_context, parms->opaque); -+ if (status) { -+ return status; -+ } -+ -+ return 0; -+} -+#endif /* HAVE_NTLM */ -+ -+ - /* Examine a digest challenge: return 0 if it is a valid Digest challenge, - * else non-zero. */ - static int digest_challenge(auth_session *sess, int attempt, -@@ -1134,6 +1213,11 @@ - sspi_challenge, request_sspi, NULL, - AUTH_FLAG_OPAQUE_PARAM|AUTH_FLAG_VERIFY_NON40x|AUTH_FLAG_CONN_AUTH }, - #endif -+#ifdef HAVE_NTLM -+ { NE_AUTH_NEGOTIATE, 30, "NTLM", -+ ntlm_challenge, request_ntlm, NULL, -+ AUTH_FLAG_OPAQUE_PARAM|AUTH_FLAG_VERIFY_NON40x|AUTH_FLAG_CONN_AUTH }, -+#endif - { 0 } - }; - -@@ -1431,6 +1515,11 @@ - ne_sspi_clear_context(sess->sspi_context); - } - #endif -+#ifdef HAVE_NTLM -+ if (sess->ntlm_context) { -+ ne_ntlm_clear_context(sess->ntlm_context); -+ } -+#endif - - return ret; - } ---- misc/neon-0.28.2/src/ne_auth.h 2007-12-05 17:39:58.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_auth.h 2010-01-08 11:30:07.000000000 +0100 +--- misc/neon-0.29.3/src/ne_auth.h 2009-09-01 22:13:12.000000000 +0200 ++++ misc/build/neon-0.29.3/src/ne_auth.h 2010-01-27 12:44:10.000000000 +0100 @@ -47,8 +47,8 @@ * Hint: if you just wish to attempt authentication just once (even if * the user gets the username/password wrong), have the callback @@ -768,8 +646,8 @@ /* Set callbacks to provide credentials for server and proxy * authentication, using the default set of authentication protocols. ---- misc/neon-0.28.2/src/ne_defs.h 2006-10-24 21:40:09.000000000 +0200 -+++ misc/build/neon-0.28.2/src/ne_defs.h 2010-01-08 11:30:07.000000000 +0100 +--- misc/neon-0.29.3/src/ne_defs.h 2009-09-02 16:04:43.000000000 +0200 ++++ misc/build/neon-0.29.3/src/ne_defs.h 2010-01-27 12:44:10.000000000 +0100 @@ -41,7 +41,7 @@ #endif @@ -779,8 +657,8 @@ #define ssize_t int #endif ---- misc/neon-0.28.2/src/ne_locks.c 2007-02-05 11:09:27.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_locks.c 2010-01-08 11:30:06.000000000 +0100 +--- misc/neon-0.29.3/src/ne_locks.c 2007-02-05 11:09:27.000000000 +0100 ++++ misc/build/neon-0.29.3/src/ne_locks.c 2010-01-27 12:44:10.000000000 +0100 @@ -579,6 +579,23 @@ const char *token = ne_get_response_header(ctx->req, "Lock-Token"); /* at the root element; retrieve the Lock-Token header, @@ -847,8 +725,8 @@ ctx->found = 1; } } ---- misc/neon-0.28.2/src/ne_locks.h 2006-01-02 12:43:19.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_locks.h 2010-01-08 11:30:07.000000000 +0100 +--- misc/neon-0.29.3/src/ne_locks.h 2006-01-02 12:43:19.000000000 +0100 ++++ misc/build/neon-0.29.3/src/ne_locks.h 2010-01-27 12:44:10.000000000 +0100 @@ -22,6 +22,10 @@ #ifndef NE_LOCKS_H #define NE_LOCKS_H @@ -860,773 +738,8 @@ #include "ne_request.h" /* for ne_session + ne_request */ #include "ne_uri.h" /* for ne_uri */ ---- misc/neon-0.28.2/src/ne_ntlm.c 2010-01-08 11:51:21.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_ntlm.c 2010-01-08 11:53:52.000000000 +0100 -@@ -1 +1,703 @@ --dummy -+/* -+ Handling of NTLM Authentication -+ Copyright (C) 2003, Daniel Stenberg <daniel@haxx.se> -+ Copyright (C) 2009, Kai Sommerfeld <kso@openoffice.org> -+ -+ This library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Library General Public -+ License as published by the Free Software Foundation; either -+ version 2 of the License, or (at your option) any later version. -+ -+ This library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Library General Public License for more details. -+ -+ You should have received a copy of the GNU Library General Public -+ License along with this library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -+ MA 02111-1307, USA -+ -+*/ -+ -+/* NTLM details: -+ -+ http://davenport.sourceforge.net/ntlm.html -+ http://www.innovation.ch/java/ntlm.html -+ -+*/ -+ -+#include "ne_ntlm.h" -+ -+#ifdef HAVE_NTLM -+ -+#include "ne_string.h" -+ -+typedef enum { -+ NTLMSTATE_NONE, -+ NTLMSTATE_TYPE1, -+ NTLMSTATE_TYPE2, -+ NTLMSTATE_TYPE3, -+ NTLMSTATE_LAST -+} NTLMState; -+ -+struct ne_ntlm_context_s { -+ NTLMState state; -+ unsigned char nonce[8]; -+ char *user; -+ char *passwd; -+ char *requestToken; -+}; -+ -+typedef enum { -+ NTLM_NONE, /* not a ntlm */ -+ NTLM_BAD, /* an ntlm, but one we don't like */ -+ NTLM_FIRST, /* the first 401-reply we got with NTLM */ -+ NTLM_FINE, /* an ntlm we act on */ -+ -+ NTLM_LAST /* last entry in this enum, don't use */ -+} ntlm; -+ -+/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */ -+ -+#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) -+/* Indicates that Unicode strings are supported for use in security buffer -+ data. */ -+ -+#define NTLMFLAG_NEGOTIATE_OEM (1<<1) -+/* Indicates that OEM strings are supported for use in security buffer data. */ -+ -+#define NTLMFLAG_REQUEST_TARGET (1<<2) -+/* Requests that the server's authentication realm be included in the Type 2 -+ message. */ -+ -+/* unknown (1<<3) */ -+#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) -+/* Specifies that authenticated communication between the client and server -+ should carry a digital signature (message integrity). */ -+ -+#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) -+/* Specifies that authenticated communication between the client and server -+ should be encrypted (message confidentiality). */ -+ -+#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) -+/* unknown purpose */ -+ -+#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) -+/* Indicates that the LAN Manager session key should be used for signing and -+ sealing authenticated communications. */ -+ -+#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) -+/* unknown purpose */ -+ -+#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) -+/* Indicates that NTLM authentication is being used. */ -+ -+/* unknown (1<<10) */ -+/* unknown (1<<11) */ -+ -+#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) -+/* Sent by the client in the Type 1 message to indicate that a desired -+ authentication realm is included in the message. */ -+ -+#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) -+/* Sent by the client in the Type 1 message to indicate that the client -+ workstation's name is included in the message. */ -+ -+#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) -+/* Sent by the server to indicate that the server and client are on the same -+ machine. Implies that the client may use a pre-established local security -+ context rather than responding to the challenge. */ -+ -+#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) -+/* Indicates that authenticated communication between the client and server -+ should be signed with a "dummy" signature. */ -+ -+#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) -+/* Sent by the server in the Type 2 message to indicate that the target -+ authentication realm is a domain. */ -+ -+#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) -+/* Sent by the server in the Type 2 message to indicate that the target -+ authentication realm is a server. */ -+ -+#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) -+/* Sent by the server in the Type 2 message to indicate that the target -+ authentication realm is a share. Presumably, this is for share-level -+ authentication. Usage is unclear. */ -+ -+#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) -+/* Indicates that the NTLM2 signing and sealing scheme should be used for -+ protecting authenticated communications. */ -+ -+#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) -+/* unknown purpose */ -+ -+#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) -+/* unknown purpose */ -+ -+#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) -+/* unknown purpose */ -+ -+#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) -+/* Sent by the server in the Type 2 message to indicate that it is including a -+ Target Information block in the message. */ -+ -+/* unknown (1<24) */ -+/* unknown (1<25) */ -+/* unknown (1<26) */ -+/* unknown (1<27) */ -+/* unknown (1<28) */ -+ -+#define NTLMFLAG_NEGOTIATE_128 (1<<29) -+/* Indicates that 128-bit encryption is supported. */ -+ -+#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) -+/* unknown purpose */ -+ -+#define NTLMFLAG_NEGOTIATE_56 (1<<31) -+/* Indicates that 56-bit encryption is supported. */ -+ -+#ifdef HAVE_OPENSSL -+/* We need OpenSSL for the crypto lib to provide us with MD4 and DES */ -+ -+/* -- WIN32 approved -- */ -+#include <stdio.h> -+#include <string.h> -+#include <stdarg.h> -+#include <stdlib.h> -+#include <ctype.h> -+ -+#include <openssl/des.h> -+#include <openssl/md4.h> -+#include <openssl/ssl.h> -+ -+#if OPENSSL_VERSION_NUMBER < 0x00907001L -+#define DES_key_schedule des_key_schedule -+#define DES_cblock des_cblock -+#define DES_set_odd_parity des_set_odd_parity -+#define DES_set_key des_set_key -+#define DES_ecb_encrypt des_ecb_encrypt -+ -+/* This is how things were done in the old days */ -+#define DESKEY(x) x -+#define DESKEYARG(x) x -+#else -+/* Modern version */ -+#define DESKEYARG(x) *x -+#define DESKEY(x) &x -+#endif -+ -+/* Define this to make the type-3 message include the NT response message */ -+#define USE_NTRESPONSES 1 -+ -+/* -+ (*) = A "security buffer" is a triplet consisting of two shorts and one -+ long: -+ -+ 1. a 'short' containing the length of the buffer in bytes -+ 2. a 'short' containing the allocated space for the buffer in bytes -+ 3. a 'long' containing the offset to the start of the buffer from the -+ beginning of the NTLM message, in bytes. -+*/ -+ -+static ntlm ne_input_ntlm(ne_ntlm_context *ctx, -+ const char *responseToken) -+{ -+ if(responseToken) { -+ /* We got a type-2 message here: -+ -+ Index Description Content -+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" -+ (0x4e544c4d53535000) -+ 8 NTLM Message Type long (0x02000000) -+ 12 Target Name security buffer(*) -+ 20 Flags long -+ 24 Challenge 8 bytes -+ (32) Context (optional) 8 bytes (two consecutive longs) -+ (40) Target Information (optional) security buffer(*) -+ 32 (48) start of data block -+ */ -+ unsigned char * buffer = NULL; -+ -+ int size = ne_unbase64(responseToken, &buffer); -+ -+ ctx->state = NTLMSTATE_TYPE2; /* we got a type-2 */ -+ -+ if(size >= 48) -+ /* the nonce of interest is index [24 .. 31], 8 bytes */ -+ memcpy(ctx->nonce, &buffer[24], 8); -+ -+ /* at index decimal 20, there's a 32bit NTLM flag field */ -+ -+ if (buffer) ne_free(buffer); -+ } -+ else { -+ if(ctx->state >= NTLMSTATE_TYPE1) -+ return NTLM_BAD; -+ -+ ctx->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */ -+ } -+ return NTLM_FINE; -+} -+ -+/* -+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The -+ * key schedule ks is also set. -+ */ -+static void setup_des_key(unsigned char *key_56, -+ DES_key_schedule DESKEYARG(ks)) -+{ -+ DES_cblock key; -+ -+ key[0] = key_56[0]; -+ key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); -+ key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); -+ key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); -+ key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); -+ key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); -+ key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); -+ key[7] = (key_56[6] << 1) & 0xFF; -+ -+ DES_set_odd_parity(&key); -+ DES_set_key(&key, ks); -+} -+ -+ /* -+ * takes a 21 byte array and treats it as 3 56-bit DES keys. The -+ * 8 byte plaintext is encrypted with each key and the resulting 24 -+ * bytes are stored in the results array. -+ */ -+static void calc_resp(unsigned char *keys, -+ unsigned char *plaintext, -+ unsigned char *results) -+{ -+ DES_key_schedule ks; -+ -+ setup_des_key(keys, DESKEY(ks)); -+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, -+ DESKEY(ks), DES_ENCRYPT); -+ -+ setup_des_key(keys+7, DESKEY(ks)); -+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8), -+ DESKEY(ks), DES_ENCRYPT); -+ -+ setup_des_key(keys+14, DESKEY(ks)); -+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), -+ DESKEY(ks), DES_ENCRYPT); -+} -+ -+/* -+ * Set up lanmanager and nt hashed passwords -+ */ -+static void mkhash(char *password, -+ unsigned char *nonce, /* 8 bytes */ -+ unsigned char *lmresp /* must fit 0x18 bytes */ -+#ifdef USE_NTRESPONSES -+ , unsigned char *ntresp /* must fit 0x18 bytes */ -+#endif -+ ) -+{ -+ unsigned char lmbuffer[21]; -+#ifdef USE_NTRESPONSES -+ unsigned char ntbuffer[21]; -+#endif -+ unsigned char *pw; -+ static const unsigned char magic[] = { -+ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 -+ }; -+ int i; -+ int len = strlen(password); -+ -+ /* make it fit at least 14 bytes */ -+ pw = malloc(len<7?14:len*2); -+ if(!pw) -+ return; /* this will lead to a badly generated package */ -+ -+ if (len > 14) -+ len = 14; -+ -+ for (i=0; i<len; i++) -+ pw[i] = toupper(password[i]); -+ -+ for (; i<14; i++) -+ pw[i] = 0; -+ -+ { -+ /* create LanManager hashed password */ -+ DES_key_schedule ks; -+ -+ setup_des_key(pw, DESKEY(ks)); -+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, -+ DESKEY(ks), DES_ENCRYPT); -+ -+ setup_des_key(pw+7, DESKEY(ks)); -+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8), -+ DESKEY(ks), DES_ENCRYPT); -+ -+ memset(lmbuffer+16, 0, 5); -+ } -+ /* create LM responses */ -+ calc_resp(lmbuffer, nonce, lmresp); -+ -+#ifdef USE_NTRESPONSES -+ { -+ /* create NT hashed password */ -+ MD4_CTX MD4; -+ -+ len = strlen(password); -+ -+ for (i=0; i<len; i++) { -+ pw[2*i] = password[i]; -+ pw[2*i+1] = 0; -+ } -+ -+ MD4_Init(&MD4); -+ MD4_Update(&MD4, pw, 2*len); -+ MD4_Final(ntbuffer, &MD4); -+ -+ memset(ntbuffer+16, 0, 8); -+ } -+ -+ calc_resp(ntbuffer, nonce, ntresp); -+#endif -+ -+ free(pw); -+} -+ -+#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8) -+#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \ -+ (((x) >>16)&0xff), ((x)>>24) -+ -+/* this is for creating ntlm header output */ -+static int ne_output_ntlm(ne_ntlm_context *ctx) -+{ -+ const char *domain=""; /* empty */ -+ const char *host=""; /* empty */ -+ int domlen=strlen(domain); -+ int hostlen = strlen(host); -+ int hostoff; /* host name offset */ -+ int domoff; /* domain name offset */ -+ int size; -+ unsigned char ntlmbuf[256]; /* enough, unless the host/domain is very long */ -+ -+ if(!ctx->user || !ctx->passwd) -+ /* no user, no auth */ -+ return 0; /* OK */ -+ -+ switch(ctx->state) { -+ case NTLMSTATE_TYPE1: -+ default: /* for the weird cases we (re)start here */ -+ hostoff = 32; -+ domoff = hostoff + hostlen; -+ -+ /* Create and send a type-1 message: -+ -+ Index Description Content -+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" -+ (0x4e544c4d53535000) -+ 8 NTLM Message Type long (0x01000000) -+ 12 Flags long -+ 16 Supplied Domain security buffer(*) -+ 24 Supplied Workstation security buffer(*) -+ 32 start of data block -+ -+ */ -+ -+ snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c" -+ "\x01%c%c%c" /* 32-bit type = 1 */ -+ "%c%c%c%c" /* 32-bit NTLM flag field */ -+ "%c%c" /* domain length */ -+ "%c%c" /* domain allocated space */ -+ "%c%c" /* domain name offset */ -+ "%c%c" /* 2 zeroes */ -+ "%c%c" /* host length */ -+ "%c%c" /* host allocated space */ -+ "%c%c" /* host name offset */ -+ "%c%c" /* 2 zeroes */ -+ "%s" /* host name */ -+ "%s", /* domain string */ -+ 0, /* trailing zero */ -+ 0,0,0, /* part of type-1 long */ -+ -+ LONGQUARTET( -+ NTLMFLAG_NEGOTIATE_OEM| /* 2 */ -+ NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */ -+ /* equals 0x0202 */ -+ ), -+ SHORTPAIR(domlen), -+ SHORTPAIR(domlen), -+ SHORTPAIR(domoff), -+ 0,0, -+ SHORTPAIR(hostlen), -+ SHORTPAIR(hostlen), -+ SHORTPAIR(hostoff), -+ 0,0, -+ host, domain); -+ -+ /* initial packet length */ -+ size = 32 + hostlen + domlen; -+ -+ /* now keeper of the base64 encoded package size */ -+ if (ctx->requestToken) ne_free(ctx->requestToken); -+ ctx->requestToken = ne_base64(ntlmbuf, size); -+ -+ break; -+ -+ case NTLMSTATE_TYPE2: -+ /* We received the type-2 already, create a type-3 message: -+ -+ Index Description Content -+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" -+ (0x4e544c4d53535000) -+ 8 NTLM Message Type long (0x03000000) -+ 12 LM/LMv2 Response security buffer(*) -+ 20 NTLM/NTLMv2 Response security buffer(*) -+ 28 Domain Name security buffer(*) -+ 36 User Name security buffer(*) -+ 44 Workstation Name security buffer(*) -+ (52) Session Key (optional) security buffer(*) -+ (60) Flags (optional) long -+ 52 (64) start of data block -+ -+ */ -+ -+ { -+ int lmrespoff; -+ int ntrespoff; -+ int useroff; -+ unsigned char lmresp[0x18]; /* fixed-size */ -+#ifdef USE_NTRESPONSES -+ unsigned char ntresp[0x18]; /* fixed-size */ -+#endif -+ const char *user; -+ int userlen; -+ -+ user = strchr(ctx->user, '\\'); -+ if(!user) -+ user = strchr(ctx->user, '/'); -+ -+ if (user) { -+ domain = ctx->user; -+ domlen = user - domain; -+ user++; -+ } -+ else -+ user = ctx->user; -+ userlen = strlen(user); -+ -+ mkhash(ctx->passwd, &ctx->nonce[0], lmresp -+#ifdef USE_NTRESPONSES -+ , ntresp -+#endif -+ ); -+ -+ domoff = 64; /* always */ -+ useroff = domoff + domlen; -+ hostoff = useroff + userlen; -+ lmrespoff = hostoff + hostlen; -+ ntrespoff = lmrespoff + 0x18; -+ -+ /* Create the big type-3 message binary blob */ -+ size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf), -+ "NTLMSSP%c" -+ "\x03%c%c%c" /* type-3, 32 bits */ -+ -+ "%c%c%c%c" /* LanManager length + allocated space */ -+ "%c%c" /* LanManager offset */ -+ "%c%c" /* 2 zeroes */ -+ -+ "%c%c" /* NT-response length */ -+ "%c%c" /* NT-response allocated space */ -+ "%c%c" /* NT-response offset */ -+ "%c%c" /* 2 zeroes */ -+ -+ "%c%c" /* domain length */ -+ "%c%c" /* domain allocated space */ -+ "%c%c" /* domain name offset */ -+ "%c%c" /* 2 zeroes */ -+ -+ "%c%c" /* user length */ -+ "%c%c" /* user allocated space */ -+ "%c%c" /* user offset */ -+ "%c%c" /* 2 zeroes */ -+ -+ "%c%c" /* host length */ -+ "%c%c" /* host allocated space */ -+ "%c%c" /* host offset */ -+ "%c%c%c%c%c%c" /* 6 zeroes */ -+ -+ "\xff\xff" /* message length */ -+ "%c%c" /* 2 zeroes */ -+ -+ "\x01\x82" /* flags */ -+ "%c%c" /* 2 zeroes */ -+ -+ /* domain string */ -+ /* user string */ -+ /* host string */ -+ /* LanManager response */ -+ /* NT response */ -+ , -+ 0, /* zero termination */ -+ 0,0,0, /* type-3 long, the 24 upper bits */ -+ -+ SHORTPAIR(0x18), /* LanManager response length, twice */ -+ SHORTPAIR(0x18), -+ SHORTPAIR(lmrespoff), -+ 0x0, 0x0, -+ -+#ifdef USE_NTRESPONSES -+ SHORTPAIR(0x18), /* NT-response length, twice */ -+ SHORTPAIR(0x18), -+#else -+ 0x0, 0x0, -+ 0x0, 0x0, -+#endif -+ SHORTPAIR(ntrespoff), -+ 0x0, 0x0, -+ -+ SHORTPAIR(domlen), -+ SHORTPAIR(domlen), -+ SHORTPAIR(domoff), -+ 0x0, 0x0, -+ -+ SHORTPAIR(userlen), -+ SHORTPAIR(userlen), -+ SHORTPAIR(useroff), -+ 0x0, 0x0, -+ -+ SHORTPAIR(hostlen), -+ SHORTPAIR(hostlen), -+ SHORTPAIR(hostoff), -+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -+ -+ 0x0, 0x0, -+ -+ 0x0, 0x0); -+ -+ /* size is now 64 */ -+ size=64; -+ ntlmbuf[62]=ntlmbuf[63]=0; -+ -+ /* Make sure that the user and domain strings fit in the target buffer -+ before we copy them there. */ -+ if(size + userlen + domlen >= sizeof(ntlmbuf)) { -+ return -1; -+ } -+ -+ memcpy(&ntlmbuf[size], domain, domlen); -+ size += domlen; -+ -+ memcpy(&ntlmbuf[size], user, userlen); -+ size += userlen; -+ -+ /* we append the binary hashes to the end of the blob */ -+ if(size < ((int)sizeof(ntlmbuf) - 0x18)) { -+ memcpy(&ntlmbuf[size], lmresp, 0x18); -+ size += 0x18; -+ } -+ -+#ifdef USE_NTRESPONSES -+ if(size < ((int)sizeof(ntlmbuf) - 0x18)) { -+ memcpy(&ntlmbuf[size], ntresp, 0x18); -+ size += 0x18; -+ } -+#endif -+ -+ ntlmbuf[56] = size & 0xff; -+ ntlmbuf[57] = size >> 8; -+ -+ /* convert the binary blob into base64 */ -+ ctx->requestToken = ne_base64(ntlmbuf, size); -+ -+ ctx->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ -+ } -+ break; -+ -+ case NTLMSTATE_TYPE3: -+ /* connection is already authenticated, -+ * don't send a header in future requests */ -+ if (ctx->requestToken) ne_free(ctx->requestToken); -+ ctx->requestToken = NULL; -+ break; -+ } -+ -+ return 0; /* OK */ -+} -+ -+int ne_ntlm_create_context(ne_ntlm_context **context, const char *userName, const char *password) -+{ -+ if (context == NULL) { -+ return -1; -+ } else { -+ ne_ntlm_context *ctx = ne_calloc(sizeof(ne_ntlm_context)); -+ -+ ctx->state = NTLMSTATE_NONE; -+ ctx->user = ne_strdup(userName); -+ ctx->passwd = ne_strdup(password); -+ -+ *context = ctx; -+ return 0; -+ } -+} -+ -+int ne_ntlm_destroy_context(ne_ntlm_context *context) -+{ -+ if (context != NULL) { -+ if (context->user) -+ ne_free(context->user); -+ -+ if (context->passwd) -+ ne_free(context->passwd); -+ -+ if (context->requestToken) -+ ne_free(context->requestToken); -+ -+ ne_free(context); -+ } -+ return 0; -+} -+ -+int ne_ntlm_clear_context(ne_ntlm_context *context) -+{ -+ return 0; -+} -+ -+int ne_ntlm_authenticate(ne_ntlm_context *context, const char *responseToken) -+{ -+ if (context == NULL) { -+ return -1; -+ } else { -+ if (!responseToken && (context->state == NTLMSTATE_TYPE3)) -+ context->state = NTLMSTATE_NONE; -+ -+ if (context->state <= NTLMSTATE_TYPE3) { -+ ntlm ntlmstatus = ne_input_ntlm(context, responseToken); -+ -+ if (ntlmstatus != NTLM_FINE) { -+ return -1; -+ } -+ } -+ } -+ return ne_output_ntlm(context); -+} -+ -+char *ne_ntlm_getRequestToken(ne_ntlm_context *context) -+{ -+ if (context == NULL) { -+ return NULL; -+ } else { -+ if (context->requestToken) { -+ char *ret = ne_strdup(context->requestToken); -+ ne_free(context->requestToken); -+ context->requestToken = NULL; -+ return ret; -+ } else { -+ return NULL; -+ } -+ } -+} -+ -+#endif /* HAVE_OPENSSL */ -+#endif /* HAVE_NTLM */ ---- misc/neon-0.28.2/src/ne_ntlm.h 2010-01-08 11:51:21.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_ntlm.h 2010-01-08 11:53:52.000000000 +0100 -@@ -1 +1,44 @@ --dummy -+/* -+ Handling of NTLM Authentication -+ Copyright (C) 2009, Kai Sommerfeld <kso@openoffice.org> -+ -+ This library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Library General Public -+ License as published by the Free Software Foundation; either -+ version 2 of the License, or (at your option) any later version. -+ -+ This library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Library General Public License for more details. -+ -+ You should have received a copy of the GNU Library General Public -+ License along with this library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -+ MA 02111-1307, USA -+ -+*/ -+#ifndef NE_NTLM_H -+#define NE_NTLM_H -+ -+#include "config.h" -+ -+/* PRIVATE TO NEON -- NOT PART OF THE EXTERNAL API. */ -+ -+#ifdef HAVE_NTLM -+ -+typedef struct ne_ntlm_context_s ne_ntlm_context; -+ -+int ne_ntlm_create_context(ne_ntlm_context **context, const char *userName, const char *password); -+ -+int ne_ntlm_destroy_context(ne_ntlm_context *context); -+ -+int ne_ntlm_clear_context(ne_ntlm_context *context); -+ -+int ne_ntlm_authenticate(ne_ntlm_context *context, const char *responseToken); -+ -+char *ne_ntlm_getRequestToken(ne_ntlm_context *context); -+ -+#endif /* HAVE_NTLM */ -+ -+#endif /* NE_NTLM_H */ ---- misc/neon-0.28.2/src/ne_socket.c 2008-02-28 14:19:19.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_socket.c 2010-01-08 11:30:06.000000000 +0100 -@@ -60,6 +60,7 @@ - #include <stddef.h> - #ifdef USE_GETADDRINFO - #include <ws2tcpip.h> -+#include <Wspiapi.h> - #endif - #endif - ---- misc/neon-0.28.2/src/ne_sspi.c 2007-08-10 17:26:08.000000000 +0200 -+++ misc/build/neon-0.28.2/src/ne_sspi.c 2010-01-08 11:30:07.000000000 +0100 +--- misc/neon-0.29.3/src/ne_sspi.c 2007-08-10 17:26:08.000000000 +0200 ++++ misc/build/neon-0.29.3/src/ne_sspi.c 2010-01-27 12:44:10.000000000 +0100 @@ -206,6 +206,45 @@ } @@ -1712,8 +825,8 @@ securityStatus = initializeSecurityContext(&sspiContext->credentials, NULL, ---- misc/neon-0.28.2/src/ne_sspi.h 2006-02-12 13:05:14.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_sspi.h 2010-01-08 11:30:06.000000000 +0100 +--- misc/neon-0.29.3/src/ne_sspi.h 2006-02-12 13:05:14.000000000 +0100 ++++ misc/build/neon-0.29.3/src/ne_sspi.h 2010-01-27 12:44:10.000000000 +0100 @@ -41,7 +41,7 @@ int ne_sspi_clear_context(void *context); @@ -1723,8 +836,8 @@ #endif /* HAVE_SSPI */ ---- misc/neon-0.28.2/src/ne_uri.c 2007-12-05 12:04:47.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_uri.c 2010-01-08 11:30:06.000000000 +0100 +--- misc/neon-0.29.3/src/ne_uri.c 2007-12-05 12:04:47.000000000 +0100 ++++ misc/build/neon-0.29.3/src/ne_uri.c 2010-01-27 12:44:10.000000000 +0100 @@ -42,7 +42,7 @@ #include "ne_alloc.h" #include "ne_uri.h" @@ -1770,8 +883,8 @@ /* 3x */ DG, DG, DG, DG, DG, DG, DG, DG, DG, DG, CL, SD, OT, SD, OT, QU, /* 4x */ AT, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, /* 5x */ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, GD, OT, GD, OT, US, ---- misc/neon-0.28.2/src/ne_utils.c 2006-03-07 10:36:43.000000000 +0100 -+++ misc/build/neon-0.28.2/src/ne_utils.c 2010-01-08 11:30:06.000000000 +0100 +--- misc/neon-0.29.3/src/ne_utils.c 2006-03-07 10:36:43.000000000 +0100 ++++ misc/build/neon-0.29.3/src/ne_utils.c 2010-01-27 12:44:10.000000000 +0100 @@ -118,6 +118,9 @@ #ifdef HAVE_GNUTLS ", GNU TLS " LIBGNUTLS_VERSION @@ -1801,8 +914,8 @@ return 1; #endif /* NE_HAVE_* */ default: ---- misc/neon-0.28.2/src/ne_utils.h 2007-07-16 08:54:57.000000000 +0200 -+++ misc/build/neon-0.28.2/src/ne_utils.h 2010-01-08 11:30:07.000000000 +0100 +--- misc/neon-0.29.3/src/ne_utils.h 2007-07-16 08:54:57.000000000 +0200 ++++ misc/build/neon-0.29.3/src/ne_utils.h 2010-01-27 12:44:10.000000000 +0100 @@ -54,6 +54,7 @@ #define NE_FEATURE_SOCKS (5) /* SOCKSv5 support */ #define NE_FEATURE_TS_SSL (6) /* Thread-safe SSL/TLS support */ diff --git a/neon/neon_exports_unix.patch b/neon/neon_exports_unix.patch index 1ee17690c8ed..55bdaac7adc4 100644 --- a/neon/neon_exports_unix.patch +++ b/neon/neon_exports_unix.patch @@ -1,7 +1,7 @@ ---- misc/neon-0.28.2/src/exports.map 2009-09-29 10:28:13.531250000 +0200 -+++ misc/build/neon-0.28.2/src/exports.map 2009-09-21 12:16:53.453125000 +0200 -@@ -0,0 +1,287 @@ -+NEON_0_28_2 { +--- misc/neon-0.29.3/src/exports.map 2009-09-29 10:28:13.531250000 +0200 ++++ misc/build/neon-0.29.3/src/exports.map 2009-09-21 12:16:53.453125000 +0200 +@@ -0,0 +1,288 @@ ++NEON_0_29_3 { + global: + ne__negotiate_ssl; + ne__ssl_exit; @@ -125,6 +125,7 @@ + ne_sock_peek; + ne_sock_peer; + ne_sock_prebind; ++ ne_sock_proxy; + ne_sock_read; + ne_sock_read_timeout; + ne_sock_readline; @@ -275,7 +276,7 @@ + ne_realloc; + ne_strdup; + ne_strndup; -+ ne_acl_set; ++ ne_acl3744_set; + ne_207_create; + ne_207_destroy; + ne_207_get_current_propstat; diff --git a/neon/neon_exports_win.patch b/neon/neon_exports_win.patch index 479f03a9d6bc..09bc86eebce4 100644 --- a/neon/neon_exports_win.patch +++ b/neon/neon_exports_win.patch @@ -1,7 +1,7 @@ ---- misc/neon-0.28.2/src/exports.map 2009-09-29 10:28:13.531250000 +0200 -+++ misc/build/neon-0.28.2/src/exports.map 2009-09-21 12:16:53.453125000 +0200 -@@ -0,0 +1,292 @@ -+NEON_0_28_2 { +--- misc/neon-0.29.3/src/exports.map 2009-09-29 10:28:13.531250000 +0200 ++++ misc/build/neon-0.29.3/src/exports.map 2009-09-21 12:16:53.453125000 +0200 +@@ -0,0 +1,294 @@ ++NEON_0_29_3 { + global: + ne_sspi_authenticate; + ne_sspi_clear_context; @@ -131,6 +131,7 @@ + ne_sock_peek; + ne_sock_peer; + ne_sock_prebind; ++ ne_sock_proxy; + ne_sock_read; + ne_sock_read_timeout; + ne_sock_readline; @@ -281,7 +282,8 @@ + ne_realloc; + ne_strdup; + ne_strndup; -+ ne_acl_set; ++ ne_free; ++ ne_acl3744_set; + ne_207_create; + ne_207_destroy; + ne_207_get_current_propstat; diff --git a/neon/version.mk b/neon/version.mk index 86716c5746f3..418999ff1452 100644 --- a/neon/version.mk +++ b/neon/version.mk @@ -28,9 +28,9 @@ # the major NEON_MAJOR=0 # the minor -NEON_MINOR=28 +NEON_MINOR=29 # the micro -NEON_MICRO=2 +NEON_MICRO=3 # concat NEON_VERSION=$(NEON_MAJOR)$(NEON_MINOR)$(NEON_MICRO) diff --git a/offapi/com/sun/star/chart/XChartDataArray.idl b/offapi/com/sun/star/chart/XChartDataArray.idl index 011597f41f66..4e7519864382 100644 --- a/offapi/com/sun/star/chart/XChartDataArray.idl +++ b/offapi/com/sun/star/chart/XChartDataArray.idl @@ -39,6 +39,8 @@ /** gives access to data represented as an array of rows. + <p>Can be obtained from interface <type>XChartDocument</type> via method getData().</p> + <p>If used for an <type>XYDiagram</type>, the row number 0 represents the <i>x</i>-values.</p> */ diff --git a/offapi/com/sun/star/chart/XChartDocument.idl b/offapi/com/sun/star/chart/XChartDocument.idl index 05966982b992..14322c6edf4a 100644 --- a/offapi/com/sun/star/chart/XChartDocument.idl +++ b/offapi/com/sun/star/chart/XChartDocument.idl @@ -136,20 +136,38 @@ published interface XChartDocument: com::sun::star::frame::XModel //------------------------------------------------------------------------- /** @returns - the data source of the chart. + the data of the chart. - @see ChartData + <p>The returned object supports interface <type>XChartDataArray</type> + which can be used to access the concrete data.</p> + + <p>Since OOo 3.3 the returned object also supports interface <type>XComplexDescriptionAccess</type> + which can be used to access complex hierarchical axis descriptions.</p> + + @see XChartData + @see XChartDataArray + @see XComplexDescriptionAccess */ com::sun::star::chart::XChartData getData(); //------------------------------------------------------------------------- - /** attaches an external data source to the chart. + /** attaches data to the chart. + + <p>The given object needs to support interface <type>XChartDataArray</type>.</p> + + <p>Since OOo 3.3 if the given object might support interface <type>XComplexDescriptionAccess</type> + which allows to set complex hierarchical axis descriptions.</p> + + <p>The given data is copied before it is applied to the chart. + So changing xData after this call will have no effect on the chart.</p> - @see ChartData + @see XChartData + @see XChartDataArray + @see XComplexDescriptionAccess @param xData - the component that provides the new data. + the object that provides the new data. */ void attachData( [in] com::sun::star::chart::XChartData xData ); diff --git a/offapi/com/sun/star/chart/XComplexDescriptionAccess.idl b/offapi/com/sun/star/chart/XComplexDescriptionAccess.idl new file mode 100755 index 000000000000..4e5af5f3ba83 --- /dev/null +++ b/offapi/com/sun/star/chart/XComplexDescriptionAccess.idl @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef __com_sun_star_chart_XComplexDescriptionAccess_idl__ +#define __com_sun_star_chart_XComplexDescriptionAccess_idl__ + +#ifndef __com_sun_star_chart_XChartDataArray_idl__ +#include <com/sun/star/chart/XChartDataArray.idl> +#endif + +//============================================================================= + + module com { module sun { module star { module chart { + +//============================================================================= + +/** Offers access to complex column and row descriptions. + +<p>Can be obtained from interface <type>XChartDocument</type> via method getData().</p> + +@since OOo 3.3 +*/ + +published interface XComplexDescriptionAccess : XChartDataArray +{ + //------------------------------------------------------------------------- + + /** retrieves the description texts for all rows. + + @returns + a sequence of sequences of strings representing the descriptions + of all rows. The outer index represents different rows. + The inner index represents the different levels (usually there is only one). + */ + sequence< sequence< string > > getComplexRowDescriptions(); + + //------------------------------------------------------------------------- + + /** sets the description texts for all rows. + + @param rRowDescriptions + a sequence of sequences of strings representing the descriptions of all + rows. The outer index represents different rows. + The inner index represents the different levels (usually there is only one). + */ + void setComplexRowDescriptions( [in] sequence< sequence< string > > rRowDescriptions ); + + //------------------------------------------------------------------------- + + /** retrieves the description texts for all columns. + + @returns + a sequence of sequences of strings representing the descriptions + of all columns. The outer index represents different columns. + The inner index represents the different levels (usually there is only one). + */ + sequence< sequence< string > > getComplexColumnDescriptions(); + + //------------------------------------------------------------------------- + + /** sets the description texts for all columns. + + @param rColumnDescriptions + a sequence of sequences of strings which represent the descriptions of + all columns. The outer index represents different columns. + The inner index represents the different levels (usually there is only one). + */ + void setComplexColumnDescriptions( [in] sequence< sequence< string > > rColumnDescriptions ); +}; + +//============================================================================= + +}; }; }; }; + +#endif diff --git a/offapi/com/sun/star/chart/makefile.mk b/offapi/com/sun/star/chart/makefile.mk index 7e3c01393824..2c0b93256b3b 100644 --- a/offapi/com/sun/star/chart/makefile.mk +++ b/offapi/com/sun/star/chart/makefile.mk @@ -103,6 +103,7 @@ IDLFILES=\ XChartDataArray.idl\ XChartDataChangeEventListener.idl\ XChartDocument.idl\ + XComplexDescriptionAccess.idl\ XDiagram.idl\ XStatisticDisplay.idl\ XTwoAxisXSupplier.idl\ diff --git a/offapi/com/sun/star/chart2/InterpretedData.idl b/offapi/com/sun/star/chart2/InterpretedData.idl index dfa2b27493ce..0eedd9c44df3 100644 --- a/offapi/com/sun/star/chart2/InterpretedData.idl +++ b/offapi/com/sun/star/chart2/InterpretedData.idl @@ -51,10 +51,6 @@ struct InterpretedData /** */ data::XLabeledDataSequence Categories; - - /** - */ - sequence< data::XLabeledDataSequence > UnusedData; }; } ; // chart2 diff --git a/offapi/com/sun/star/chart2/XChartTypeTemplate.idl b/offapi/com/sun/star/chart2/XChartTypeTemplate.idl index 5f8947baaed7..05308ba7dfcf 100644 --- a/offapi/com/sun/star/chart2/XChartTypeTemplate.idl +++ b/offapi/com/sun/star/chart2/XChartTypeTemplate.idl @@ -78,12 +78,10 @@ interface XChartTypeTemplate : ::com::sun::star::uno::XInterface [in] data::XDataSource xDataSource, [in] sequence< com::sun::star::beans::PropertyValue > aArguments ); - /** Return the names of parameters that are interpreted in the - <member>createDiagramByDataSource</member> method. - - @see StandardChartTypeTemplateParameters + /** @return + <TRUE/> if the template does support categories */ - sequence< string > getAvailableCreationParameterNames(); + boolean supportsCategories(); /** Analyses the given diagram and reinterprets its <type>DataSeries</type> and <type>Categories</type> and diff --git a/offapi/com/sun/star/chart2/XDataInterpreter.idl b/offapi/com/sun/star/chart2/XDataInterpreter.idl index d6cd1b19ee50..14238dc531a5 100644 --- a/offapi/com/sun/star/chart2/XDataInterpreter.idl +++ b/offapi/com/sun/star/chart2/XDataInterpreter.idl @@ -74,10 +74,6 @@ interface XDataInterpreter : ::com::sun::star::uno::XInterface /** Re-interprets the data given in <code>aInterpretedData</code> while keeping the number of data series and the categories. - - <p>the data passed in - <member>InterpretedData::UnusedData</member> may be used to be - added to existing <type>DataSeries</type>.</p> */ InterpretedData reinterpretDataSeries( [in] InterpretedData aInterpretedData ); @@ -85,11 +81,6 @@ interface XDataInterpreter : ::com::sun::star::uno::XInterface <member>reinterpretDataSeries</member> call can be done without data loss. - <p>if this method returns <TRUE/>, a call to - <member>reinterpretDataSeries</member> should leave the - <member>InterpretedData::UnusedData</member> list - untouched.</p> - @return <TRUE/>, if the data given in <code>aInterpretedData</code> has a similar structure than diff --git a/offapi/com/sun/star/chart2/XDiagram.idl b/offapi/com/sun/star/chart2/XDiagram.idl index c38f8b0824f7..3836489b7aed 100644 --- a/offapi/com/sun/star/chart2/XDiagram.idl +++ b/offapi/com/sun/star/chart2/XDiagram.idl @@ -87,10 +87,6 @@ interface XDiagram : ::com::sun::star::uno::XInterface colors for data series (or data points) in the diagram. */ void setDefaultColorScheme( [in] XColorScheme xColorScheme ); - - void setUnusedData( [in] sequence< data::XLabeledDataSequence > aUnusedData ); - - sequence< data::XLabeledDataSequence > getUnusedData(); }; } ; // chart2 diff --git a/offapi/com/sun/star/chart2/XInternalDataProvider.idl b/offapi/com/sun/star/chart2/XInternalDataProvider.idl index 5504e7f79abe..a1f9caa64092 100644 --- a/offapi/com/sun/star/chart2/XInternalDataProvider.idl +++ b/offapi/com/sun/star/chart2/XInternalDataProvider.idl @@ -39,7 +39,7 @@ module star module chart2 { -/** An internal DataProvider that has more access to data that a plain +/** An internal DataProvider that has more access to data than a plain DataProvider. */ interface XInternalDataProvider : com::sun::star::chart2::data::XDataProvider @@ -73,6 +73,17 @@ interface XInternalDataProvider : com::sun::star::chart2::data::XDataProvider it has to be explicitly registered via this method.</p> */ void registerDataSequenceForChanges( [in] data::XDataSequence xSeq ); + + /** insert an additional sequence for categories nLevel>=1; + categories at level 0 are always present and cannot be inserted or deleted + @since OOo 3.3 + */ + void insertComplexCategoryLevel( [in] long nLevel ); + /** deletes an additional sequence for categories at nLevel>=1; + categories at level 0 are always present and cannot be deleted + @since OOo 3.3 + */ + void deleteComplexCategoryLevel( [in] long nLevel ); }; } ; // chart2 diff --git a/offapi/com/sun/star/chart2/data/XDataReceiver.idl b/offapi/com/sun/star/chart2/data/XDataReceiver.idl index fa8cd9823c00..10602cee2f34 100644 --- a/offapi/com/sun/star/chart2/data/XDataReceiver.idl +++ b/offapi/com/sun/star/chart2/data/XDataReceiver.idl @@ -73,24 +73,6 @@ interface XDataReceiver : ::com::sun::star::uno::XInterface */ void attachDataProvider( [in] XDataProvider xProvider ); - /** Sets the data for the chart as a whole. When this method is - called, all currently set data is removed. It is replaced by - the data that is returned by the current - <type>XDataProvider</type> by using the given range - representation. - - @param aRangeRepresentation - This range representation must be in a format that is - understood by the currently attached - <type>XDataProvider</type>. - - @throws com::sun::star::lang::IllegalArgumentException - If the range representation could not dealt with by the - current data provider, or there is currently no data - provider at all. - */ -// void setRangeRepresentation( [in] string aRangeRepresentation ) -// raises( com::sun::star::lang::IllegalArgumentException ); void setArguments( [in] sequence< com::sun::star::beans::PropertyValue > aArguments ) raises( com::sun::star::lang::IllegalArgumentException ); diff --git a/offapi/com/sun/star/sheet/DataPilotDescriptor.idl b/offapi/com/sun/star/sheet/DataPilotDescriptor.idl index 8e303601cb95..992afdef5ed9 100644 --- a/offapi/com/sun/star/sheet/DataPilotDescriptor.idl +++ b/offapi/com/sun/star/sheet/DataPilotDescriptor.idl @@ -40,6 +40,10 @@ #include <com/sun/star/beans/XPropertySet.idl> #endif +#ifndef __com_sun_star_beans_PropertyValue_idl__ +#include <com/sun/star/beans/PropertyValue.idl> +#endif + //============================================================================= module com { module sun { module star { module sheet { @@ -73,6 +77,36 @@ published service DataPilotDescriptor //========================================================================= + /** specifies parameters to create the data pilot table from a database. + + @see DatabaseImportDescriptor + @since OOo 3.3.0 + + */ + [optional, property] sequence< com::sun::star::beans::PropertyValue > ImportDescriptor; + + //------------------------------------------------------------------------- + + /** specifies the name of a <type>DataPilotSource</type> implementation + for the data pilot table. + + @since OOo 3.3.0 + + */ + [optional, property] string SourceServiceName; + + //------------------------------------------------------------------------- + + /** specifies arguments that are passed to the implementation named by + <member>SourceServiceName</member>. + + @since OOo 3.3.0 + + */ + [optional, property] sequence< com::sun::star::beans::PropertyValue > ServiceArguments; + + //------------------------------------------------------------------------- + /** specifies the orientation of the field. */ [optional, property] boolean IgnoreEmptyRows; diff --git a/offapi/com/sun/star/sheet/DataPilotTable.idl b/offapi/com/sun/star/sheet/DataPilotTable.idl index db09028abd42..c2385c46e5fa 100644 --- a/offapi/com/sun/star/sheet/DataPilotTable.idl +++ b/offapi/com/sun/star/sheet/DataPilotTable.idl @@ -36,6 +36,10 @@ #include <com/sun/star/sheet/XDataPilotTable.idl> #endif +#ifndef __com_sun_star_util_XModifyBroadcaster_idl__ +#include <com/sun/star/util/XModifyBroadcaster.idl> +#endif + //============================================================================= module com { module sun { module star { module sheet { @@ -58,6 +62,14 @@ published service DataPilotTable */ interface com::sun::star::sheet::XDataPilotTable; + //------------------------------------------------------------------------- + + /** allows notification of modifications to the data pilot table. + + @since OOo 3.3.0 + + */ + [optional] interface com::sun::star::util::XModifyBroadcaster; }; //============================================================================= diff --git a/offapi/prj/build.lst b/offapi/prj/build.lst index 226741529436..a0be2398f429 100644 --- a/offapi/prj/build.lst +++ b/offapi/prj/build.lst @@ -94,7 +94,7 @@ oa offapi\com\sun\star\xsd nmake - all oa_xsd NULL oa offapi\com\sun\star\inspection nmake - all oa_inspection NULL oa offapi\com\sun\star\ui nmake - all oa_ui NULL oa offapi\com\sun\star\ui\dialogs nmake - all oa_ui_dialogs NULL -oa offapi\com\sun\star nmake - all - NULL +oa offapi\com\sun\star nmake - all oa_starme NULL oa offapi\com\sun\star\security nmake - all oa_security NULL oa offapi\com\sun\star\xml\crypto\sax nmake - all oa_crypto_sax oa_wrapper oa_csax NULL oa offapi\com\sun\star\xml\crypto nmake - all oa_crypto oa_wrapper oa_security NULL @@ -105,4 +105,4 @@ oa offapi\com\sun\star\rendering nmake - all oa_rendering oa_geometry NU oa offapi\com\sun\star\rdf nmake - all oa_rdf oa_datatransfer oa_text NULL oa offapi\com\sun\star\office nmake - all oa_office oa_text NULL oa offapi\drafts\com\sun\star\form nmake - all oa_drafts_form NULL -oa offapi\util nmake - all oa_util oa_auth oa_awt oa_awttree oa_awtgrid oa_chart oa_chart2 oa_chart2_data oa_config oa_configbootstrap oa_configbackend oa_configbackend_xml oa_datatrans_clip oa_datatrans_dnd oa_datatransfer oa_docu oa_draw oa_draw_framework oa_embed oa_fcomp oa_finsp oa_fcontr oa_fieldmaster oa_form oa_xforms oa_formula oa_frame oa_i18n oa_inst oa_ldap oa_ling2 oa_logging oa_mail oa_media oa_mozilla oa_packages oa_manifest oa_zippackage oa_plug oa_pres oa_animations oa_putil oa_resrc oa_sax oa_xml_input oa_scan oa_sdb oa_sdbtools oa_sdbapp oa_sdbc oa_sdbcx oa_setup oa_sheet oa_style oa_svg oa_sync oa_sync2 oa_system oa_table oa_task oa_text oa_textfield oa_docinfo oa_ucb oa_view oa_xml oa_xml_dom oa_xml_xpath oa_xml_views oa_xml_events oa_image oa_xsd oa_inspection oa_ui oa_ui_dialogs oa_accessibility oa_form_binding oa_form_validation oa_form_submission oa_fruntime oa_geometry oa_rendering oa_sfprovider oa_sfbrowse oa_drafts_form oa_deployment oa_deploymenttest oa_deployment_ui oa_frame_status oa_gallery oa_graphic oa_security oa_crypto_sax oa_crypto oa_csax oa_wrapper oa_script oa_smarttags oa_report oa_reportins oa_reportmeta oa_rdf oa_oooimprovement oa_office NULL +oa offapi\util nmake - all oa_util oa_auth oa_awt oa_awttree oa_awtgrid oa_chart oa_chart2 oa_chart2_data oa_config oa_configbootstrap oa_configbackend oa_configbackend_xml oa_datatrans_clip oa_datatrans_dnd oa_datatransfer oa_docu oa_draw oa_draw_framework oa_embed oa_fcomp oa_finsp oa_fcontr oa_fieldmaster oa_form oa_xforms oa_formula oa_frame oa_i18n oa_inst oa_ldap oa_ling2 oa_logging oa_mail oa_media oa_mozilla oa_packages oa_manifest oa_zippackage oa_plug oa_pres oa_animations oa_putil oa_resrc oa_sax oa_xml_input oa_scan oa_sdb oa_sdbtools oa_sdbapp oa_sdbc oa_sdbcx oa_setup oa_sheet oa_style oa_svg oa_sync oa_sync2 oa_system oa_table oa_task oa_text oa_textfield oa_docinfo oa_ucb oa_view oa_xml oa_xml_dom oa_xml_xpath oa_xml_views oa_xml_events oa_image oa_xsd oa_inspection oa_ui oa_ui_dialogs oa_accessibility oa_form_binding oa_form_validation oa_form_submission oa_fruntime oa_geometry oa_rendering oa_sfprovider oa_sfbrowse oa_drafts_form oa_deployment oa_deploymenttest oa_deployment_ui oa_frame_status oa_gallery oa_graphic oa_security oa_crypto_sax oa_crypto oa_csax oa_wrapper oa_script oa_smarttags oa_report oa_reportins oa_reportmeta oa_rdf oa_oooimprovement oa_office oa_prestextfield oa_starme NULL diff --git a/postprocess/packregistry/makefile.mk b/postprocess/packregistry/makefile.mk index 054f98233389..ec7c5c0a3e2d 100644 --- a/postprocess/packregistry/makefile.mk +++ b/postprocess/packregistry/makefile.mk @@ -499,6 +499,9 @@ $(MISC)/lang/Langpack-%.xcd .ERRREMOVE : $(MISC)/lang/fcfg_langpack_{$(alllangiso)}.xcd : $(SOLARPCKDIR)/$$(@:b).zip +# It can happen that localized $(SOLARPCKDIR)/fcfg_langpack_*.zip contain +# zero-sized org/openoffice/TypeDectection/Filter.xcu; filter them out in the +# find shell command below (see issue 110041): $(MISC)/lang/fcfg_langpack_%.xcd .ERRREMOVE : $(MKDIRHIER) $(@:d) rm -rf $(MISC)/$(@:b).unzip @@ -506,7 +509,7 @@ $(MISC)/lang/fcfg_langpack_%.xcd .ERRREMOVE : cd $(MISC)/$(@:b).unzip && unzip $(SOLARPCKDIR)/$(@:b).zip - $(RM) $(MISC)/$(@:b).list echo '<list>' $(foreach,i,$(shell cd $(MISC) && \ - find $(@:b).unzip -name \*.xcu -print) \ + find $(@:b).unzip -name \*.xcu -size +0c -print) \ '<filename>$i</filename>') '</list>' > $(MISC)/$(@:b).list $(XSLTPROC) --nonet -o $@ $(SOLARENV)/bin/packregistry.xslt \ $(MISC)/$(@:b).list diff --git a/redland/rasqal/makefile.mk b/redland/rasqal/makefile.mk index af0f34ab9431..fc9e93baaa6d 100644 --- a/redland/rasqal/makefile.mk +++ b/redland/rasqal/makefile.mk @@ -55,8 +55,7 @@ OOO_PATCH_FILES= \ $(TARFILE_NAME).patch.autotools \ $(TARFILE_NAME).patch.ooo_build \ $(TARFILE_NAME).patch.dmake \ - $(TARFILE_NAME).patch.win32 \ - + $(TARFILE_NAME).patch.win32 PATCH_FILES=$(OOO_PATCH_FILES) diff --git a/redland/rasqal/rasqal-0.9.16.patch.ooo_build b/redland/rasqal/rasqal-0.9.16.patch.ooo_build index eb4d24bb9c45..827147995e6f 100644 --- a/redland/rasqal/rasqal-0.9.16.patch.ooo_build +++ b/redland/rasqal/rasqal-0.9.16.patch.ooo_build @@ -32,3 +32,25 @@ fi if test "$echo_libtool_libs" = "yes"; then echo @libdir@/@RASQAL_LIBTOOLLIBS@ +--- misc/rasqal-0.9.16/Makefile.am 2010-02-12 08:43:21.000000000 +0000 ++++ misc/build/rasqal-0.9.16/Makefile.am 2010-02-12 08:43:56.000000000 +0000 +@@ -22,7 +22,7 @@ + + noinst_SCRIPTS = rasqal-src-config + +-SUBDIRS=src utils tests docs data win32 ++SUBDIRS=src tests docs data win32 + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = rasqal.pc +--- misc/rasqal-0.9.16/Makefile.in 2010-02-12 08:43:19.000000000 +0000 ++++ misc/build/rasqal-0.9.16/Makefile.in 2010-02-12 08:44:03.000000000 +0000 +@@ -242,7 +242,7 @@ + with_raptor = @with_raptor@ + with_redland = @with_redland@ + noinst_SCRIPTS = rasqal-src-config +-SUBDIRS = src utils tests docs data win32 ++SUBDIRS = src tests docs data win32 + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = rasqal.pc + EXTRA_DIST = ChangeLog ChangeLog.1 ChangeLog.2 ChangeLog.3 ChangeLog.4 \ diff --git a/redland/redland/makefile.mk b/redland/redland/makefile.mk index 2808686420ce..c89724087dc9 100644 --- a/redland/redland/makefile.mk +++ b/redland/redland/makefile.mk @@ -54,14 +54,13 @@ OOO_PATCH_FILES= \ $(TARFILE_NAME).patch.legal \ $(TARFILE_NAME).patch.autotools \ $(TARFILE_NAME).patch.dmake \ - $(TARFILE_NAME).patch.win32 \ - + $(TARFILE_NAME).patch.ooo_build \ + $(TARFILE_NAME).patch.win32 PATCH_FILES=$(OOO_PATCH_FILES) \ $(TARFILE_NAME).patch.free_null \ $(TARFILE_NAME).patch.storage_hashes_context_serialize_get_statement \ - $(TARFILE_NAME).patch.storage_hashes_list_duplicates \ - + $(TARFILE_NAME).patch.storage_hashes_list_duplicates .IF "$(OS)"=="OS2" BUILD_ACTION=dmake diff --git a/redland/redland/redland-1.0.8.patch.ooo_build b/redland/redland/redland-1.0.8.patch.ooo_build new file mode 100644 index 000000000000..805a88d49ea2 --- /dev/null +++ b/redland/redland/redland-1.0.8.patch.ooo_build @@ -0,0 +1,22 @@ +--- misc/redland-1.0.8/Makefile.am 2010-02-12 08:47:40.000000000 +0000 ++++ misc/build/redland-1.0.8/Makefile.am 2010-02-12 08:47:51.000000000 +0000 +@@ -48,7 +48,7 @@ + # to ensure that the raptor and rasqal subdirectories are called + # as CONFIG_SUBDIR directories. + # +-SUBDIRS=@LOCAL_SUBDIRS@ librdf examples utils demos docs data ++SUBDIRS=@LOCAL_SUBDIRS@ librdf examples demos docs data + + EXTRA_DIST=ChangeLog ChangeLog.1 ChangeLog.2 ChangeLog.3 ChangeLog.4 \ + ChangeLog.5 ChangeLog.6 ChangeLog.7 \ +--- misc/redland-1.0.8/Makefile.in 2010-02-12 08:47:39.000000000 +0000 ++++ misc/build/redland-1.0.8/Makefile.in 2010-02-12 08:47:55.000000000 +0000 +@@ -283,7 +283,7 @@ + # to ensure that the raptor and rasqal subdirectories are called + # as CONFIG_SUBDIR directories. + # +-SUBDIRS = @LOCAL_SUBDIRS@ librdf examples utils demos docs data ++SUBDIRS = @LOCAL_SUBDIRS@ librdf examples demos docs data + EXTRA_DIST = ChangeLog ChangeLog.1 ChangeLog.2 ChangeLog.3 ChangeLog.4 \ + ChangeLog.5 ChangeLog.6 ChangeLog.7 \ + README NEWS LICENSE.txt TODO \ diff --git a/reportdesign/source/ui/inc/DataProvider.hxx b/reportdesign/source/ui/inc/DataProvider.hxx deleted file mode 100644 index 11c602bb3519..000000000000 --- a/reportdesign/source/ui/inc/DataProvider.hxx +++ /dev/null @@ -1,537 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef RPT_DATAPROVIDER_HXX -#define RPT_DATAPROVIDER_HXX - -#include <svl/lstner.hxx> -#include <com/sun/star/chart2/data/XDataProvider.hpp> -#include <com/sun/star/chart2/data/XRangeXMLConversion.hpp> -#include <com/sun/star/chart2/data/XDataSource.hpp> -#include <com/sun/star/chart2/data/XDataSequence.hpp> -#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> -#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> -#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> -#include <com/sun/star/chart2/data/DataSequenceRole.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/util/XCloneable.hpp> -#include <com/sun/star/util/XModifyBroadcaster.hpp> -// #ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ -// #include <com/sun/star/lang/XUnoTunnel.hpp> -// #endif -#include <cppuhelper/implbase3.hxx> -#include <rtl/ustring.hxx> -#include <svl/itemprop.hxx> - -#include <map> -#include <list> - -// DataProvider ============================================================== -class DatabaseDataProvider : public - ::cppu::WeakImplHelper3< - ::com::sun::star::chart2::data::XDataProvider, - ::com::sun::star::chart2::data::XRangeXMLConversion, - ::com::sun::star::lang::XServiceInfo>, - SfxListener -{ -public: - - explicit DatabaseDataProvider( ScDocument* pDoc ); - virtual ~DatabaseDataProvider(); - -private: - virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); - - // XDataProvider --------------------------------------------------------- - - virtual ::sal_Bool SAL_CALL createDataSourcePossible( - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArguments ) - throw (::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSource > SAL_CALL createDataSource( - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArguments ) - throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Sequence< - ::com::sun::star::beans::PropertyValue > SAL_CALL detectArguments( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource >& xDataSource ) - throw (::com::sun::star::uno::RuntimeException); - - virtual ::sal_Bool SAL_CALL createDataSequenceByRangeRepresentationPossible( - const ::rtl::OUString& aRangeRepresentation ) - throw (::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSequence > SAL_CALL createDataSequenceByRangeRepresentation( - const ::rtl::OUString& aRangeRepresentation ) - throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XRangeSelection > SAL_CALL getRangeSelection() - throw (::com::sun::star::uno::RuntimeException); - -/* virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > SAL_CALL getNumberFormatsSupplier() - throw (::com::sun::star::uno::RuntimeException);*/ - - // XRangeXMLConversion --------------------------------------------------- - - virtual ::rtl::OUString SAL_CALL convertRangeToXML( const ::rtl::OUString& sRangeRepresentation ) - throw ( ::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException ); - - virtual ::rtl::OUString SAL_CALL convertRangeFromXML( const ::rtl::OUString& sXMLRange ) - throw ( ::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException ); - - // XServiceInfo ---------------------------------------------------------- - - virtual ::rtl::OUString SAL_CALL getImplementationName() throw( - ::com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& - rServiceName) throw( ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL - getSupportedServiceNames() throw( - ::com::sun::star::uno::RuntimeException); -private: -}; - - -// DataSource ================================================================ - -class ScChart2DataSource : public - ::cppu::WeakImplHelper2< - ::com::sun::star::chart2::data::XDataSource, - ::com::sun::star::lang::XServiceInfo>, - SfxListener -{ -public: - - explicit ScChart2DataSource( ScDocument* pDoc); - virtual ~ScChart2DataSource(); - virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); - - // XDataSource ----------------------------------------------------------- - - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XLabeledDataSequence > > SAL_CALL - getDataSequences() throw (::com::sun::star::uno::RuntimeException); - - // XServiceInfo ---------------------------------------------------------- - - virtual ::rtl::OUString SAL_CALL getImplementationName() throw( - ::com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& - rServiceName) throw( ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL - getSupportedServiceNames() throw( - ::com::sun::star::uno::RuntimeException); - - // implementation - - void AddLabeledSequence(const com::sun::star::uno::Reference < com::sun::star::chart2::data::XLabeledDataSequence >& xNew); - -private: - - ScDocument* m_pDocument; - typedef std::list < com::sun::star::uno::Reference< com::sun::star::chart2::data::XLabeledDataSequence > > LabeledList; - LabeledList m_aLabeledSequences; - -}; - - -// LabeledDataSequence ======================================================= - -class ScChart2LabeledDataSequence : public - ::cppu::WeakImplHelper4< - ::com::sun::star::chart2::data::XLabeledDataSequence, - ::com::sun::star::util::XCloneable, - ::com::sun::star::util::XModifyBroadcaster, - ::com::sun::star::lang::XServiceInfo >, - SfxListener -{ -public: - - explicit ScChart2LabeledDataSequence( ScDocument* pDoc ); - virtual ~ScChart2LabeledDataSequence(); - - // SfxListener ----------------------------------------------------------- - - virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); - - // XLabeledDataSequence -------------------------------------------------- - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > SAL_CALL getValues() - throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setValues( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >& xSequence ) - throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > SAL_CALL getLabel() - throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setLabel( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >& xSequence ) - throw (::com::sun::star::uno::RuntimeException); - - // XCloneable ------------------------------------------------------------ - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() - throw (::com::sun::star::uno::RuntimeException); - - // XModifyBroadcaster ---------------------------------------------------- - - virtual void SAL_CALL addModifyListener( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) - throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeModifyListener( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) - throw (::com::sun::star::uno::RuntimeException); - - // XServiceInfo ---------------------------------------------------------- - - virtual ::rtl::OUString SAL_CALL getImplementationName() throw( - ::com::sun::star::uno::RuntimeException); - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& - rServiceName) throw( ::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL - getSupportedServiceNames() throw( - ::com::sun::star::uno::RuntimeException); - -private: - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSequence > m_aData; - ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::data::XDataSequence > m_aLabel; - ScDocument* m_pDocument; -}; - -// DataSequence ============================================================== - -class ScChart2DataSequence : public - ::cppu::WeakImplHelper7< - ::com::sun::star::chart2::data::XDataSequence, - ::com::sun::star::chart2::data::XTextualDataSequence, - ::com::sun::star::chart2::data::XNumericalDataSequence, - ::com::sun::star::util::XCloneable, - ::com::sun::star::util::XModifyBroadcaster, - ::com::sun::star::beans::XPropertySet, -// ::com::sun::star::lang::XUnoTunnel, - ::com::sun::star::lang::XServiceInfo>, - SfxListener -{ -public: - - explicit ScChart2DataSequence( ScDocument* pDoc, - const com::sun::star::uno::Reference< com::sun::star::chart2::data::XDataProvider >& xDP, - const ScRangeListRef& rRangeList ); - virtual ~ScChart2DataSequence(); - virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); - - // XDataSequence --------------------------------------------------------- - - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > - SAL_CALL getData() throw (::com::sun::star::uno::RuntimeException); - virtual ::rtl::OUString SAL_CALL getSourceRangeRepresentation() - throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > - SAL_CALL generateLabel(::com::sun::star::chart2::data::LabelOrigin nOrigin) - throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Int32 SAL_CALL getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) - throw (::com::sun::star::lang::IndexOutOfBoundsException, - ::com::sun::star::uno::RuntimeException); - - // XNumericalDataSequence -------------------------------------------------- - - virtual ::com::sun::star::uno::Sequence< double > - SAL_CALL getNumericalData( ) throw (::com::sun::star::uno::RuntimeException); - - // XTextualDataSequence -------------------------------------------------- - - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > - SAL_CALL getTextualData( ) throw (::com::sun::star::uno::RuntimeException); - - // XPropertySet ---------------------------------------------------------- - - virtual ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XPropertySetInfo> SAL_CALL - getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL setPropertyValue( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Any& rValue) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::beans::PropertyVetoException, - ::com::sun::star::lang::IllegalArgumentException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( - const ::rtl::OUString& rPropertyName) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL addPropertyChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XPropertyChangeListener>& xListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removePropertyChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XPropertyChangeListener>& rListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL addVetoableChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XVetoableChangeListener>& rListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removeVetoableChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XVetoableChangeListener>& rListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - // XCloneable ------------------------------------------------------------ - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() - throw (::com::sun::star::uno::RuntimeException); - - // XModifyBroadcaster ---------------------------------------------------- - - virtual void SAL_CALL addModifyListener( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) - throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeModifyListener( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) - throw (::com::sun::star::uno::RuntimeException); - - // XServiceInfo ---------------------------------------------------------- - - virtual ::rtl::OUString SAL_CALL getImplementationName() throw( - ::com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& - rServiceName) throw( ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL - getSupportedServiceNames() throw( - ::com::sun::star::uno::RuntimeException); - - // XUnoTunnel ------------------------------------------------------------ - -// virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< -// sal_Int8 >& aIdentifier ) -// throw(::com::sun::star::uno::RuntimeException); - -// static const com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelId(); -// static ScChart2DataSequence* getImplementation( const com::sun::star::uno::Reference< -// com::sun::star::uno::XInterface> xObj ); - - // Implementation -------------------------------------------------------- - - ScRangeListRef GetRangeList() { return m_xRanges; } - - void RefChanged(); - DECL_LINK( ValueListenerHdl, SfxHint* ); - -private: - - // properties - ::com::sun::star::chart2::data::DataSequenceRole m_aRole; - sal_Bool m_bHidden; - // internals - ScRangeListRef m_xRanges; - sal_Int64 m_nObjectId; - ScDocument* m_pDocument; - com::sun::star::uno::Reference < com::sun::star::chart2::data::XDataProvider > m_xDataProvider; - SfxItemPropertySet m_aPropSet; - - ScLinkListener* m_pValueListener; - sal_Bool m_bGotDataChangedHint; - XModifyListenerArr_Impl m_aValueListeners; -}; - -// DataSequence ============================================================== - -class ScChart2EmptyDataSequence : public - ::cppu::WeakImplHelper6< - ::com::sun::star::chart2::data::XDataSequence, - ::com::sun::star::chart2::data::XTextualDataSequence, - ::com::sun::star::util::XCloneable, - ::com::sun::star::util::XModifyBroadcaster, - ::com::sun::star::beans::XPropertySet, -// ::com::sun::star::lang::XUnoTunnel, - ::com::sun::star::lang::XServiceInfo>, - SfxListener -{ -public: - - explicit ScChart2EmptyDataSequence( ScDocument* pDoc, - const com::sun::star::uno::Reference< com::sun::star::chart2::data::XDataProvider >& xDP, - const ScRangeListRef& rRangeList, sal_Bool bColumn ); - virtual ~ScChart2EmptyDataSequence(); - virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); - - // XDataSequence --------------------------------------------------------- - - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > - SAL_CALL getData() throw (::com::sun::star::uno::RuntimeException); - virtual ::rtl::OUString SAL_CALL getSourceRangeRepresentation() - throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > - SAL_CALL generateLabel(::com::sun::star::chart2::data::LabelOrigin nOrigin) - throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Int32 SAL_CALL getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) - throw (::com::sun::star::lang::IndexOutOfBoundsException, - ::com::sun::star::uno::RuntimeException); - - // XTextualDataSequence -------------------------------------------------- - - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > - SAL_CALL getTextualData( ) throw (::com::sun::star::uno::RuntimeException); - - // XPropertySet ---------------------------------------------------------- - - virtual ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XPropertySetInfo> SAL_CALL - getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL setPropertyValue( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Any& rValue) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::beans::PropertyVetoException, - ::com::sun::star::lang::IllegalArgumentException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( - const ::rtl::OUString& rPropertyName) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL addPropertyChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XPropertyChangeListener>& xListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removePropertyChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XPropertyChangeListener>& rListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL addVetoableChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XVetoableChangeListener>& rListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removeVetoableChangeListener( - const ::rtl::OUString& rPropertyName, - const ::com::sun::star::uno::Reference< - ::com::sun::star::beans::XVetoableChangeListener>& rListener) - throw( ::com::sun::star::beans::UnknownPropertyException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException); - - // XCloneable ------------------------------------------------------------ - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() - throw (::com::sun::star::uno::RuntimeException); - - // XModifyBroadcaster ---------------------------------------------------- - - virtual void SAL_CALL addModifyListener( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) - throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeModifyListener( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) - throw (::com::sun::star::uno::RuntimeException); - - // XServiceInfo ---------------------------------------------------------- - - virtual ::rtl::OUString SAL_CALL getImplementationName() throw( - ::com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& - rServiceName) throw( ::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL - getSupportedServiceNames() throw( - ::com::sun::star::uno::RuntimeException); - - // XUnoTunnel ------------------------------------------------------------ - -// virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< -// sal_Int8 >& aIdentifier ) -// throw(::com::sun::star::uno::RuntimeException); - -// static const com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelId(); -// static ScChart2DataSequence* getImplementation( const com::sun::star::uno::Reference< -// com::sun::star::uno::XInterface> xObj ); - - // Implementation -------------------------------------------------------- - - ScRangeListRef GetRangeList() { return m_xRanges; } - -private: - - // properties - ::com::sun::star::chart2::data::DataSequenceRole m_aRole; - sal_Bool m_bHidden; - // internals - ScRangeListRef m_xRanges; - ScDocument* m_pDocument; - com::sun::star::uno::Reference < com::sun::star::chart2::data::XDataProvider > m_xDataProvider; - SfxItemPropertySet m_aPropSet; - sal_Bool m_bColumn; // defines the orientation to create the right labels - -}; - -#endif // RPT_DATAPROVIDER_HXX diff --git a/sc/inc/chart2uno.hxx b/sc/inc/chart2uno.hxx index d63e47d642b9..44737e711090 100644 --- a/sc/inc/chart2uno.hxx +++ b/sc/inc/chart2uno.hxx @@ -188,24 +188,6 @@ public: getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException); - /** - * Check the current list of reference tokens, and add the upper left - * corner of the minimum range that encloses all ranges if certain - * conditions are met. - * - * @param rRefTokens list of reference tokens - * - * @return true if the corner was added, false otherwise. - */ - static bool addUpperLeftCornerIfMissing(::std::vector<ScSharedTokenRef>& rRefTokens); - -private: - - void detectRangesFromDataSource(::std::vector<ScSharedTokenRef>& rRefTokens, - ::com::sun::star::chart::ChartDataRowSource& rRowSource, - bool& rRowSourceDetected, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource >& xDataSource); - private: ScDocument* m_pDocument; diff --git a/sc/inc/dapiuno.hxx b/sc/inc/dapiuno.hxx index ba695d8784bc..c9a5305a05ca 100644 --- a/sc/inc/dapiuno.hxx +++ b/sc/inc/dapiuno.hxx @@ -31,6 +31,8 @@ #include "global.hxx" #include "dpobject.hxx" #include "rangeutl.hxx" // ScArea +#include "cellsuno.hxx" // for XModifyListenerArr_Impl + #include <svl/lstner.hxx> #include <svl/itemprop.hxx> @@ -39,6 +41,7 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/container/XEnumerationAccess.hpp> #include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp> #include <com/sun/star/sheet/DataPilotFieldGroupInfo.hpp> @@ -313,11 +316,15 @@ public: // ============================================================================ class ScDataPilotTableObj : public ScDataPilotDescriptorBase, - public com::sun::star::sheet::XDataPilotTable2 + public com::sun::star::sheet::XDataPilotTable2, + public com::sun::star::util::XModifyBroadcaster { private: SCTAB nTab; String aName; + XModifyListenerArr_Impl aModifyListeners; + + void Refreshed_Impl(); public: ScDataPilotTableObj(ScDocShell* pDocSh, SCTAB nT, const String& rN); @@ -329,6 +336,8 @@ public: virtual void SAL_CALL acquire() throw(); virtual void SAL_CALL release() throw(); + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + virtual ScDPObject* GetDPObject() const; virtual void SetDPObject(ScDPObject* pDPObj); @@ -361,6 +370,14 @@ public: throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::util::XModifyListener >& aListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::util::XModifyListener >& aListener ) + throw (::com::sun::star::uno::RuntimeException); + // XTypeProvider (overloaded) virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx index 1f980bdec3bf..21e23e883da9 100644 --- a/sc/inc/dpsdbtab.hxx +++ b/sc/inc/dpsdbtab.hxx @@ -50,6 +50,8 @@ struct ScImportSourceDesc USHORT nType; // enum DataImportMode BOOL bNative; + ScImportSourceDesc() : nType(0), bNative(FALSE) {} + BOOL operator== ( const ScImportSourceDesc& rOther ) const { return aDBName == rOther.aDBName && aObject == rOther.aObject && diff --git a/sc/inc/hints.hxx b/sc/inc/hints.hxx index 00791921527d..fca3d184a4a2 100644 --- a/sc/inc/hints.hxx +++ b/sc/inc/hints.hxx @@ -170,4 +170,16 @@ public: const ScImportParam& GetImportParam() const { return aParam; } }; +class ScDataPilotModifiedHint : public SfxHint +{ + String maName; + +public: + TYPEINFO(); + ScDataPilotModifiedHint( const String& rName ); + ~ScDataPilotModifiedHint(); + + const String& GetName() const { return maName; } +}; + #endif diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 84e5c4b11cb1..f5de35c9d033 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -574,6 +574,15 @@ #define SC_UNO_RPTEMPTY "RepeatIfEmpty" #define SC_UNO_DRILLDOWN "DrillDownOnDoubleClick" #define SC_UNO_SHOWFILT "ShowFilterButton" +#define SC_UNO_IMPORTDESC "ImportDescriptor" +#define SC_UNO_SOURCESERV "SourceServiceName" +#define SC_UNO_SERVICEARG "ServiceArguments" + +// properties in data pilot descriptor ServiceArguments +#define SC_UNO_SOURCENAME "SourceName" +#define SC_UNO_OBJECTNAME "ObjectName" +#define SC_UNO_USERNAME "UserName" +#define SC_UNO_PASSWORD "Password" // range selection #define SC_UNONAME_INITVAL "InitialValue" diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 66ac3a4bedbb..7d1dd85c0a25 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -784,13 +784,10 @@ bool ScDPObject::IsDimNameInUse(const OUString& rName) const if (!xPropSet.is()) continue; - Any any = xPropSet->getPropertyValue(OUString::createFromAscii(SC_UNO_LAYOUTNAME)); - OUString aLayoutName; - if (any >>= aLayoutName) - { - if (aLayoutName.equalsIgnoreAsciiCase(rName)) - return true; - } + OUString aLayoutName = ScUnoHelpFunctions::GetStringProperty( + xPropSet, OUString::createFromAscii(SC_UNO_LAYOUTNAME), OUString()); + if (aLayoutName.equalsIgnoreAsciiCase(rName)) + return true; } return false; } diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index 7ecdc3d34702..401d9b396bc0 100644 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -451,14 +451,12 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS if ( xLevNam.is() && xLevRes.is() ) { String aName = xLevNam->getName(); - OUString aCaption = aName; // Caption equals the field name by default. Reference<XPropertySet> xPropSet(xLevel, UNO_QUERY); - if (xPropSet.is()) - { - Any any = xPropSet->getPropertyValue( - OUString::createFromAscii(SC_UNO_LAYOUTNAME)); - any >>= aCaption; - } + // Caption equals the field name by default. + // #i108948# use ScUnoHelpFunctions::GetStringProperty, because + // LayoutName is new and may not be present in external implementation + OUString aCaption = ScUnoHelpFunctions::GetStringProperty( xPropSet, + OUString::createFromAscii(SC_UNO_LAYOUTNAME), aName ); bool bRowFieldHasMember = false; switch ( eDimOrient ) diff --git a/sc/source/core/tool/hints.cxx b/sc/source/core/tool/hints.cxx index e2bcb11fc573..b2a8266705c7 100644 --- a/sc/source/core/tool/hints.cxx +++ b/sc/source/core/tool/hints.cxx @@ -40,6 +40,7 @@ TYPEINIT1(ScPointerChangedHint, SfxHint); TYPEINIT1(ScLinkRefreshedHint, SfxHint); TYPEINIT1(ScAutoStyleHint, SfxHint); TYPEINIT1(ScDBRangeRefreshedHint, SfxHint); +TYPEINIT1(ScDataPilotModifiedHint, SfxHint); // ----------------------------------------------------------------------- // ScPaintHint - Angabe, was neu gezeichnet werden muss @@ -150,3 +151,12 @@ ScDBRangeRefreshedHint::~ScDBRangeRefreshedHint() } +ScDataPilotModifiedHint::ScDataPilotModifiedHint( const String& rName ) + : maName(rName) +{ +} +ScDataPilotModifiedHint::~ScDataPilotModifiedHint() +{ +} + + diff --git a/sc/source/filter/xml/xmldpimp.cxx b/sc/source/filter/xml/xmldpimp.cxx index 580dd2ee0791..01dae48f6d84 100644 --- a/sc/source/filter/xml/xmldpimp.cxx +++ b/sc/source/filter/xml/xmldpimp.cxx @@ -428,7 +428,7 @@ void ScXMLDataPilotTableContext::EndElement() break; case SERVICE : { - ScDPServiceDesc aServiceDesk(sServiceName, sServiceSourceObject, sServiceSourceName, + ScDPServiceDesc aServiceDesk(sServiceName, sServiceSourceName, sServiceSourceObject, sServiceUsername, sServicePassword); pDPObject->SetServiceData(aServiceDesk); } diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 1633af000b51..2053cebc8ce5 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -56,6 +56,7 @@ #include "attrib.hxx" #include "drwlayer.hxx" #include "dpshttab.hxx" +#include "hints.hxx" // ----------------------------------------------------------------- @@ -1403,7 +1404,12 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb delete pUndoDPObj; if (bDone) + { + // notify API objects + if (pDestObj) + pDoc->BroadcastUno( ScDataPilotModifiedHint( pDestObj->GetName() ) ); aModificator.SetDocumentModified(); + } if ( nErrId && !bApi ) rDocShell.ErrorMessage( nErrId ); diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx index 2ed65d5db6f5..d550d54f1aea 100644 --- a/sc/source/ui/undo/undodat.cxx +++ b/sc/source/ui/undo/undodat.cxx @@ -50,6 +50,7 @@ #include "olinefun.hxx" #include "dpobject.hxx" #include "attrib.hxx" +#include "hints.hxx" #include "sc.hrc" // ----------------------------------------------------------------------- @@ -1902,6 +1903,12 @@ void __EXPORT ScUndoDataPilot::Undo() //! set current sheet } + if (pNewDPObject) + { + // notify API objects + pDoc->BroadcastUno( ScDataPilotModifiedHint( pNewDPObject->GetName() ) ); + } + EndUndo(); } diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index b8a751669e6f..8654de8a429e 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -118,61 +118,6 @@ template< typename T > return aResult; } -::std::vector< ::rtl::OUString > lcl_getRangeRepresentationsFromDataSource( - const uno::Reference< chart2::data::XDataSource > & xDataSource ) -{ - ::std::vector< ::rtl::OUString > aResult; - if( xDataSource.is()) - { - uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences( - xDataSource->getDataSequences()); - const sal_Int32 nCount( aSequences.getLength()); - for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) - { - if( aSequences[nIdx].is() ) - { - // first: label - uno::Reference< chart2::data::XDataSequence > xSeq( aSequences[nIdx]->getLabel()); - if( xSeq.is()) - aResult.push_back( xSeq->getSourceRangeRepresentation()); - // then: values - xSeq.set( aSequences[nIdx]->getValues()); - if( xSeq.is()) - aResult.push_back( xSeq->getSourceRangeRepresentation()); - } - } - } - return aResult; -} - -uno::Reference< chart2::data::XLabeledDataSequence > lcl_getCategoriesFromDataSource( - const uno::Reference< chart2::data::XDataSource > & xDataSource ) -{ - uno::Reference< chart2::data::XLabeledDataSequence > xResult; - if( xDataSource.is()) - { - uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences( - xDataSource->getDataSequences()); - const sal_Int32 nCount( aSequences.getLength()); - for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) - { - if( aSequences[nIdx].is() ) - { - uno::Reference< beans::XPropertySet > xSeqProp( aSequences[nIdx]->getValues(), uno::UNO_QUERY ); - ::rtl::OUString aRole; - if( xSeqProp.is() && - (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) && - aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) ) - { - xResult.set( aSequences[nIdx] ); - break; - } - } - } - } - return xResult; -} - struct lcl_appendTableNumber : public ::std::unary_function< SCTAB, void > { lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) : @@ -214,173 +159,290 @@ uno::Reference< sheet::XSpreadsheetDocument > lcl_GetSpreadSheetDocument( ScDocu // ============================================================================ -class Chart2PositionMap +namespace { + +struct DeleteInstance : public unary_function<FormulaToken*, void> { -public: - Chart2PositionMap(SCCOL nColCount, SCROW nRowCount, - bool bColAdd, bool bRowAdd, Table& rCols); - ~Chart2PositionMap(); + void operator() (FormulaToken* p) const + { + delete p; + } +}; - SCCOL getColCount() const { return static_cast<SCCOL>(maColHeaders.size()); } - SCROW getRowCount() const { return static_cast<SCROW>(maRowHeaders.size()); } +} - const FormulaToken* getColHeaderPosition(SCCOL nChartCol) const; - const FormulaToken* getRowHeaderPosition(SCROW nChartRow) const; +struct TokenTable +{ + SCROW mnRowCount; + SCCOL mnColCount; + vector<FormulaToken*> maTokens; - vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const; - vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const; + void init( SCCOL nColCount, SCROW nRowCount ) + { + mnColCount = nColCount; + mnRowCount = nRowCount; + maTokens.reserve(mnColCount*mnRowCount); + } + void clear() + { + for_each(maTokens.begin(), maTokens.end(), DeleteInstance()); + } + void push_back( FormulaToken* pToken ) + { + maTokens.push_back( pToken ); + DBG_ASSERT( maTokens.size()<= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too much tokens" ); + } -private: sal_uInt32 getIndex(SCCOL nCol, SCROW nRow) const { - return static_cast<sal_uInt32>(nCol*getRowCount() + nRow); + DBG_ASSERT( nCol<mnColCount, "wrong column index" ); + DBG_ASSERT( nRow<mnRowCount, "wrong row index" ); + sal_uInt32 nRet = static_cast<sal_uInt32>(nCol*mnRowCount + nRow); + DBG_ASSERT( maTokens.size()>= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too few tokens" ); + return nRet; } -private: - vector<FormulaToken*> maRowHeaders; - vector<FormulaToken*> maColHeaders; - vector<FormulaToken*> maData; + vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const; + vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const; + vector<ScSharedTokenRef>* getAllRanges() const; }; -Chart2PositionMap::Chart2PositionMap(SCCOL nColCount, SCROW nRowCount, - bool bColAdd, bool bRowAdd, Table& rCols) +vector<ScSharedTokenRef>* TokenTable::getColRanges(SCCOL nCol) const { - // bColAdd is true when the first column serves as a row header. Likewise, - // when bRowAdd is true the first row serves as a column header. + if (nCol >= mnColCount) + return NULL; + if( mnRowCount<=0 ) + return NULL; - maColHeaders.reserve(nColCount); - maRowHeaders.reserve(nRowCount); - maData.reserve(nColCount*nRowCount); + auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); + sal_uInt32 nLast = getIndex(nCol, mnRowCount-1); + for (sal_uInt32 i = getIndex(nCol, 0); i <= nLast; ++i) + { + FormulaToken* p = maTokens[i]; + if (!p) + continue; - Table* pCol = static_cast<Table*>(rCols.First()); - FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First()); + ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone())); + ScRefTokenHelper::join(*pTokens, pCopy); + } + return pTokens.release(); +} - if (bRowAdd) - pPos = static_cast<FormulaToken*>(pCol->Next()); +vector<ScSharedTokenRef>* TokenTable::getRowRanges(SCROW nRow) const +{ + if (nRow >= mnRowCount) + return NULL; + if( mnColCount<=0 ) + return NULL; - if (bColAdd) + auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); + sal_uInt32 nLast = getIndex(mnColCount-1, nRow); + for (sal_uInt32 i = getIndex(0, nRow); i <= nLast; i += mnRowCount) { - // 1st column as a row header. - for (SCROW nRow = 0; nRow < nRowCount; ++nRow) - { - maRowHeaders.push_back(pPos); - pPos = static_cast<FormulaToken*>(pCol->Next()); - } - pCol = static_cast<Table*>(rCols.Next()); // move to the next column. + FormulaToken* p = maTokens[i]; + if (!p) + continue; + + ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); + ScRefTokenHelper::join(*pTokens, p2); } - else + return pTokens.release(); +} + +vector<ScSharedTokenRef>* TokenTable::getAllRanges() const +{ + auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); + sal_uInt32 nStop = mnColCount*mnRowCount; + for (sal_uInt32 i = 0; i < nStop; i++) { - for (SCROW nRow = 0; nRow < nRowCount; ++nRow) - { - // Make a copy. - maRowHeaders.push_back(pPos ? pPos->Clone() : NULL); - pPos = static_cast<FormulaToken*>(pCol->Next()); - } + FormulaToken* p = maTokens[i]; + if (!p) + continue; + + ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); + ScRefTokenHelper::join(*pTokens, p2); } + return pTokens.release(); +} + +// ============================================================================ + +class Chart2PositionMap +{ +public: + Chart2PositionMap(SCCOL nColCount, SCROW nRowCount, + bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, + ScDocument* pDoc ); + ~Chart2PositionMap(); + + SCCOL getDataColCount() const { return mnDataColCount; } + SCROW getDataRowCount() const { return mnDataRowCount; } + + vector<ScSharedTokenRef>* getLeftUpperCornerRanges() const; + vector<ScSharedTokenRef>* getAllColHeaderRanges() const; + vector<ScSharedTokenRef>* getAllRowHeaderRanges() const; + + vector<ScSharedTokenRef>* getColHeaderRanges(SCCOL nChartCol) const; + vector<ScSharedTokenRef>* getRowHeaderRanges(SCROW nChartRow) const; + + vector<ScSharedTokenRef>* getDataColRanges(SCCOL nCol) const; + vector<ScSharedTokenRef>* getDataRowRanges(SCROW nRow) const; - // Data in columns and in column headers. - for (SCCOL nCol = 0; nCol < nColCount; ++nCol) +private: + SCCOL mnDataColCount; + SCROW mnDataRowCount; + + TokenTable maLeftUpperCorner; //nHeaderColCount*nHeaderRowCount + TokenTable maColHeaders; //mnDataColCount*nHeaderRowCount + TokenTable maRowHeaders; //nHeaderColCount*mnDataRowCount + TokenTable maData;//mnDataColCount*mnDataRowCount +}; + +Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount, SCROW nAllRowCount, + bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, ScDocument* pDoc) +{ + // if bFillRowHeader is true, at least the first column serves as a row header. + // If more than one column is pure text all the first pure text columns are used as header. + // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header. + // If more than one row is pure text all the first pure text rows are used as header. + + SCROW nHeaderRowCount = (bFillColumnHeader && nAllColCount && nAllRowCount) ? 1 : 0; + SCCOL nHeaderColCount = (bFillRowHeader && nAllColCount && nAllRowCount) ? 1 : 0; + + if( nHeaderColCount || nHeaderRowCount ) { - if (pCol) + const SCCOL nInitialHeaderColCount = nHeaderColCount; + //check whether there is more than one text column or row that should be added to the headers + SCROW nSmallestValueRowIndex = nAllRowCount; + bool bFoundValues = false; + bool bFoundAnything = false; + Table* pCol = static_cast<Table*>(rCols.First()); + for (SCCOL nCol = 0; !bFoundValues && nCol < nAllColCount; ++nCol) { - pPos = static_cast<FormulaToken*>(pCol->First()); - if (bRowAdd) - { - // 1st row as a column header. - maColHeaders.push_back(pPos); - pPos = static_cast<FormulaToken*>(pCol->Next()); - } - else - // Duplicate the 1st cell as a column header. - maColHeaders.push_back(pPos ? pPos->Clone() : NULL); - - for (SCROW nRow = 0; nRow < nRowCount; ++nRow) + if (pCol && nCol>=nHeaderColCount) { - maData.push_back(pPos); - pPos = static_cast<FormulaToken*>(pCol->Next()); + ScToken* pToken = static_cast<ScToken*>(pCol->First()); + for (SCROW nRow = 0; !bFoundValues && nRow < nSmallestValueRowIndex; ++nRow) + { + if (pToken && nRow>=nHeaderRowCount) + { + ScRange aRange; + bool bExternal = false; + StackVar eType = pToken->GetType(); + if( eType==svExternal || eType==svExternalSingleRef || eType==svExternalDoubleRef || eType==svExternalName ) + bExternal = true;//lllll todo correct? + ScSharedTokenRef pSharedToken(static_cast<ScToken*>(pToken->Clone())); + ScRefTokenHelper::getRangeFromToken(aRange, pSharedToken, bExternal ); + SCCOL nCol1=0, nCol2=0; + SCROW nRow1=0, nRow2=0; + SCTAB nTab1=0, nTab2=0; + aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + if (pDoc && pDoc->HasValueData( nCol1, nRow1, nTab1 )) + { + bFoundValues = bFoundAnything = true; + nSmallestValueRowIndex = std::min( nSmallestValueRowIndex, nRow ); + } + if( !bFoundAnything ) + { + if (pDoc && pDoc->HasData( nCol1, nRow1, nTab1 ) ) + bFoundAnything = true; + } + } + pToken = static_cast<ScToken*>(pCol->Next()); + } + if(!bFoundValues && nHeaderColCount>0) + nHeaderColCount++; } + pCol = static_cast<Table*>(rCols.Next()); } - else + if( bFoundAnything ) { - // the entire column is empty. - maColHeaders.push_back(NULL); - for (SCROW nRow = 0; nRow < nRowCount; ++nRow) - maData.push_back(NULL); + if(nHeaderRowCount>0) + { + if( bFoundValues ) + nHeaderRowCount = nSmallestValueRowIndex; + else if( nAllRowCount>1 ) + nHeaderRowCount = nAllRowCount-1; + } } - pCol = static_cast<Table*>(rCols.Next()); + else //if the cells are completely empty, just use single header rows and columns + nHeaderColCount = nInitialHeaderColCount; } -} -namespace { + mnDataColCount = nAllColCount - nHeaderColCount; + mnDataRowCount = nAllRowCount - nHeaderRowCount; -struct DeleteInstance : public unary_function<FormulaToken*, void> -{ - void operator() (FormulaToken* p) const + maLeftUpperCorner.init(nHeaderColCount,nHeaderRowCount); + maColHeaders.init(mnDataColCount,nHeaderRowCount); + maRowHeaders.init(nHeaderColCount,mnDataRowCount); + maData.init(mnDataColCount,mnDataRowCount); + + Table* pCol = static_cast<Table*>(rCols.First()); + FormulaToken* pToken = static_cast<FormulaToken*>(pCol->First()); + for (SCCOL nCol = 0; nCol < nAllColCount; ++nCol) { - delete p; - } -}; + if (pCol) + { + pToken = static_cast<FormulaToken*>(pCol->First()); + for (SCROW nRow = 0; nRow < nAllRowCount; ++nRow) + { + if( nCol < nHeaderColCount ) + { + if( nRow < nHeaderRowCount ) + maLeftUpperCorner.push_back(pToken); + else + maRowHeaders.push_back(pToken); + } + else if( nRow < nHeaderRowCount ) + maColHeaders.push_back(pToken); + else + maData.push_back(pToken); + pToken = static_cast<FormulaToken*>(pCol->Next()); + } + } + pCol = static_cast<Table*>(rCols.Next()); + } } Chart2PositionMap::~Chart2PositionMap() { - for_each(maColHeaders.begin(), maColHeaders.end(), DeleteInstance()); - for_each(maRowHeaders.begin(), maRowHeaders.end(), DeleteInstance()); - for_each(maData.begin(), maData.end(), DeleteInstance()); + maLeftUpperCorner.clear(); + maColHeaders.clear(); + maRowHeaders.clear(); + maData.clear(); } -const FormulaToken* Chart2PositionMap::getColHeaderPosition(SCCOL nCol) const +vector<ScSharedTokenRef>* Chart2PositionMap::getLeftUpperCornerRanges() const { - if (nCol < getColCount()) - return maColHeaders[nCol]; - return NULL; + return maLeftUpperCorner.getAllRanges(); } -const FormulaToken* Chart2PositionMap::getRowHeaderPosition(SCROW nRow) const +vector<ScSharedTokenRef>* Chart2PositionMap::getAllColHeaderRanges() const { - if (nRow < getRowCount()) - return maRowHeaders[nRow]; - return NULL; + return maColHeaders.getAllRanges(); } - -vector<ScSharedTokenRef>* Chart2PositionMap::getColRanges(SCCOL nCol) const +vector<ScSharedTokenRef>* Chart2PositionMap::getAllRowHeaderRanges() const { - if (nCol >= getColCount()) - return NULL; - - auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); - sal_uInt32 nStop = getIndex(nCol, getRowCount()); - for (sal_uInt32 i = getIndex(nCol, 0); i < nStop; ++i) - { - FormulaToken* p = maData[i]; - if (!p) - continue; - - ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone())); - ScRefTokenHelper::join(*pTokens, pCopy); - } - return pTokens.release(); + return maRowHeaders.getAllRanges(); } - -vector<ScSharedTokenRef>* Chart2PositionMap::getRowRanges(SCROW nRow) const +vector<ScSharedTokenRef>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol) const { - SCROW nRowCount = getRowCount(); - if (nRow >= nRowCount) - return NULL; + return maColHeaders.getColRanges( nCol); +} +vector<ScSharedTokenRef>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow) const +{ + return maRowHeaders.getRowRanges( nRow); +} - auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); - sal_uInt32 nStop = getIndex(getColCount(), nRow); - for (sal_uInt32 i = getIndex(0, nRow); i < nStop; i += nRowCount) - { - FormulaToken* p = maData[i]; - if (!p) - continue; +vector<ScSharedTokenRef>* Chart2PositionMap::getDataColRanges(SCCOL nCol) const +{ + return maData.getColRanges( nCol); +} - ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); - ScRefTokenHelper::join(*pTokens, p2); - } - return pTokens.release(); +vector<ScSharedTokenRef>* Chart2PositionMap::getDataRowRanges(SCROW nRow) const +{ + return maData.getRowRanges( nRow); } // ---------------------------------------------------------------------------- @@ -730,55 +792,20 @@ void Chart2Positioner::createPositionMap() pNewAddress.reset(NULL); pNewRowTable.reset(NULL); - bool bColAdd = mbRowHeaders; - bool bRowAdd = mbColHeaders; + bool bFillRowHeader = mbRowHeaders; + bool bFillColumnHeader = mbColHeaders; - SCSIZE nColCount = static_cast<SCSIZE>(pCols->Count()); - SCSIZE nRowCount = 0; + SCSIZE nAllColCount = static_cast<SCSIZE>(pCols->Count()); + SCSIZE nAllRowCount = 0; pCol = static_cast<Table*>(pCols->First()); if (pCol) { if (mbDummyUpperLeft) pCol->Insert(0, NULL); // Dummy fuer Beschriftung - nRowCount = static_cast<SCSIZE>(pCol->Count()); + nAllRowCount = static_cast<SCSIZE>(pCol->Count()); } - else - nRowCount = 0; - if (nColCount > 0 && bColAdd) - nColCount -= 1; - if (nRowCount > 0 && bRowAdd) - nRowCount -= 1; - - if (nColCount == 0 || nRowCount == 0) - { - ScComplexRefData aData; - ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front()); - if (pCols->Count() > 0) - pCol = static_cast<Table*>(pCols->First()); - else - { - pCol = new Table; - pCols->Insert(0, pCol); - } - nColCount = 1; - if (pCol->Count() > 0) - { - FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First()); - if (pPos) - { - delete pPos; - pCol->Replace(pCol->GetCurKey(), NULL); - } - } - else - pCol->Insert(0, NULL); - - nRowCount = 1; - bColAdd = false; - bRowAdd = false; - } - else + if( nAllColCount!=0 && nAllRowCount!=0 ) { if (bNoGlue) { @@ -796,8 +823,8 @@ void Chart2Positioner::createPositionMap() } mpPositionMap.reset( new Chart2PositionMap( - static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount), - bColAdd, bRowAdd, *pCols)); + static_cast<SCCOL>(nAllColCount), static_cast<SCROW>(nAllRowCount), + bFillRowHeader, bFillColumnHeader, *pCols, mpDoc)); // Destroy all column instances. for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next())) @@ -1021,639 +1048,44 @@ void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint return !aTokens.empty(); } -namespace { - -class RemoveHeaderFromRanges : public unary_function<ScSharedTokenRef, void> -{ -public: - RemoveHeaderFromRanges(const ScSharedTokenRef& rHeaderCell, bool bOrientCol) : - mpTokens(new vector<ScSharedTokenRef>), - mpHeaderCell(rHeaderCell), - mbOrientCol(bOrientCol) - { - } - - RemoveHeaderFromRanges(const RemoveHeaderFromRanges& r) : - mpTokens(r.mpTokens), - mpHeaderCell(r.mpHeaderCell), - mbOrientCol(r.mbOrientCol) - { - } - - void operator() (const ScSharedTokenRef& pRange) - { - if (!isContained(pRange)) - { - // header cell is not part of this range. Just add it to the - // range list and move on. - ScRefTokenHelper::join(*mpTokens, pRange); - return; - } - - // This range contains the header cell. - - ScComplexRefData aRange; - ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange); - const ScSingleRefData& s = aRange.Ref1; - const ScSingleRefData& e = aRange.Ref2; - const ScSingleRefData& h = mpHeaderCell->GetSingleRef(); - - if (equals(s, e)) - // This range *only* contains the header cell. Skip it. - return; - - if (s.nTab != e.nTab) - // 3D range has no business being here.... - return; - - if (mbOrientCol) - { - // column major - - if (s.nCol == e.nCol) - { - // single column range. - splitSingleColRange(pRange, s, e); - } - else - { - if (s.nCol == h.nCol) - { - // header cell is in the first column. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(s.nCol, e.nRow, s.nTab); - splitSingleColRange(pNew, r.Ref1, r.Ref2); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(s.nCol + 1, s.nRow, s.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - else if (e.nCol == h.nCol) - { - // header cell is in the last column. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(e.nCol, s.nRow, s.nTab); - splitSingleColRange(pNew, r.Ref1, r.Ref2); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(e.nCol - 1, e.nRow, e.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - else - { - // header cell is somewhere between the first and last columns. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(h.nCol - 1, e.nRow, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(h.nCol, s.nRow, s.nTab); - r.Ref2.InitAddress(h.nCol, e.nRow, e.nTab); - splitSingleColRange(pNew, r.Ref1, r.Ref2); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(h.nCol + 1, s.nRow, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - } - } - else - { - // row major - - if (s.nRow == e.nRow) - { - // Single row range. - splitSingleRowRange(pRange, s, e); - } - else - { - if (s.nRow == h.nRow) - { - // header cell is in the first row. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(e.nCol, s.nRow, s.nTab); - splitSingleRowRange(pNew, r.Ref1, r.Ref2); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(s.nCol, s.nRow + 1, s.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - else if (e.nRow == h.nRow) - { - // header cell is in the last row. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(s.nCol, e.nRow, s.nTab); - splitSingleRowRange(pNew, r.Ref1, r.Ref2); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(e.nCol, e.nRow - 1, e.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - else - { - // header cell is somewhere between the 1st and last rows. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(e.nCol, h.nRow - 1, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(s.nCol, h.nRow, s.nTab); - r.Ref2.InitAddress(e.nCol, h.nRow, e.nTab); - splitSingleRowRange(pNew, r.Ref1, r.Ref2); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(s.nCol, h.nRow + 1, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - } - } - } - - void getNewTokens(vector<ScSharedTokenRef>& rTokens) - { - mpTokens->swap(rTokens); - } - -private: - - void splitSingleColRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e) - { - const ScSingleRefData& h = mpHeaderCell->GetSingleRef(); - - if (equals(s, h)) - { - // header is at the top. - - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.nRow += 1; - ScRefTokenHelper::join(*mpTokens, pNew); - } - else if (equals(e, h)) - { - // header is at the bottom. - - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.nRow -= 1; - ScRefTokenHelper::join(*mpTokens, pNew); - } - else - { - // header is somewhere in the middle. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(h.nCol, h.nRow - 1, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(h.nCol, h.nRow + 1, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - } - - void splitSingleRowRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e) - { - const ScSingleRefData& h = mpHeaderCell->GetSingleRef(); - - if (equals(s, h)) - { - // header is at the top. - - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.nCol += 1; - ScRefTokenHelper::join(*mpTokens, pNew); - } - else if (equals(e, h)) - { - // header is at the bottom. - - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.nCol -= 1; - ScRefTokenHelper::join(*mpTokens, pNew); - } - else - { - // header is somewhere in the middle. - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref2.InitAddress(h.nCol - 1, h.nRow, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - - { - ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone())); - ScComplexRefData& r = pNew->GetDoubleRef(); - r.Ref1.InitAddress(h.nCol + 1, h.nRow, h.nTab); - ScRefTokenHelper::join(*mpTokens, pNew); - } - } - } - - /** - * Compare two single ref data for equality, but only compare their - * absolute cell addresses while ignoring flags and relative addresses. - */ - bool equals(const ScSingleRefData& r1, const ScSingleRefData& r2) const - { - return (r1.nCol == r2.nCol) && (r1.nRow == r2.nRow) && (r1.nTab == r2.nTab); - } - - bool isContained(const ScSharedTokenRef& pRange) - { - bool bExternal = ScRefTokenHelper::isExternalRef(mpHeaderCell); - if (bExternal != ScRefTokenHelper::isExternalRef(pRange)) - // internal vs external. - return false; - - if (bExternal) - { - if (pRange->GetIndex() != mpHeaderCell->GetIndex()) - // different external files. - return false; - - if (pRange->GetString() != mpHeaderCell->GetString()) - // different table. - return false; - } - - ScComplexRefData aRange; - ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange); - const ScSingleRefData& rCell = mpHeaderCell->GetSingleRef(); - - bool bRowContained = (aRange.Ref1.nRow <= rCell.nRow) && (rCell.nRow <= aRange.Ref2.nRow); - bool bColContained = (aRange.Ref1.nCol <= rCell.nCol) && (rCell.nCol <= aRange.Ref2.nCol); - bool bTabContained = (aRange.Ref1.nTab <= rCell.nTab) && (rCell.nTab <= aRange.Ref2.nTab); - - return (bRowContained && bColContained && bTabContained); - } - -private: - shared_ptr< vector<ScSharedTokenRef> > mpTokens; - - /** - * Stores header cell position. Must be a single ref token i.e. either - * ScSingleRefToken or ScExternalSingleRefToken. - */ - ScSharedTokenRef mpHeaderCell; - - bool mbOrientCol; -}; - -} - -static void lcl_removeHeaderFromRanges(vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& rHeaderCell, bool bOrientCol) -{ - RemoveHeaderFromRanges func(rHeaderCell, bOrientCol); - func = for_each(rTokens.begin(), rTokens.end(), func); - func.getNewTokens(rTokens); -} - -uno::Reference< chart2::data::XDataSource> SAL_CALL -ScChart2DataProvider::createDataSource( - const uno::Sequence< beans::PropertyValue >& aArguments ) - throw( lang::IllegalArgumentException, uno::RuntimeException) -{ - ScUnoGuard aGuard; - if ( ! m_pDocument ) - throw uno::RuntimeException(); - - uno::Reference< chart2::data::XDataSource> xResult; - bool bLabel = true; - bool bOrientCol = true; - ::rtl::OUString aRangeRepresentation; - uno::Sequence< sal_Int32 > aSequenceMapping; - for(sal_Int32 i = 0; i < aArguments.getLength(); ++i) - { - rtl::OUString sName(aArguments[i].Name); - if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource"))) - { - chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS; - if( ! (aArguments[i].Value >>= eSource)) - { - sal_Int32 nSource(0); - if( aArguments[i].Value >>= nSource ) - eSource = (static_cast< chart::ChartDataRowSource >( nSource )); - } - bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS); - } - else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel"))) - { - bLabel = ::cppu::any2bool(aArguments[i].Value); - } - else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) - { - aArguments[i].Value >>= aRangeRepresentation; - } - else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping"))) - { - aArguments[i].Value >>= aSequenceMapping; - } - } - - vector<ScSharedTokenRef> aRefTokens; - ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); - if (aRefTokens.empty()) - // Invalid range representation. Bail out. - throw lang::IllegalArgumentException(); - - if (bLabel) - addUpperLeftCornerIfMissing(aRefTokens); - - bool bColHeaders = (bOrientCol ? bLabel : false ); - bool bRowHeaders = (bOrientCol ? false : bLabel ); - - Chart2Positioner aChPositioner(m_pDocument, aRefTokens); - aChPositioner.setHeaders(bColHeaders, bRowHeaders); - - const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap(); - if (!pChartMap) - // No chart position map instance. Bail out. - return xResult; - - ScChart2DataSource* pDS = NULL; - std::list < ScChart2LabeledDataSequence* > aSeqs; - - // Fill Categories - - ScChart2LabeledDataSequence* pHeader = NULL; - if (bOrientCol ? aChPositioner.hasRowHeaders() : aChPositioner.hasColHeaders()) - { - pHeader = new ScChart2LabeledDataSequence(m_pDocument); - sal_Int32 nCount = static_cast< sal_Int32 >( bOrientCol ? pChartMap->getRowCount() : pChartMap->getColCount() ); - vector<ScSharedTokenRef> aRefTokens2; - ScSharedTokenRef pLabelToken; - for (sal_Int32 i = 0; i < nCount; ++i) - { - const FormulaToken* pPos = bOrientCol ? - pChartMap->getRowHeaderPosition(static_cast<SCROW>(i)) : - pChartMap->getColHeaderPosition(static_cast<SCCOL>(i)); - if (pPos) - { - ScSharedTokenRef p(static_cast<ScToken*>(pPos->Clone())); - ScRefTokenHelper::join(aRefTokens2, p); - if (!pLabelToken) - { - pLabelToken = p; - StackVar eType = pLabelToken->GetType(); - if (eType == svSingleRef || eType == svExternalSingleRef) - { - ScSingleRefData& r = pLabelToken->GetSingleRef(); - if (bOrientCol) - r.nRow -= 1; - else - r.nCol -= 1; - } - } - } - } - if (pLabelToken) - { - if (bLabel) - { - auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); - pTokens->push_back(pLabelToken); - Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells)); - Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY); - if (xLabelProps.is()) - xLabelProps->setPropertyValue( - OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)), - uno::makeAny(OUString(RTL_CONSTASCII_USTRINGPARAM("label")))); - pHeader->setLabel(xLabelSeq); - } - else - ScRefTokenHelper::join(aRefTokens2, pLabelToken); - } - auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); - pTokens->swap(aRefTokens2); - uno::Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells) ); - pHeader->setValues(xSeq); - } - if (pHeader) - aSeqs.push_back(pHeader); - - // Fill Serieses with Labels - - sal_Int32 nCount = bOrientCol ? pChartMap->getColCount() : pChartMap->getRowCount(); - for (sal_Int32 i = 0; i < nCount; ++i) - { - ScChart2LabeledDataSequence* pLabeled = new ScChart2LabeledDataSequence(m_pDocument); - uno::Reference < chart2::data::XDataSequence > xLabelSeq; - auto_ptr< vector<ScSharedTokenRef> > pRanges(NULL); - if (bOrientCol) - pRanges.reset(pChartMap->getColRanges(static_cast<SCCOL>(i))); - else - pRanges.reset(pChartMap->getRowRanges(static_cast<SCROW>(i))); - - ScSharedTokenRef pHeaderCell; - if (bOrientCol) - { - const FormulaToken* p = pChartMap->getColHeaderPosition(static_cast<SCCOL>(i)); - if (p) - pHeaderCell.reset(static_cast<ScToken*>(p->Clone())); - } - else - { - const FormulaToken* p = pChartMap->getRowHeaderPosition(static_cast<SCROW>(i)); - if (p) - pHeaderCell.reset(static_cast<ScToken*>(p->Clone())); - } - - if (bLabel) - { - if (!pHeaderCell && pRanges.get() && !pRanges->empty()) - { - const ScSharedTokenRef& p = pRanges->front(); - if (p && ScRefTokenHelper::isRef(p)) - { - // Take the first cell in the range as the header position. - ScSingleRefData aData = p->GetSingleRef(); - bool bExternal = ScRefTokenHelper::isExternalRef(p); - if (bExternal) - { - sal_uInt16 nFileId = p->GetIndex(); - const String& rTabName = p->GetString(); - pHeaderCell.reset(new ScExternalSingleRefToken(nFileId, rTabName, aData)); - } - else - pHeaderCell.reset(new ScSingleRefToken(aData)); - } - } - if (pHeaderCell) - { - auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); - pTokens->reserve(1); - pTokens->push_back(pHeaderCell); - xLabelSeq.set(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells)); - uno::Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY); - if (xLabelProps.is()) - xLabelProps->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)), uno::makeAny(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("label")))); - - // remove Header from Ranges - lcl_removeHeaderFromRanges(*pRanges, pHeaderCell, bOrientCol); - } - } - else - { - if (pHeaderCell) - ScRefTokenHelper::join(*pRanges, pHeaderCell); - } - - // FIXME: if there are no labels the column or row name should be taken - - uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(m_pDocument, this, pRanges.release(), m_bIncludeHiddenCells)); - - pLabeled->setValues(xSeq); - pLabeled->setLabel(xLabelSeq); - - aSeqs.push_back(pLabeled); - } - - pDS = new ScChart2DataSource(m_pDocument); - std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin()); - std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end()); - - //reorder labeled sequences according to aSequenceMapping - std::vector< ScChart2LabeledDataSequence* > aSeqVector; - while(aItr != aEndItr) - { - aSeqVector.push_back(*aItr); - ++aItr; - } - - std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap; - for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ ) - { - // note: assuming that the values in the sequence mapping are always non-negative - std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] )); - if( nOldIndex < aSeqVector.size() ) - { - pDS->AddLabeledSequence( aSeqVector[nOldIndex] ); - aSeqVector[nOldIndex] = 0; - } - - } - - std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin()); - std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end()); - while(aVectorItr != aVectorEndItr) - { - if(*aVectorItr) - pDS->AddLabeledSequence(*aVectorItr); - ++aVectorItr; - } - - xResult.set( pDS ); - return xResult; -} - namespace { -bool lcl_HasCategories( - const uno::Reference< chart2::data::XDataSource >& xDataSource, - bool & rOutHasCategories ) +ScChart2LabeledDataSequence* lcl_createScChart2DataSequenceFromTokens( auto_ptr< vector<ScSharedTokenRef> > pValueTokens, auto_ptr< vector<ScSharedTokenRef> > pLabelTokens, + ScDocument* pDoc, const uno::Reference < chart2::data::XDataProvider >& xDP, bool bIncludeHiddenCells ) { - bool bResult = false; - uno::Reference< chart2::data::XLabeledDataSequence > xCategories( - lcl_getCategoriesFromDataSource( xDataSource )); - if( xCategories.is()) + ScChart2LabeledDataSequence* pRet = 0; + bool bHasValues = pValueTokens.get() && !pValueTokens->empty(); + bool bHasLabel = pLabelTokens.get() && !pLabelTokens->empty(); + if( bHasValues || bHasLabel ) { - uno::Reference< lang::XServiceInfo > xValues( xCategories->getValues(), uno::UNO_QUERY ); - if (xValues.is()) + pRet = new ScChart2LabeledDataSequence(pDoc); + if(bHasValues) { - rOutHasCategories = xValues->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence")); - bResult = true; + uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(pDoc, xDP, pValueTokens.release(), bIncludeHiddenCells)); + pRet->setValues(xSeq); } - } - return bResult; -} - -bool lcl_HasFirstCellAsLabel( - const uno::Reference< chart2::data::XDataSource >& xDataSource, - bool & rOutHasFirstCellAsLabel ) -{ - bool bResult = false; - if( xDataSource.is()) - { - uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences( - xDataSource->getDataSequences()); - const sal_Int32 nCount( aSequences.getLength()); - if (nCount > 0 && aSequences[nCount - 1].is() ) + if(bHasLabel) { - uno::Reference< lang::XServiceInfo > xLabel( aSequences[nCount - 1]->getLabel(), uno::UNO_QUERY ); // take the last sequence, because the first has no label if it is also created - if (xLabel.is()) - { - rOutHasFirstCellAsLabel = xLabel->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence")); - bResult = true; - } + uno::Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(pDoc, xDP, pLabelTokens.release(), bIncludeHiddenCells)); + pRet->setLabel(xLabelSeq); } } - return bResult; + return pRet; } -} // anonymous namespace - -bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens) +//---------------------------------------------------- +/** + * Check the current list of reference tokens, and add the upper left + * corner of the minimum range that encloses all ranges if certain + * conditions are met. + * + * @param rRefTokens list of reference tokens + * + * @return true if the corner was added, false otherwise. + */ +bool lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens, + SCROW nCornerRowCount=1, SCCOL nCornerColumnCount=1) { using ::std::max; using ::std::min; @@ -1834,13 +1266,13 @@ bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& // The corner cell is contained. return false; - if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow) + if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow) bRight = true; - if (rData.nCol == nMinCol && rData.nRow == nMinRow+1) + if (rData.nCol == nMinCol && rData.nRow == nMinRow+nCornerRowCount) bBottom = true; - if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow+1) + if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow+nCornerRowCount) bDiagonal = true; } break; @@ -1855,16 +1287,16 @@ bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& // The corner cell is contained. return false; - if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol && + if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol && r1.nRow <= nMinRow && nMinRow <= r2.nRow) bRight = true; if (r1.nCol <= nMinCol && nMinCol <= r2.nCol && - r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow) + r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow) bBottom = true; - if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol && - r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow) + if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol && + r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow) bDiagonal = true; } break; @@ -1934,22 +1366,194 @@ bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& aData.nRow = nMinRow; aData.nTab = nTab; - if (bExternal) + if( nCornerRowCount==1 && nCornerColumnCount==1 ) { - ScSharedTokenRef pCorner( - new ScExternalSingleRefToken(nFileId, aExtTabName, aData)); - ScRefTokenHelper::join(rRefTokens, pCorner); + if (bExternal) + { + ScSharedTokenRef pCorner( + new ScExternalSingleRefToken(nFileId, aExtTabName, aData)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } + else + { + ScSharedTokenRef pCorner(new ScSingleRefToken(aData)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } } else { - ScSharedTokenRef pCorner(new ScSingleRefToken(aData)); - ScRefTokenHelper::join(rRefTokens, pCorner); + ScSingleRefData aDataEnd(aData); + aDataEnd.nCol += (nCornerColumnCount-1); + aDataEnd.nRow += (nCornerRowCount-1); + ScComplexRefData r; + r.Ref1=aData; + r.Ref2=aDataEnd; + if (bExternal) + { + ScSharedTokenRef pCorner( + new ScExternalDoubleRefToken(nFileId, aExtTabName, r)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } + else + { + ScSharedTokenRef pCorner(new ScDoubleRefToken(r)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } } return true; } -namespace { +} + +uno::Reference< chart2::data::XDataSource> SAL_CALL +ScChart2DataProvider::createDataSource( + const uno::Sequence< beans::PropertyValue >& aArguments ) + throw( lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( ! m_pDocument ) + throw uno::RuntimeException(); + + uno::Reference< chart2::data::XDataSource> xResult; + bool bLabel = true; + bool bCategories = false; + bool bOrientCol = true; + ::rtl::OUString aRangeRepresentation; + uno::Sequence< sal_Int32 > aSequenceMapping; + for(sal_Int32 i = 0; i < aArguments.getLength(); ++i) + { + rtl::OUString sName(aArguments[i].Name); + if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource"))) + { + chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS; + if( ! (aArguments[i].Value >>= eSource)) + { + sal_Int32 nSource(0); + if( aArguments[i].Value >>= nSource ) + eSource = (static_cast< chart::ChartDataRowSource >( nSource )); + } + bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS); + } + else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel"))) + { + bLabel = ::cppu::any2bool(aArguments[i].Value); + } + else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories"))) + { + bCategories = ::cppu::any2bool(aArguments[i].Value); + } + else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) + { + aArguments[i].Value >>= aRangeRepresentation; + } + else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping"))) + { + aArguments[i].Value >>= aSequenceMapping; + } + } + + vector<ScSharedTokenRef> aRefTokens; + ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); + if (aRefTokens.empty()) + // Invalid range representation. Bail out. + throw lang::IllegalArgumentException(); + + if (bLabel) + lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669# + + bool bColHeaders = (bOrientCol ? bLabel : bCategories ); + bool bRowHeaders = (bOrientCol ? bCategories : bLabel ); + + Chart2Positioner aChPositioner(m_pDocument, aRefTokens); + aChPositioner.setHeaders(bColHeaders, bRowHeaders); + + const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap(); + if (!pChartMap) + // No chart position map instance. Bail out. + return xResult; + + ScChart2DataSource* pDS = NULL; + std::list < ScChart2LabeledDataSequence* > aSeqs; + + // Fill Categories + if( bCategories ) + { + auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL); + if (bOrientCol) + pValueTokens.reset(pChartMap->getAllRowHeaderRanges()); + else + pValueTokens.reset(pChartMap->getAllColHeaderRanges()); + + auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL); + pLabelTokens.reset(pChartMap->getLeftUpperCornerRanges()); + + ScChart2LabeledDataSequence* pCategories = lcl_createScChart2DataSequenceFromTokens( pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells );//ownership of pointers is transfered! + if( pCategories ) + aSeqs.push_back(pCategories); + } + + // Fill Serieses (values and label) + sal_Int32 nCount = bOrientCol ? pChartMap->getDataColCount() : pChartMap->getDataRowCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL); + auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL); + if (bOrientCol) + { + pValueTokens.reset(pChartMap->getDataColRanges(static_cast<SCCOL>(i))); + pLabelTokens.reset(pChartMap->getColHeaderRanges(static_cast<SCCOL>(i))); + } + else + { + pValueTokens.reset(pChartMap->getDataRowRanges(static_cast<SCROW>(i))); + pLabelTokens.reset(pChartMap->getRowHeaderRanges(static_cast<SCROW>(i))); + } + ScChart2LabeledDataSequence* pChartSeries = lcl_createScChart2DataSequenceFromTokens( pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered! + if( pChartSeries ) + aSeqs.push_back(pChartSeries); + } + + pDS = new ScChart2DataSource(m_pDocument); + std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin()); + std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end()); + + //reorder labeled sequences according to aSequenceMapping + std::vector< ScChart2LabeledDataSequence* > aSeqVector; + while(aItr != aEndItr) + { + aSeqVector.push_back(*aItr); + ++aItr; + } + + std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap; + for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ ) + { + // note: assuming that the values in the sequence mapping are always non-negative + std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] )); + if( nOldIndex < aSeqVector.size() ) + { + pDS->AddLabeledSequence( aSeqVector[nOldIndex] ); + aSeqVector[nOldIndex] = 0; + } + + } + + std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin()); + std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end()); + while(aVectorItr != aVectorEndItr) + { + if(*aVectorItr) + pDS->AddLabeledSequence(*aVectorItr); + ++aVectorItr; + } + + xResult.set( pDS ); + return xResult; +} + +namespace +{ /** * Function object to create a list of table numbers from a token list. @@ -1984,8 +1588,134 @@ private: shared_ptr< list<SCTAB> > mpTabNumList; }; +class RangeAnalyzer +{ +public: + RangeAnalyzer(); + void initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens ); + void analyzeRange( sal_Int32& rnDataInRows, sal_Int32& rnDataInCols, + bool& rbRowSourceAmbiguous ) const; + bool inSameSingleRow( RangeAnalyzer& rOther ); + bool inSameSingleColumn( RangeAnalyzer& rOther ); + SCROW getRowCount() { return mnRowCount; } + SCCOL getColumnCount() { return mnColumnCount; } + +private: + bool mbEmpty; + bool mbAmbiguous; + SCROW mnRowCount; + SCCOL mnColumnCount; + + SCCOL mnStartColumn; + SCROW mnStartRow; +}; + +RangeAnalyzer::RangeAnalyzer() + : mbEmpty(true) + , mbAmbiguous(false) + , mnRowCount(0) + , mnColumnCount(0) + , mnStartColumn(-1) + , mnStartRow(-1) +{ } +void RangeAnalyzer::initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens ) +{ + mnRowCount=0; + mnColumnCount=0; + mnStartColumn = -1; + mnStartRow = -1; + mbAmbiguous=false; + if( rTokens.empty() ) + { + mbEmpty=true; + return; + } + mbEmpty=false; + + vector<ScSharedTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end(); + for (; itr != itrEnd ; ++itr) + { + ScSharedTokenRef aRefToken = *itr; + StackVar eVar = aRefToken->GetType(); + if (eVar == svDoubleRef || eVar == svExternalDoubleRef) + { + const ScComplexRefData& r = aRefToken->GetDoubleRef(); + if (r.Ref1.nTab == r.Ref2.nTab) + { + mnColumnCount = std::max<SCCOL>( mnColumnCount, static_cast<SCCOL>(abs(r.Ref2.nCol - r.Ref1.nCol)+1) ); + mnRowCount = std::max<SCROW>( mnRowCount, static_cast<SCROW>(abs(r.Ref2.nRow - r.Ref1.nRow)+1) ); + if( mnStartColumn == -1 ) + { + mnStartColumn = r.Ref1.nCol; + mnStartRow = r.Ref1.nRow; + } + else + { + if( mnStartColumn != r.Ref1.nCol && mnStartRow != r.Ref1.nRow ) + mbAmbiguous=true; + } + } + else + mbAmbiguous=true; + } + else if (eVar == svSingleRef || eVar == svExternalSingleRef) + { + const ScSingleRefData& r = aRefToken->GetSingleRef(); + mnColumnCount = std::max<SCCOL>( mnColumnCount, 1); + mnRowCount = std::max<SCROW>( mnRowCount, 1); + if( mnStartColumn == -1 ) + { + mnStartColumn = r.nCol; + mnStartRow = r.nRow; + } + else + { + if( mnStartColumn != r.nCol && mnStartRow != r.nRow ) + mbAmbiguous=true; + } + } + else + mbAmbiguous=true; + } +} + +void RangeAnalyzer::analyzeRange( sal_Int32& rnDataInRows, + sal_Int32& rnDataInCols, + bool& rbRowSourceAmbiguous ) const +{ + if(!mbEmpty && !mbAmbiguous) + { + if( mnRowCount==1 && mnColumnCount>1 ) + ++rnDataInRows; + else if( mnColumnCount==1 && mnRowCount>1 ) + ++rnDataInCols; + else if( mnRowCount>1 && mnColumnCount>1 ) + rbRowSourceAmbiguous = true; + } + else if( !mbEmpty ) + rbRowSourceAmbiguous = true; +} + +bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer& rOther ) +{ + if( mnStartRow==rOther.mnStartRow && + mnRowCount==1 && rOther.mnRowCount==1 ) + return true; + return false; +} + +bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer& rOther ) +{ + if( mnStartColumn==rOther.mnStartColumn && + mnColumnCount==1 && rOther.mnColumnCount==1 ) + return true; + return false; +} + +} //end anonymous namespace + uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments( const uno::Reference< chart2::data::XDataSource >& xDataSource ) throw (uno::RuntimeException) @@ -1993,28 +1723,137 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum ::std::vector< beans::PropertyValue > aResult; bool bRowSourceDetected = false; bool bFirstCellAsLabel = false; - bool bHasCategories = true; + bool bHasCategories = false; ::rtl::OUString sRangeRep; + bool bHasCategoriesLabels = false; + vector<ScSharedTokenRef> aAllCategoriesValuesTokens; + vector<ScSharedTokenRef> aAllSeriesLabelTokens; + chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS; - vector<ScSharedTokenRef> aTokens; + vector<ScSharedTokenRef> aAllTokens; - // CellRangeRepresentation + // parse given data source and collect infos { ScUnoGuard aGuard; DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" ); - if(!m_pDocument) + if(!m_pDocument ||!xDataSource.is()) return lcl_VectorToSequence( aResult ); - detectRangesFromDataSource(aTokens, eRowSource, bRowSourceDetected, xDataSource); + sal_Int32 nDataInRows = 0; + sal_Int32 nDataInCols = 0; + bool bRowSourceAmbiguous = false; + + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); + const sal_Int32 nCount( aSequences.getLength()); + RangeAnalyzer aPrevLabel,aPrevValues; + for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) + { + Reference< chart2::data::XLabeledDataSequence > xLS(aSequences[nIdx]); + if( xLS.is() ) + { + bool bThisIsCategories = false; + if(!bHasCategories) + { + Reference< beans::XPropertySet > xSeqProp( xLS->getValues(), uno::UNO_QUERY ); + ::rtl::OUString aRole; + if( xSeqProp.is() && (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) && + aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) ) + bThisIsCategories = bHasCategories = true; + } + + RangeAnalyzer aLabel,aValues; + // label + Reference< chart2::data::XDataSequence > xLabel( xLS->getLabel()); + if( xLabel.is()) + { + bFirstCellAsLabel = true; + vector<ScSharedTokenRef> aTokens; + ScRefTokenHelper::compileRangeRepresentation( aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() ); + aLabel.initRangeAnalyzer(aTokens); + vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end(); + for (; itr != itrEnd; ++itr) + { + ScRefTokenHelper::join(aAllTokens, *itr); + if(!bThisIsCategories) + ScRefTokenHelper::join(aAllSeriesLabelTokens, *itr); + } + if(bThisIsCategories) + bHasCategoriesLabels=true; + } + // values + Reference< chart2::data::XDataSequence > xValues( xLS->getValues()); + if( xValues.is()) + { + vector<ScSharedTokenRef> aTokens; + ScRefTokenHelper::compileRangeRepresentation( aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() ); + aValues.initRangeAnalyzer(aTokens); + vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end(); + for (; itr != itrEnd; ++itr) + { + ScRefTokenHelper::join(aAllTokens, *itr); + if(bThisIsCategories) + ScRefTokenHelper::join(aAllCategoriesValuesTokens, *itr); + } + } + //detect row source + if(!bThisIsCategories || nCount==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available + { + if (!bRowSourceAmbiguous) + { + aValues.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous); + aLabel.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous); + if (nDataInRows > 1 && nDataInCols > 1) + bRowSourceAmbiguous = true; + else if( !bRowSourceAmbiguous && !nDataInRows && !nDataInCols ) + { + if( aValues.inSameSingleColumn( aLabel ) ) + nDataInCols++; + else if( aValues.inSameSingleRow( aLabel ) ) + nDataInRows++; + else + { + //#i86188# also detect a single column split into rows correctly + if( aValues.inSameSingleColumn( aPrevValues ) ) + nDataInRows++; + else if( aValues.inSameSingleRow( aPrevValues ) ) + nDataInCols++; + else if( aLabel.inSameSingleColumn( aPrevLabel ) ) + nDataInRows++; + else if( aLabel.inSameSingleRow( aPrevLabel ) ) + nDataInCols++; + } + } + } + } + aPrevValues=aValues; + aPrevLabel=aLabel; + } + } + + if (!bRowSourceAmbiguous) + { + bRowSourceDetected = true; + eRowSource = ( nDataInRows > 0 + ? chart::ChartDataRowSource_ROWS + : chart::ChartDataRowSource_COLUMNS ); + } + else + { + // set DataRowSource to the better of the two ambiguities + eRowSource = ( nDataInRows > nDataInCols + ? chart::ChartDataRowSource_ROWS + : chart::ChartDataRowSource_COLUMNS ); + } + } // TableNumberList { list<SCTAB> aTableNumList; InsertTabNumber func; - func = for_each(aTokens.begin(), aTokens.end(), func); + func = for_each(aAllTokens.begin(), aAllTokens.end(), func); func.getList(aTableNumList); aResult.push_back( beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1, @@ -2033,29 +1872,38 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum // HasCategories if( bRowSourceDetected ) { - if( lcl_HasCategories( xDataSource, bHasCategories )) - { - aResult.push_back( - beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1, - uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE )); - } + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1, + uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE )); } // FirstCellAsLabel if( bRowSourceDetected ) { - lcl_HasFirstCellAsLabel( xDataSource, bFirstCellAsLabel ); aResult.push_back( beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE )); } // Add the left upper corner to the range if it is missing. - if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories) - addUpperLeftCornerIfMissing(aTokens); + if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories && !bHasCategoriesLabels ) + { + RangeAnalyzer aTop,aLeft; + if( eRowSource==chart::ChartDataRowSource_COLUMNS ) + { + aTop.initRangeAnalyzer(aAllSeriesLabelTokens); + aLeft.initRangeAnalyzer(aAllCategoriesValuesTokens); + } + else + { + aTop.initRangeAnalyzer(aAllCategoriesValuesTokens); + aLeft.initRangeAnalyzer(aAllSeriesLabelTokens); + } + lcl_addUpperLeftCornerIfMissing(aAllTokens, aTop.getRowCount(), aLeft.getColumnCount());//e.g. #i91212# + } // Get range string. - lcl_convertTokensToString(sRangeRep, aTokens, m_pDocument); + lcl_convertTokensToString(sRangeRep, aAllTokens, m_pDocument); // add cell range property aResult.push_back( @@ -2270,91 +2118,6 @@ rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUS return aRet; } -namespace { - -class CollectRefTokens : public ::std::unary_function<ScSharedTokenRef, void> -{ -public: - CollectRefTokens() : - mpRefTokens(new vector<ScSharedTokenRef>()), - mnDataInRows(0), - mnDataInCols(0), - mbRowSourceAmbiguous(false) - { - } - - CollectRefTokens(const CollectRefTokens& r) : - mpRefTokens(r.mpRefTokens), - mnDataInRows(r.mnDataInRows), - mnDataInCols(r.mnDataInCols), - mbRowSourceAmbiguous(r.mbRowSourceAmbiguous) - { - } - - void operator() (const ScSharedTokenRef& rRefToken) - { - if (!mbRowSourceAmbiguous) - { - StackVar eVar = rRefToken->GetType(); - if (eVar == svDoubleRef || eVar == svExternalDoubleRef) - { - const ScComplexRefData& r = rRefToken->GetDoubleRef(); - mbRowSourceAmbiguous = r.Ref1.nTab != r.Ref2.nTab; - if (!mbRowSourceAmbiguous) - { - bool bColDiff = (r.Ref2.nCol - r.Ref1.nCol) != 0; - bool bRowDiff = (r.Ref2.nRow - r.Ref1.nRow) != 0; - - if (bColDiff && !bRowDiff) - ++mnDataInRows; - else if (bRowDiff && !bColDiff) - ++mnDataInCols; - else if (bRowDiff && bColDiff) - mbRowSourceAmbiguous = true; - - if (mnDataInRows > 0 && mnDataInCols > 0) - mbRowSourceAmbiguous = true; - } - } - } - - mpRefTokens->push_back(rRefToken); - } - - void appendTokens(vector<ScSharedTokenRef>& rTokens) - { - vector<ScSharedTokenRef> aNewTokens = rTokens; - vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end(); - for (; itr != itrEnd; ++itr) - ScRefTokenHelper::join(aNewTokens, *itr); - - rTokens.swap(aNewTokens); - } - - bool isRowSourceAmbiguous() const - { - return mbRowSourceAmbiguous; - } - - sal_uInt32 getDataInRows() const - { - return mnDataInRows; - } - - sal_uInt32 getDataInCols() const - { - return mnDataInCols; - } - -private: - shared_ptr< vector<ScSharedTokenRef> > mpRefTokens; - sal_uInt32 mnDataInRows; - sal_uInt32 mnDataInCols; - bool mbRowSourceAmbiguous; -}; - -} - // DataProvider XPropertySet ------------------------------------------------- uno::Reference< beans::XPropertySetInfo> SAL_CALL @@ -2437,53 +2200,6 @@ void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener( OSL_ENSURE( false, "Not yet implemented" ); } -void ScChart2DataProvider::detectRangesFromDataSource(vector<ScSharedTokenRef>& rRefTokens, - chart::ChartDataRowSource& rRowSource, - bool& rRowSourceDetected, - const Reference<chart2::data::XDataSource>& xDataSource) -{ - if (!m_pDocument) - return; - - sal_Int32 nDataInRows = 0; - sal_Int32 nDataInCols = 0; - bool bRowSourceAmbiguous = false; - - vector<OUString> aRangeReps = lcl_getRangeRepresentationsFromDataSource(xDataSource); - for (vector<OUString>::const_iterator itr = aRangeReps.begin(), itrEnd = aRangeReps.end(); - itr != itrEnd; ++itr) - { - const OUString& rRangeRep = *itr; - vector<ScSharedTokenRef> aTokens; - ScRefTokenHelper::compileRangeRepresentation(aTokens, rRangeRep, m_pDocument, m_pDocument->GetGrammar()); - - CollectRefTokens func; - func = for_each(aTokens.begin(), aTokens.end(), func); - func.appendTokens(rRefTokens); - bRowSourceAmbiguous = bRowSourceAmbiguous || func.isRowSourceAmbiguous(); - if (!bRowSourceAmbiguous) - { - nDataInRows += func.getDataInRows(); - nDataInCols += func.getDataInCols(); - } - } - - if (!bRowSourceAmbiguous) - { - rRowSourceDetected = true; - rRowSource = ( nDataInRows > 0 - ? chart::ChartDataRowSource_ROWS - : chart::ChartDataRowSource_COLUMNS ); - } - else - { - // set DataRowSource to the better of the two ambiguities - rRowSource = ( nDataInRows > nDataInCols - ? chart::ChartDataRowSource_ROWS - : chart::ChartDataRowSource_COLUMNS ); - } -} - // DataSource ================================================================ ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc) diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx index a921d1e125f2..ab94be3052e0 100644 --- a/sc/source/ui/unoobj/dapiuno.cxx +++ b/sc/source/ui/unoobj/dapiuno.cxx @@ -43,15 +43,19 @@ #include "unoguard.hxx" #include "dpobject.hxx" #include "dpshttab.hxx" +#include "dpsdbtab.hxx" #include "dpsave.hxx" #include "dbdocfun.hxx" #include "unonames.hxx" #include "dpgroup.hxx" #include "dpdimsave.hxx" +#include "hints.hxx" + #include <com/sun/star/sheet/XHierarchiesSupplier.hpp> #include <com/sun/star/sheet/XLevelsSupplier.hpp> #include <com/sun/star/sheet/XMembersSupplier.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sheet/DataImportMode.hpp> #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp> @@ -105,9 +109,12 @@ const SfxItemPropertyMapEntry* lcl_GetDataPilotDescriptorBaseMap() {MAP_CHAR_LEN(SC_UNO_COLGRAND), 0, &getBooleanCppuType(), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_DRILLDOWN), 0, &getBooleanCppuType(), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_IGNEMPROWS), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_IMPORTDESC), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_RPTEMPTY), 0, &getBooleanCppuType(), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_SERVICEARG), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_SHOWFILT), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_SOURCESERV), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, {0,0,0,0,0,0} }; return aDataPilotDescriptorBaseMap_Impl; @@ -261,8 +268,7 @@ ScDPObject* lcl_GetDPObject( ScDocShell* pDocShell, SCTAB nTab, const String& rN for (USHORT i=0; i<nCount; i++) { ScDPObject* pDPObj = (*pColl)[i]; - if ( pDPObj->IsSheetData() && - pDPObj->GetOutRange().aStart.Tab() == nTab && + if ( pDPObj->GetOutRange().aStart.Tab() == nTab && pDPObj->GetName() == rName ) return pDPObj; } @@ -344,7 +350,7 @@ ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByIndex_Impl( sal_Int32 nInd for (USHORT i=0; i<nCount; i++) { ScDPObject* pDPObj = (*pColl)[i]; - if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) { if ( nFound == nIndex ) { @@ -496,7 +502,7 @@ sal_Int32 SAL_CALL ScDataPilotTablesObj::getCount() throw(RuntimeException) for (USHORT i=0; i<nCount; i++) { ScDPObject* pDPObj = (*pColl)[i]; - if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) ++nFound; } return nFound; @@ -560,7 +566,7 @@ Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames() for (i=0; i<nCount; i++) { ScDPObject* pDPObj = (*pColl)[i]; - if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) ++nFound; } @@ -570,7 +576,7 @@ Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames() for (i=0; i<nCount; i++) { ScDPObject* pDPObj = (*pColl)[i]; - if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) pAry[nPos++] = pDPObj->GetName(); } @@ -598,8 +604,7 @@ sal_Bool SAL_CALL ScDataPilotTablesObj::hasByName( const OUString& aName ) //! allow all data sources!!! ScDPObject* pDPObj = (*pColl)[i]; - if ( pDPObj->IsSheetData() && - pDPObj->GetOutRange().aStart.Tab() == nTab && + if ( pDPObj->GetOutRange().aStart.Tab() == nTab && pDPObj->GetName() == aNamStr ) return TRUE; } @@ -696,11 +701,12 @@ CellRangeAddress SAL_CALL ScDataPilotDescriptorBase::getSourceRange() ScUnoGuard aGuard; ScDPObject* pDPObject(GetDPObject()); - if (!pDPObject || !pDPObject->IsSheetData()) + if (!pDPObject) throw RuntimeException(); CellRangeAddress aRet; - ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange ); + if (pDPObject->IsSheetData()) + ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange ); return aRet; } @@ -818,6 +824,99 @@ void SAL_CALL ScDataPilotDescriptorBase::setPropertyValue( const OUString& aProp { aNewData.SetDrillDown(::cppu::any2bool( aValue )); } + else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) ) + { + uno::Sequence<beans::PropertyValue> aArgSeq; + if ( aValue >>= aArgSeq ) + { + ScImportSourceDesc aImportDesc; + + const ScImportSourceDesc* pOldDesc = pDPObject->GetImportSourceDesc(); + if (pOldDesc) + aImportDesc = *pOldDesc; + + ScImportParam aParam; + ScImportDescriptor::FillImportParam( aParam, aArgSeq ); + + USHORT nNewType = sheet::DataImportMode_NONE; + if ( aParam.bImport ) + { + if ( aParam.bSql ) + nNewType = sheet::DataImportMode_SQL; + else if ( aParam.nType == ScDbQuery ) + nNewType = sheet::DataImportMode_QUERY; + else + nNewType = sheet::DataImportMode_TABLE; + } + aImportDesc.nType = nNewType; + aImportDesc.aDBName = aParam.aDBName; + aImportDesc.aObject = aParam.aStatement; + aImportDesc.bNative = aParam.bNative; + + pDPObject->SetImportDesc( aImportDesc ); + } + } + else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) ) + { + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + { + String aEmpty; + ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty); + + const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc(); + if (pOldDesc) + aServiceDesc = *pOldDesc; + + aServiceDesc.aServiceName = aStrVal; + + pDPObject->SetServiceData( aServiceDesc ); + } + } + else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) ) + { + uno::Sequence<beans::PropertyValue> aArgSeq; + if ( aValue >>= aArgSeq ) + { + String aEmpty; + ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty); + + const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc(); + if (pOldDesc) + aServiceDesc = *pOldDesc; + + rtl::OUString aStrVal; + sal_Int32 nArgs = aArgSeq.getLength(); + for (sal_Int32 nArgPos=0; nArgPos<nArgs; ++nArgPos) + { + const beans::PropertyValue& rProp = aArgSeq[nArgPos]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNO_SOURCENAME )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParSource = aStrVal; + } + else if (aPropName.EqualsAscii( SC_UNO_OBJECTNAME )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParName = aStrVal; + } + else if (aPropName.EqualsAscii( SC_UNO_USERNAME )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParUser = aStrVal; + } + else if (aPropName.EqualsAscii( SC_UNO_PASSWORD )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParPass = aStrVal; + } + } + + pDPObject->SetServiceData( aServiceDesc ); + } + } else throw UnknownPropertyException(); @@ -868,6 +967,63 @@ Any SAL_CALL ScDataPilotDescriptorBase::getPropertyValue( const OUString& aPrope { aRet = ::cppu::bool2any( aNewData.GetDrillDown() ); } + else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) ) + { + const ScImportSourceDesc* pImportDesc = pDPObject->GetImportSourceDesc(); + if ( pImportDesc ) + { + // fill ScImportParam so ScImportDescriptor::FillProperties can be used + ScImportParam aParam; + aParam.bImport = ( pImportDesc->nType != sheet::DataImportMode_NONE ); + aParam.aDBName = pImportDesc->aDBName; + aParam.aStatement = pImportDesc->aObject; + aParam.bNative = pImportDesc->bNative; + aParam.bSql = ( pImportDesc->nType == sheet::DataImportMode_SQL ); + aParam.nType = static_cast<BYTE>(( pImportDesc->nType == sheet::DataImportMode_QUERY ) ? ScDbQuery : ScDbTable); + + uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() ); + ScImportDescriptor::FillProperties( aSeq, aParam ); + aRet <<= aSeq; + } + else + { + // empty sequence + uno::Sequence<beans::PropertyValue> aEmpty(0); + aRet <<= aEmpty; + } + } + else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) ) + { + rtl::OUString aServiceName; + const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc(); + if (pServiceDesc) + aServiceName = pServiceDesc->aServiceName; + aRet <<= aServiceName; // empty string if no ServiceDesc set + } + else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) ) + { + const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc(); + if (pServiceDesc) + { + uno::Sequence<beans::PropertyValue> aSeq( 4 ); + beans::PropertyValue* pArray = aSeq.getArray(); + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNO_SOURCENAME ); + pArray[0].Value <<= rtl::OUString( pServiceDesc->aParSource ); + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNO_OBJECTNAME ); + pArray[1].Value <<= rtl::OUString( pServiceDesc->aParName ); + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNO_USERNAME ); + pArray[2].Value <<= rtl::OUString( pServiceDesc->aParUser ); + pArray[3].Name = rtl::OUString::createFromAscii( SC_UNO_PASSWORD ); + pArray[3].Value <<= rtl::OUString( pServiceDesc->aParPass ); + aRet <<= aSeq; + } + else + { + // empty sequence + uno::Sequence<beans::PropertyValue> aEmpty(0); + aRet <<= aEmpty; + } + } else throw UnknownPropertyException(); } @@ -966,7 +1122,8 @@ ScDataPilotDescriptorBase* ScDataPilotDescriptorBase::getImplementation( ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell* pDocSh, SCTAB nT, const String& rN) : ScDataPilotDescriptorBase( pDocSh ), nTab( nT ), - aName( rN ) + aName( rN ), + aModifyListeners( 0 ) { } @@ -981,6 +1138,7 @@ Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType ) // we also need to do the same for XDataPilotTable SC_QUERYINTERFACE( XDataPilotTable ) SC_QUERYINTERFACE( XDataPilotTable2 ) + SC_QUERYINTERFACE( XModifyBroadcaster ) return ScDataPilotDescriptorBase::queryInterface( rType ); } @@ -1004,12 +1162,13 @@ Sequence< uno::Type > SAL_CALL ScDataPilotTableObj::getTypes() throw(RuntimeExce sal_Int32 nParentLen = aParentTypes.getLength(); const uno::Type* pParentPtr = aParentTypes.getConstArray(); - aTypes.realloc( nParentLen + 1 ); + aTypes.realloc( nParentLen + 2 ); uno::Type* pPtr = aTypes.getArray(); for (sal_Int32 i = 0; i < nParentLen; ++i) pPtr[ i ] = pParentPtr[ i ]; // parent types first pPtr[ nParentLen ] = getCppuType( (const Reference< XDataPilotTable2 >*)0 ); + pPtr[ nParentLen+1 ] = getCppuType( (const Reference< XModifyBroadcaster >*)0 ); } return aTypes; } @@ -1183,6 +1342,70 @@ CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRangeByType( sal_Int32 n return aRet; } +void SAL_CALL ScDataPilotTableObj::addModifyListener( const uno::Reference<util::XModifyListener>& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<util::XModifyListener> *pObj = new uno::Reference<util::XModifyListener>( aListener ); + aModifyListeners.Insert( pObj, aModifyListeners.Count() ); + + if ( aModifyListeners.Count() == 1 ) + { + acquire(); // don't lose this object (one ref for all listeners) + } +} + +void SAL_CALL ScDataPilotTableObj::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + acquire(); // in case the listeners have the last ref - released below + + USHORT nCount = aModifyListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XModifyListener> *pObj = aModifyListeners[n]; + if ( *pObj == aListener ) + { + aModifyListeners.DeleteAndDestroy( n ); + + if ( aModifyListeners.Count() == 0 ) + { + release(); // release the ref for the listeners + } + + break; + } + } + + release(); // might delete this object +} + +void ScDataPilotTableObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if ( rHint.ISA(ScDataPilotModifiedHint) && + static_cast<const ScDataPilotModifiedHint&>(rHint).GetName() == aName ) + { + Refreshed_Impl(); + } + + ScDataPilotDescriptorBase::Notify( rBC, rHint ); +} + +void ScDataPilotTableObj::Refreshed_Impl() +{ + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + + // the EventObject holds a Ref to this object until after the listener calls + + ScDocument* pDoc = GetDocShell()->GetDocument(); + for ( USHORT n=0; n<aModifyListeners.Count(); n++ ) + pDoc->AddUnoListenerCall( *aModifyListeners[n], aEvent ); +} + // ============================================================================ ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) : diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx index b0711f919a7b..a3c20411d1fc 100644 --- a/sfx2/source/doc/objserv.cxx +++ b/sfx2/source/doc/objserv.cxx @@ -1259,21 +1259,13 @@ sal_uInt16 SfxObjectShell::ImplCheckSignaturesInformation( const uno::Sequence< bool bCompleteSignature = true; if( nInfos ) { - //These errors of certificates are allowed - sal_Int32 nNonErrors = security::CertificateValidity::VALID | - security::CertificateValidity::UNKNOWN_REVOKATION; - //Build a mask to filter out the allowed errors - sal_Int32 nMask = ~nNonErrors; - nResult = SIGNATURESTATE_SIGNATURES_OK; for ( int n = 0; n < nInfos; n++ ) { if ( bCertValid ) { sal_Int32 nCertStat = aInfos[n].CertificateStatus; - // "subtract" the allowed error flags from the result - sal_Int32 nErrors = ( nCertStat & nMask ); - bCertValid = nErrors > 0 ? sal_False : sal_True; + bCertValid = nCertStat == security::CertificateValidity::VALID ? sal_True : sal_False; } if ( !aInfos[n].SignatureIsValid ) diff --git a/solenv/bin/build.pl b/solenv/bin/build.pl index 5775468d0ead..442dcba26946 100755 --- a/solenv/bin/build.pl +++ b/solenv/bin/build.pl @@ -342,102 +342,19 @@ sub rename_file { }; sub generate_config_file { - my $source_config = SourceConfig -> new(); - $source_config_file = $source_config->get_config_file_path(); - my $temp_config_file = File::Temp::tmpnam($ENV{TMP}); - my @config_content_new = (); - my $addition_message; - my $removal_message; - my %present_modules = (); - if ($source_config_file) { - open(SOURCE_CONFIG_FILE, $source_config_file); - my @config_content = <SOURCE_CONFIG_FILE>; - close SOURCE_CONFIG_FILE; - my ($module_section, $repository_section); - foreach (@config_content) { - if ((!/^\S+/)||(/^\s*#+/)) { - push(@config_content_new, $_); - next; - } - if (/^\[repositories\]\s*(\s+#)*/) { - if ($module_section) { - $addition_message = add_modules_to_source_config(\%add_to_config, \@config_content_new); - }; - $module_section = 0; - $repository_section = 1; - push(@config_content_new, $_); - next; - }; - if (/^\[modules\]\s*(\s+#)*/) { - $module_section = 1; - $repository_section = 0; - push(@config_content_new, $_); - next; - }; - if ($module_section && /\s*(\S+)=active\s*(\s+#)*/) { - if ($clear_config || defined $remove_from_config{$1}) { - delete $remove_from_config{$1}; - $removal_message .= "$1 "; - } else { - push(@config_content_new, $_); - if (defined $add_to_config{$1} && !$prepare) { - push(@warnings, "Module $1 already activated in $source_config_file\n"); - delete $add_to_config{$1}; - } - }; - } else { - push(@config_content_new, $_); - }; - }; - if (keys %add_to_config) { - if (!$module_section) { - push(@config_content_new, "[modules]\n"); - }; - $addition_message = add_modules_to_source_config(\%add_to_config, \@config_content_new); - }; - } else { - if ($clear_config || scalar %remove_from_config) { - print_error('No source config file found'); - }; - $source_config_file = $source_config->get_config_file_default_path(); - push(@config_content_new, "[modules]\n"); - $addition_message = add_modules_to_source_config(\%add_to_config, \@config_content_new); - }; - die("Cannot open $temp_config_file") if (!open(NEW_CONFIG, ">$temp_config_file")); - print NEW_CONFIG $_ foreach (@config_content_new); - close NEW_CONFIG; - rename_file($temp_config_file, $source_config_file, 1); - foreach (keys %remove_from_config) { - push(@warnings, "Module(s) $_ not found in " . $source_config_file . "\n"); - }; - print_warnings(); - print $addition_message if ($addition_message); - print "Module(s):\n$removal_message\nremoved from $source_config_file\n" if ($removal_message); + my $source_config = SourceConfig->new(); + $source_config->add_active_modules([keys %add_to_config], 1) if (scalar %add_to_config); + $source_config->remove_activated_modules([keys %remove_from_config], 1) if (scalar %remove_from_config); + $source_config->remove_all_activated_modules() if ($clear_config); }; -# -# Add modules from the passed hash to the array of config strigns -# -sub add_modules_to_source_config { - my ($modules_hash_ref, $config_content_new) = @_; - my $message; - foreach (keys %$modules_hash_ref) { - push(@$config_content_new, "$_=active\n"); - $message .= "$_ "; - }; - if ($message) { - return "Module(s):\n" .$message . "\nare added to the " . $source_config_file . "\n\n"; - } else { - return ''; - }; -}; sub start_interactive { $pid = open(HTML_PIPE, "-|"); print "Pipe is open\n"; if ($pid) { # parent - # make file handle non-bloking + # make file handle non-blocking my $flags = ''; fcntl(HTML_PIPE, F_GETFL, $flags); $flags |= O_NONBLOCK; @@ -1675,7 +1592,7 @@ sub get_options { }; sub get_module_and_buildlist_paths { - if ($build_all_parents) { + if ($build_all_parents || $checkparents) { my $source_config = SourceConfig -> new($StandDir); $source_config_file = $source_config->get_config_file_path(); $active_modules{$_}++ foreach ($source_config->get_active_modules()); @@ -2371,7 +2288,9 @@ sub prepare_incompatible_build { @modules_built = keys %$deps_hash; %add_to_config = %$deps_hash; if ($prepare) { - generate_config_file() if ((!defined $ENV{UPDATER}) || (defined $ENV{CWS_WORK_STAMP})); + if ((!defined $ENV{UPDATER}) || (defined $ENV{CWS_WORK_STAMP})) { + SourceConfig->new()->add_active_modules([keys %add_to_config], 0); + } clear_delivered(); } my $old_output_tree = ''; diff --git a/solenv/bin/modules/SourceConfig.pm b/solenv/bin/modules/SourceConfig.pm index 88aa226f68a9..c3503221b8fa 100644..100755 --- a/solenv/bin/modules/SourceConfig.pm +++ b/solenv/bin/modules/SourceConfig.pm @@ -38,10 +38,12 @@ package SourceConfig; use strict; use constant SOURCE_CONFIG_FILE_NAME => 'source_config'; +use constant SOURCE_CONFIG_VERSION => 2; use Carp; use Cwd; use File::Basename; +use File::Temp qw(tmpnam); my $debug = 0; @@ -62,20 +64,28 @@ sub new { } else { $source_root = $ENV{SOURCE_ROOT_DIR}; }; - $source_root = Cwd::realpath($source_root); + $self->{SOURCE_ROOT} = Cwd::realpath($source_root); $self->{DEBUG} = 0; - $self->{SOURCE_ROOT} = $source_root; + $self->{VERBOSE} = 0; $self->{REPOSITORIES} = {}; + $self->{ACTIVATED_REPOSITORIES} = {}; $self->{MODULE_PATHS} = {}; $self->{MODULE_BUILD_LIST_PATHS} = {}; $self->{ACTIVATED_MODULES} = {}; $self->{MODULE_REPOSITORY} = {}; $self->{REAL_MODULES} = {}; + $self->{NEW_MODULES} = []; + $self->{REMOVE_MODULES} = {}; + $self->{REMOVE_REPOSITORIES} = {}; + $self->{NEW_REPOSITORIES} = []; + $self->{WARNINGS} = []; + $self->{REPORT_MESSAGES} = []; + $self->{CONFIG_FILE_CONTENT} = []; if (defined $self->{USER_SOURCE_ROOT}) { ${$self->{REPOSITORIES}}{File::Basename::basename($self->{USER_SOURCE_ROOT})} = $self->{USER_SOURCE_ROOT}; }; - $self->{SOURCE_CONFIG_FILE} = get_config_file($source_root); - $self->{SOURCE_CONFIG_DEFAULT} = $source_root .'/'.SOURCE_CONFIG_FILE_NAME; + $self->{SOURCE_CONFIG_FILE} = get_config_file($self->{SOURCE_ROOT}); + $self->{SOURCE_CONFIG_DEFAULT} = $self->{SOURCE_ROOT} .'/'.SOURCE_CONFIG_FILE_NAME; read_config_file($self); bless($self, $class); return $self; @@ -83,6 +93,10 @@ sub new { ##### methods ##### +sub get_version { + return SOURCE_CONFIG_VERSION; +}; + sub get_repositories { my $self = shift; @@ -249,8 +263,11 @@ sub read_config_file { my $repository_section = 0; my $module_section = 0; my $line = 0; + my @file_content = (); + if (open(SOURCE_CONFIG_FILE, $self->{SOURCE_CONFIG_FILE})) { foreach (<SOURCE_CONFIG_FILE>) { + push (@{$self->{CONFIG_FILE_CONTENT}}, $_); $line++; chomp; next if (!/^\S+/); @@ -270,6 +287,10 @@ sub read_config_file { if (/\s*(\S+)=active\s*(\s+#)*/) { if ($repository_section) { ${$self->{REPOSITORIES}}{$1} = $self->{SOURCE_ROOT} . "/$1"; + ${$self->{ACTIVATED_REPOSITORIES}}{$1}++; + if (defined $ENV{UPDMINOREXT}) { + ${$self->{REPOSITORIES}}{$1} .= $ENV{UPDMINOREXT}; + }; next; } if ($module_section) { @@ -290,6 +311,187 @@ sub read_config_file { }; }; +sub remove_all_activated_repositories { + my $self = shift; + $self->remove_activated_repositories([keys %{$self->{ACTIVATED_REPOSITORIES}}]); +}; + +sub remove_activated_repositories { + my $self = shift; + my $new_repositories_ref = shift; + push(@{$self->{WARNINGS}}, "\nWARNING: Empty repository list passed for removing from source_config\n") if (!scalar @$new_repositories_ref); + $self->{VERBOSE} = shift; + $self->{REMOVE_REPOSITORIES} = {}; + foreach (@$new_repositories_ref) { + if (!defined ${$self->{ACTIVATED_REPOSITORIES}}{$_}) { + push (@{$self->{WARNINGS}}, "\nWARNING: repository $_ is not activated in ". $self->get_config_file_default_path()."\n"); + } else { + ${$self->{REMOVE_REPOSITORIES}}{$_}++; + delete ${$self->{ACTIVATED_REPOSITORIES}}{$_}; + }; + }; + generate_config_file($self); +}; + +sub remove_all_activated_modules { + my $self = shift; + $self->remove_activated_modules([keys %{$self->{ACTIVATED_MODULES}}]); +}; + +sub remove_activated_modules { + my $self = shift; + my $new_modules_ref = shift; + push(@{$self->{WARNINGS}}, "\nWARNING: Empty module list passed for removing from source_config\n") if (!scalar @$new_modules_ref); + $self->{VERBOSE} = shift; + $self->{REMOVE_MODULES} = {}; + foreach (@$new_modules_ref) { + if (!defined ${$self->{ACTIVATED_MODULES}}{$_}) { + push (@{$self->{WARNINGS}}, "\nWARNING: module $_ is not activated in ". $self->get_config_file_default_path()."\n"); + } else { + ${$self->{REMOVE_MODULES}}{$_}++; + delete ${$self->{ACTIVATED_MODULES}}{$_}; + }; + }; + generate_config_file($self); +}; + +sub add_active_repositories { + my $self = shift; + $self->{NEW_REPOSITORIES} = shift; + croak('Empty module list passed for adding to source_config') if (!scalar @{$self->{NEW_REPOSITORIES}}); + $self->{VERBOSE} = shift; + generate_config_file($self); +}; + +sub add_active_modules { + my $self = shift; + $self->{NEW_MODULES} = shift; + croak('Empty module list passed for adding to source_config') if (!scalar @{$self->{NEW_MODULES}}); + $self->{VERBOSE} = shift; + generate_config_file($self); +}; + +sub add_content { + my $self = shift; + my $content = shift; + my $entries_to_add = shift; + return if (!scalar @$entries_to_add); + my $message; + my $message_part1; + my $warning_message; + my $activated_entries; + + if ($entries_to_add == $self->{NEW_MODULES}) { + $self->{NEW_MODULES} = []; + $message_part1 = "Module(s):\n"; + $activated_entries = $self->{ACTIVATED_MODULES}; + } elsif ($entries_to_add == $self->{NEW_REPOSITORIES}) { + $self->{NEW_REPOSITORIES} = []; + $message_part1 = "Repositories:\n"; + $activated_entries = $self->{ACTIVATED_REPOSITORIES}; + }; + foreach my $entry (@$entries_to_add) { + if (defined $$activated_entries{$entry}) { + $warning_message .= "$entry " + } else { + push(@$content, "$entry=active\n"); + ${$activated_entries}{$entry}++; + $message .= "$entry " + }; + }; + + push(@{$self->{REPORT_MESSAGES}}, "\n$message_part1 $message\nhave been added to the ". $self->get_config_file_default_path()."\n") if ($message); + push (@{$self->{WARNINGS}}, "\nWARNING: $message_part1 $warning_message\nare already added to the ". $self->get_config_file_default_path()."\n") if ($warning_message); +}; + +sub generate_config_file { + my $self = shift; + my @config_content_new = (); + my ($module_section, $repository_section); + my %removed_modules = (); + my %removed_repositories = (); + foreach (@{$self->{CONFIG_FILE_CONTENT}}) { + if (/^\[repositories\]\s*(\s+#)*/) { + if ($module_section) { + $self->add_content(\@config_content_new, $self->{NEW_MODULES}); + }; + $module_section = 0; + $repository_section = 1; + }; + if (/^\[modules\]\s*(\s+#)*/) { + if ($repository_section) { + $self->add_content(\@config_content_new, $self->{NEW_REPOSITORIES}); + }; + $module_section = 1; + $repository_section = 0; + }; + if ($module_section && /\s*(\S+)=active\s*(\s+#)*/) { + if (defined ${$self->{REMOVE_MODULES}}{$1}) { + $removed_modules{$1}++; + next; + }; + } + if ($repository_section && /\s*(\S+)=active\s*(\s+#)*/) { + if (defined ${$self->{REMOVE_REPOSITORIES}}{$1}) { + $removed_repositories{$1}++; + next; + }; + } + push(@config_content_new, $_); + }; + if (scalar @{$self->{NEW_MODULES}}) { + push(@config_content_new, "[modules]\n") if (!$module_section); + $self->add_content(\@config_content_new, $self->{NEW_MODULES}); + }; + if (scalar @{$self->{NEW_REPOSITORIES}}) { + push(@config_content_new, "[repositories]\n") if (!$repository_section); + $self->add_content(\@config_content_new, $self->{NEW_REPOSITORIES}); + }; + if (scalar keys %removed_modules) { + my @deleted_modules = keys %removed_modules; + push(@{$self->{REPORT_MESSAGES}}, "\nModules: @deleted_modules\nhave been removed from the ". $self->get_config_file_default_path()."\n"); + + }; + if (scalar keys %removed_repositories) { + my @deleted_repositories = keys %removed_repositories; + push(@{$self->{REPORT_MESSAGES}}, "\nRepositories: @deleted_repositories\nhave been removed from the ". $self->get_config_file_default_path()."\n"); + + }; + + # Writing file, printing warnings and reports + + #check if we need to write a new file + my $write_needed = 0; + if ((scalar @{$self->{CONFIG_FILE_CONTENT}}) != (scalar @config_content_new)) { + $write_needed++; + } else { + foreach my $i (0 .. $#{$self->{CONFIG_FILE_CONTENT}}) { + if (${$self->{CONFIG_FILE_CONTENT}}[$i] ne $config_content_new[$i]) { + $write_needed++; + last; + }; + }; + }; + if ($write_needed) { + my $temp_config_file = File::Temp::tmpnam($ENV{TMP}); + die("Cannot open $temp_config_file") if (!open(NEW_CONFIG, ">$temp_config_file")); + print NEW_CONFIG $_ foreach (@config_content_new); + close NEW_CONFIG; + rename($temp_config_file, $self->get_config_file_default_path()) or system("mv", $temp_config_file, $self->get_config_file_default_path()); + if (-e $temp_config_file) { + system("rm -rf $temp_config_file") if (!unlink $temp_config_file); + }; + $self->{CONFIG_FILE_CONTENT} = \@config_content_new; + }; + if ($self->{VERBOSE}) { + print $_ foreach (@{$self->{WARNINGS}}); + $self->{VERBOSE} = 0; + }; + $self->{WARNINGS} = []; + print $_ foreach (@{$self->{REPORT_MESSAGES}}); + $self->{REPORT_MESSAGES} = []; +}; + ##### finish ##### 1; # needed by use or require @@ -325,6 +527,10 @@ SourceConfig::new() Creates a new instance of SourceConfig. Can't fail. +SourceConfig::get_version() + +Returns version number of the module. Can't fail. + SourceConfig::get_repositories() @@ -364,9 +570,35 @@ SourceConfig::is_active() Returns 1 (TRUE) if a module is active Returns 0 (FALSE) if a module is not active +SourceConfig::add_active_modules($module_array_ref) + +Adds modules from the @$module_array_ref as active to the source_config file + +SourceConfig::add_active_repositories($repository_array_ref) + +Adds repositories from the @$repository_array_ref as active to the source_config file + +SourceConfig::remove_activated_modules($module_array_ref) + +Removes modules from the @$module_array_ref from the source_config file + +SourceConfig::remove_all_activated_modules() + +Removes all activated modules from the source_config file + +SourceConfig::remove_activated_repositories($repository_array_ref) + +Removes repositories from the @$repository_array_ref from the source_config file + +SourceConfig::remove_all_activated_repositories() + +Removes all activated repositories from the source_config file + + =head2 EXPORT SourceConfig::new() +SourceConfig::get_version() SourceConfig::get_repositories() SourceConfig::get_active_modules() SourceConfig::get_all_modules() @@ -376,6 +608,12 @@ SourceConfig::get_module_repository($module) SourceConfig::get_config_file_path() SourceConfig::get_config_file_default_path() SourceConfig::is_active($module) +SourceConfig::add_active_modules($module_array_ref) +SourceConfig::add_active_repositories($repository_array_ref) +SourceConfig::remove_activated_modules($module_array_ref) +SourceConfig::remove_all_activated_modules() +SourceConfig::remove_activated_repositories($repository_array_ref) +SourceConfig::remove_all_activated_repositories() =head1 AUTHOR diff --git a/solenv/bin/modules/installer/epmfile.pm b/solenv/bin/modules/installer/epmfile.pm index 95f661160a0e..ffe79136b57e 100644 --- a/solenv/bin/modules/installer/epmfile.pm +++ b/solenv/bin/modules/installer/epmfile.pm @@ -2544,6 +2544,7 @@ sub create_packages_without_epm my $dir = getcwd; my $buildroot = $dir . "/" . $epmdir . "buildroot/"; $buildrootstring = "--buildroot=$buildroot"; + mkdir($buildroot = $dir . "/" . $epmdir . "BUILD/"); } my $systemcall = "$rpmcommand -bb --define \"_unpackaged_files_terminate_build 0\" $specfilename --target $target $buildrootstring 2\>\&1 |"; @@ -2719,6 +2720,15 @@ sub remove_temporary_epm_files my $returnvalue = system($systemcall); + $removedir = $epmdir . "BUILD"; + + $systemcall = "rm -rf $removedir"; + + installer::logger::print_message( "... $systemcall ...\n" ); + + $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; push( @installer::globals::logfileinfo, $infoline); diff --git a/solenv/config/sdev300.ini b/solenv/config/sdev300.ini index e0efaf771933..7fffd7eaca26 100644 --- a/solenv/config/sdev300.ini +++ b/solenv/config/sdev300.ini @@ -211,6 +211,7 @@ finish SOLARLIB -L%SOLARVER%/%INPATH%/lib%UPDMINOREXT% %JDKLIBS% %SOLAREXTRALIB% SOLARSRC %SRC_ROOT% SOURCE_ROOT_DIR $expand(%SOLARSRC%/..) + ANT_HOME %COMMON_BUILD_TOOLS%$/apache-ant-1.7.1 } common_2:0 IF X%CWS_WORK_STAMP%X == XX { diff --git a/solenv/inc/antsettings.mk b/solenv/inc/antsettings.mk index d840e4457f61..5a28b242967d 100644 --- a/solenv/inc/antsettings.mk +++ b/solenv/inc/antsettings.mk @@ -28,10 +28,6 @@ .IF "$(SOLAR_JAVA)"!="" -.IF "$(ANT_HOME)" == "" -ANT_HOME*:=$(COMMON_BUILD_TOOLS)/apache-ant-1.7.0 -.EXPORT : ANT_HOME -.ENDIF ANT_LIB*:=$(ANT_HOME)/lib ANT_CLASSPATH:=$(ANT_LIB)/xercesImpl.jar$(PATH_SEPERATOR)$(ANT_LIB)/xml-apis.jar$(PATH_SEPERATOR)$(ANT_LIB)/ant.jar diff --git a/solenv/inc/minor.mk b/solenv/inc/minor.mk index 6e6607f779e1..ca9b6bf01e13 100644 --- a/solenv/inc/minor.mk +++ b/solenv/inc/minor.mk @@ -1,5 +1,5 @@ RSCVERSION=300 -RSCREVISION=300m74(Build:9487) -BUILD=9487 -LAST_MINOR=m74 +RSCREVISION=300m75(Build:9488) +BUILD=9488 +LAST_MINOR=m75 SOURCEVERSION=DEV300 diff --git a/sysui/desktop/freedesktop/freedesktop-menus.spec b/sysui/desktop/freedesktop/freedesktop-menus.spec index 14a7c7795b24..501f8432d940 100644 --- a/sysui/desktop/freedesktop/freedesktop-menus.spec +++ b/sysui/desktop/freedesktop/freedesktop-menus.spec @@ -325,6 +325,7 @@ done /usr/share/applications/%unixfilename-printeradmin.desktop /usr/share/applications/%unixfilename-writer.desktop /usr/share/applications/%unixfilename-startcenter.desktop +/usr/share/applications/%unixfilename-javafilter.desktop /usr/share/icons/gnome/*/apps/*png /usr/share/icons/gnome/*/mimetypes/*png /usr/share/icons/hicolor/*/apps/*png diff --git a/sysui/desktop/menus/javafilter.desktop b/sysui/desktop/menus/javafilter.desktop new file mode 100644 index 000000000000..9d230f954a7b --- /dev/null +++ b/sysui/desktop/menus/javafilter.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Version=1.0 +Terminal=false +Type=Application +Exec=openoffice -writer %U +MimeType=application/x-aportisdoc;application/x-pocket-word;application/x-pocket-excel; +Name=%PRODUCTNAME Small Device Format Importer +GenericName=Small Device Format Importer +NoDisplay=true diff --git a/sysui/desktop/redhat/redhat-menus.spec b/sysui/desktop/redhat/redhat-menus.spec index 4ad74ad1b31f..e153b55c3fd4 100644 --- a/sysui/desktop/redhat/redhat-menus.spec +++ b/sysui/desktop/redhat/redhat-menus.spec @@ -279,6 +279,7 @@ done /usr/share/applications/%unixfilename-base.desktop /usr/share/applications/%unixfilename-printeradmin.desktop /usr/share/applications/%unixfilename-startcenter.desktop +/usr/share/applications/%unixfilename-javafilter.desktop /usr/share/applnk-redhat/Office/%unixfilename-writer.desktop /usr/share/applnk-redhat/Office/%unixfilename-calc.desktop /usr/share/applnk-redhat/Office/%unixfilename-draw.desktop @@ -287,6 +288,7 @@ done /usr/share/applnk-redhat/Office/%unixfilename-base.desktop /usr/share/applnk-redhat/Office/%unixfilename-printeradmin.desktop /usr/share/applnk-redhat/Office/%unixfilename-startcenter.desktop +/usr/share/applnk-redhat/Office/%unixfilename-javafilter.desktop /usr/share/mime-info/*.keys /usr/share/mime-info/*.mime /usr/share/mimelnk/application/*.desktop diff --git a/sysui/desktop/share/launcher_genericname.ulf b/sysui/desktop/share/launcher_genericname.ulf index ea11da04e03f..ff8041a155fc 100644 --- a/sysui/desktop/share/launcher_genericname.ulf +++ b/sysui/desktop/share/launcher_genericname.ulf @@ -18,3 +18,6 @@ en-US = "Drawing Program" [startcenter] en-US = "Office" + +[javafilter] +en-US = "Small Device Format Importer" diff --git a/sysui/desktop/share/makefile.mk b/sysui/desktop/share/makefile.mk index 9668272a5615..e1e47648b077 100644 --- a/sysui/desktop/share/makefile.mk +++ b/sysui/desktop/share/makefile.mk @@ -52,7 +52,7 @@ ULFFILES= \ launcher_genericname.ulf \ launcher_name.ulf -LAUNCHERLIST = writer calc draw impress math base printeradmin qstart startcenter +LAUNCHERLIST = writer calc draw impress math base printeradmin qstart startcenter javafilter LAUNCHERDEPN = ../menus/{$(LAUNCHERLIST)}.desktop LAUNCHERFLAGFILE = $(COMMONMISC)/$(TARGET)/xdg.flag @@ -126,9 +126,9 @@ MIMEICONLIST = \ extension ICONDEPN = \ - ../icons/hicolor/{16x16 32x32 48x48}/apps/{$(LAUNCHERLIST:s/qstart//)}.png \ + ../icons/hicolor/{16x16 32x32 48x48}/apps/{$(LAUNCHERLIST:s/qstart//:s/javafilter//)}.png \ ../icons/hicolor/{16x16 32x32 48x48}/mimetypes/{$(MIMEICONLIST)}.png \ - ../icons/locolor/{16x16 32x32}/apps/{$(LAUNCHERLIST:s/qstart//)}.png \ + ../icons/locolor/{16x16 32x32}/apps/{$(LAUNCHERLIST:s/qstart//:s/javafilter//)}.png \ ../icons/locolor/{16x16 32x32}/mimetypes/{$(MIMEICONLIST)}.png # --- Targets ------------------------------------------------------ diff --git a/sysui/desktop/suse/suse-menus.spec b/sysui/desktop/suse/suse-menus.spec index a1bd2b0359f1..7280d9dbae8b 100644 --- a/sysui/desktop/suse/suse-menus.spec +++ b/sysui/desktop/suse/suse-menus.spec @@ -291,6 +291,7 @@ done /usr/share/applications/%unixfilename-base.desktop /usr/share/applications/%unixfilename-printeradmin.desktop /usr/share/applications/%unixfilename-startcenter.desktop +/usr/share/applications/%unixfilename-javafilter.desktop /opt/gnome/share/mime-info/*.keys /opt/gnome/share/mime-info/*.mime /opt/kde3/share/mimelnk/application/*.desktop diff --git a/testautomation/chart2/required/includes/ch2_datadialogue.inc b/testautomation/chart2/optional/includes/ch2_datadialogue.inc index 85bb63a200f9..e0db844353c1 100644 --- a/testautomation/chart2/required/includes/ch2_datadialogue.inc +++ b/testautomation/chart2/optional/includes/ch2_datadialogue.inc @@ -105,6 +105,12 @@ testcase tChartDataDialogueButtons else printlog " DeleteColumn was correctly disabled." end if + printlog "Check if the 'Insert Text Column'-button is enabled." + if InsertTextColumn.isEnabled then + printlog " Insert Text Column was correctly enabled." + else + warnlog " Insert Text Column wasnt enabled, but should have been." + end if '/// Press 'TAB' to enter the Data-fields, followed by 'SHIFT TAB' end up in the first field. printlog "Press 'TAB' to enter the Data-fields, followed by 'SHIFT TAB' end up in the first field." Kontext "Diagramdata" @@ -204,6 +210,8 @@ testcase tChartDataDialogueButtons else warnlog " Error when Swapping a Row." end if + printlog "Insert a text column" + InsertTextColumn.Click '/// Close the dialogue printlog " Close the dialogue." Diagramdata.Close diff --git a/testautomation/chart2/optional/includes/wizard/ch2_lvl1_wizard.inc b/testautomation/chart2/optional/includes/wizard/ch2_lvl1_wizard.inc index dcdb65ab7446..10ba7eb017e1 100644 --- a/testautomation/chart2/optional/includes/wizard/ch2_lvl1_wizard.inc +++ b/testautomation/chart2/optional/includes/wizard/ch2_lvl1_wizard.inc @@ -544,53 +544,16 @@ testcase tCreateNewLineChart end if printlog "Format / Data Ranges" FormatDataRanges - Kontext - Active.SetPage TabChartTypeDataRange - Kontext "TabChartTypeDataRange" - if TabChartTypeDataRange.Exists(2) then - printlog "Check substrings '$A$2:$C$13', '$A$19', '$B$1:$C$13', '$E$1:$F$13' and '$B$17:$E$17' in Data Range" - sControlString = DataRange.GetText - printlog "Data Range is: " & sControlString - if instr ( sControlString , "$A$2:$C$13" ) = 0 Then - warnlog "Data range wasn't correctly preserved after save and reload: $A$2:$C$13" - endif - if instr ( sControlString , "$A$19" ) = 0 Then - warnlog "Data range wasn't correctly preserved after save and reload: $A$19" - endif - if instr ( sControlString , "$B$1:$C$13" ) = 0 Then - QAErrorlog "#i100780#Data range wasn't correctly preserved after save and reload: $B$1:$C$13" - endif - if instr ( sControlString , "$E$1:$F$13" ) = 0 Then - warnlog "Data range wasn't correctly preserved after save and reload: $E$1:$F$13" - endif - if instr ( sControlString , "$B$17:$E$17" ) = 0 Then - warnlog "Data range wasn't correctly preserved after save and reload: $B$17:$E$17" - endif - printlog "Check if Radio Button ROWS is checked" - if Rows.IsChecked then - warnlog "Radio Button ROWS (disabled) wasn't preserved after save and reload." - endif - printlog "Check if Radio Button COLUMNS is unchecked" - if NOT Columns.IsChecked then - warnlog "Radio Button COLUMNS (enabled) wasn't preserved after save and reload." - endif - printlog "Check if 'First row as label' box is unchecked" - if NOT FirstRowAsLabel.IsChecked then - warnlog "Check box 'First row as label' (enabled) wasn't preserved after save and reload." - endif - printlog "Check if 'First column as label' box is checked" - if NOT FirstColumnAsLabel.IsChecked then - warnlog "Check box 'First column as label' (enabled) wasn't preserved after save and reload." - endif - else - warnlog "Tab page Data Range was not up!" - FormatDataRanges - end if printlog "Switch to tab page Data Series" Kontext + Active.SetPage TabFormatDataRangesDataRange 'Due to bug #i77237# the tabpage has to be switched once before 'OK' or 'Cancel' can be used Active.SetPage TabFormatDataRangesDataSeries Kontext "TabChartTypeDataSeries" - if TabChartTypeDataSeries.Exists(2) then + if TabChartTypeDataSeries.Exists(2) then + printlog "Verify that there are 4 data series" + if DataSeries.GetItemCount <> 4 then + warnlog "There should be 4 dataseries, but there are " & DataSeries.GetItemCount + end if printlog "Select 4th entry in Data Series" if fSetListBoxByItem ( DataSeries , 4 ) > 0 then warnlog "Selecting 4th item in Data Series failed. EXITING!" diff --git a/testautomation/framework/optional/includes/basic_issues.inc b/testautomation/framework/optional/includes/basic_issues.inc index d07326226ed8..0c38e743fb93 100644 --- a/testautomation/framework/optional/includes/basic_issues.inc +++ b/testautomation/framework/optional/includes/basic_issues.inc @@ -52,6 +52,13 @@ function hTestActive( cString as string , iMethod as integer , bExact as boolean ' -3 = content of messagebox not relevant ' -4 = Messagebox not displayed / Macro not executed ' 1 - 4 = Number of buttons on the dialog + + ' internal states, if state = 0 we return the buttoncount instead + const STATE_SUCCESS = 0 + const STATE_FUZZY_MATCH = -1 + const STATE_NO_MATCH = -2 + const STATE_IGNORE_MSGBOX = -3 + const STATE_MACRO_EXECUTION_FAILED = -4 const CFN = "hTestActive()::" @@ -65,30 +72,26 @@ function hTestActive( cString as string , iMethod as integer , bExact as boolean cMsg = Active.getText() if ( cString <> "" ) then - if ( instr( active.getText(), cString ) <> 0 ) then + if ( instr( active.getText(), cString ) ) then if ( active.getText() = cString ) then - 'printlog( CFN & "Correct message found (exact match): " & cMsg ) - rc = 0 + rc = STATE_SUCCESS else if ( bExact ) then warnlog( CFN & "Message is no exact match: " & cMsg ) - rc = -1 + rc = STATE_FUZZY_MATCH else - 'printlog( CFN & "Correct message found (fuzzy match): " & cMsg ) - rc = 0 + rc = STATE_SUCCESS endif endif else warnlog( CFN & "Messagebox has wrong content: " & cMsg ) - rc = -4 + rc = STATE_NO_MATCH endif else - 'printlog( CFN & "Messagebox: " & cMsg ) - rc = -3 + rc = STATE_IGNORE_MSGBOX endif buttons = Active.getButtonCount() - 'printlog( CFN & "Number of buttons: " & buttons ) select case( iMethod ) case 1 : Active.OK() case 2 : Active.Cancel() @@ -97,9 +100,10 @@ function hTestActive( cString as string , iMethod as integer , bExact as boolean end select else warnlog( CFN & "Messagebox is missing" ) + rc = STATE_MACRO_EXECUTION_FAILED endif - if ( rc = 0 ) then hTestActive() = buttons + if ( rc = STATE_SUCCESS ) then hTestActive() = buttons end function @@ -176,7 +180,7 @@ testcase t_macros() hIDERunMacro() hTestActive( "1900" , 1 , FALSE ) hTestActive( "2" , 1 , FALSE ) -'--------- + printlog( "" ) printlog( " ---------- i103691 ------------ " ) hInsertMacroFromFile( "i103691" ) @@ -197,7 +201,14 @@ testcase t_macros() hTestActive( "43" , 1 , FALSE ) hTestActive( "Pi" , 1 , FALSE ) -'------- + printlog( "" ) + printlog( " ---------- i107070 ------------ " ) + hInsertMacroFromFile( "i107070" ) + hIDERunMacro() + hTestActive( "Dbg_Methods" , 1 , FALSE ) + hTestActive( "Dbg_Methods" , 1 , FALSE ) + hTestActive( "." , 1 , FALSE ) + printlog( "" ) printlog( " ---------- MessageBoxes ------------ " ) hInsertMacroFromFile( "MessageBoxes" ) diff --git a/testautomation/global/input/macros.txt b/testautomation/global/input/macros.txt index f34e54f607d1..ffe95be431e3 100755 --- a/testautomation/global/input/macros.txt +++ b/testautomation/global/input/macros.txt @@ -262,3 +262,20 @@ Sub Main msgbox( "Error" ) endif end sub + +# ---------------------------------------------------------------------------- # + +[i107070] +Sub Main + oSingleton = com.sun.star.logging.LoggerPool + + oInstance1 = oSingleton.get() + msgbox oInstance1.dbg_properties + + oCtx = GetDefaultContext() + oInstance2 = oSingleton.get( oCtx ) + msgbox oInstance2.dbg_properties + + ' Uncommenting this should result in an error "Invalid procedure call" + oInstanceErr1 = oSingleton.get( 42 ) +End Sub diff --git a/testautomation/global/win/dial_d_h.win b/testautomation/global/win/dial_d_h.win index 48724c5eaa27..1540dbd8743f 100755 --- a/testautomation/global/win/dial_d_h.win +++ b/testautomation/global/win/dial_d_h.win @@ -83,16 +83,6 @@ Art sc:ListBox:RID_SCDLG_DAPIDATA:LB_OBJTYPE *DatenquelleLiteraturdatenbank HID_DLG_DBCHANGE Auswahl HID_SELECTION_TLB -*Diagramdata SID_DIAGRAM_DATA -Toolbox2 HID_SCH_TBX_DATA -InsertRow HID_SCH_TBI_DATA_INSERT_ROW -InsertColumn HID_SCH_TBI_DATA_INSERT_COL -DeleteRow HID_SCH_TBI_DATA_DELETE_ROW -DeleteColumn HID_SCH_TBI_DATA_DELETE_COL -SwapColumns HID_SCH_TBI_DATA_SWAP_COL -SwapRows HID_SCH_TBI_DATA_SWAP_ROW -Tables HID_SCH_CTL_DATA -DataSeriesLabel HID_SCH_DATA_SERIES_LABEL *Dokumenteigenschaften SID_DOCINFO diff --git a/testautomation/global/win/edia_d_h.win b/testautomation/global/win/edia_d_h.win index de1b69ab4429..505c35536025 100755 --- a/testautomation/global/win/edia_d_h.win +++ b/testautomation/global/win/edia_d_h.win @@ -58,6 +58,18 @@ DatabaseFile SID_OPENURL Browse cui:PushButton:DLG_DOCUMENTLINK:PB_BROWSEFILE RegisteredName cui:Edit:DLG_DOCUMENTLINK:ET_NAME +*Diagramdata SID_DIAGRAM_DATA +Toolbox2 HID_SCH_TBX_DATA +InsertRow HID_SCH_TBI_DATA_INSERT_ROW +InsertColumn HID_SCH_TBI_DATA_INSERT_COL +InsertTextColumn HID_SCH_TBI_DATA_INSERT_TEXT_COL +DeleteRow HID_SCH_TBI_DATA_DELETE_ROW +DeleteColumn HID_SCH_TBI_DATA_DELETE_COL +SwapColumns HID_SCH_TBI_DATA_SWAP_COL +SwapRows HID_SCH_TBI_DATA_SWAP_ROW +Tables HID_SCH_CTL_DATA +DataSeriesLabel HID_SCH_DATA_SERIES_LABEL + *DigitalSignature HID_XMLSEC_DLG_DIGSIG ViewCertificate xmlsecurity:PushButton:RID_XMLSECDLG_DIGSIG:BTN_VIEWCERT CertificateList HID_XMLSEC_CTRL_SIGNATURESDLG diff --git a/testautomation/spreadsheet/optional/input/validity.ods b/testautomation/spreadsheet/optional/input/validity.ods Binary files differindex 06a980c67478..aced256e948b 100755 --- a/testautomation/spreadsheet/optional/input/validity.ods +++ b/testautomation/spreadsheet/optional/input/validity.ods diff --git a/ucb/source/ucp/gio/gio_content.hxx b/ucb/source/ucp/gio/gio_content.hxx index 824fa6514379..1c00f8c79d6e 100644 --- a/ucb/source/ucp/gio/gio_content.hxx +++ b/ucb/source/ucp/gio/gio_content.hxx @@ -140,7 +140,7 @@ public: virtual ~Content(); - static com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > getPropertyValuesFromGFileInfo( + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > getPropertyValuesFromGFileInfo( GFileInfo *pInfo, const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr, const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv, const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& rProperties); diff --git a/ucb/source/ucp/gio/gio_datasupplier.cxx b/ucb/source/ucp/gio/gio_datasupplier.cxx index e7d55039ed27..22cd4afa08fe 100644 --- a/ucb/source/ucp/gio/gio_datasupplier.cxx +++ b/ucb/source/ucp/gio/gio_datasupplier.cxx @@ -236,11 +236,31 @@ uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nInde if ( getResult( nIndex ) ) { - uno::Reference< sdbc::XRow > xRow = Content::getPropertyValuesFromGFileInfo( - maResults[ nIndex ]->pInfo, m_xSMgr, getResultSet()->getEnvironment(), getResultSet()->getProperties()); - - maResults[ nIndex ]->xRow = xRow; - return xRow; + uno::Reference< ucb::XContent > xContent( queryContent( nIndex ) ); + if ( xContent.is() ) + { + try + { + uno::Reference< ucb::XCommandProcessor > xCmdProc( + xContent, uno::UNO_QUERY_THROW ); + sal_Int32 nCmdId( xCmdProc->createCommandIdentifier() ); + ucb::Command aCmd; + aCmd.Name = rtl::OUString::createFromAscii( "getPropertyValues" ); + aCmd.Handle = -1; + aCmd.Argument <<= getResultSet()->getProperties(); + uno::Any aResult( xCmdProc->execute( + aCmd, nCmdId, getResultSet()->getEnvironment() ) ); + uno::Reference< sdbc::XRow > xRow; + if ( aResult >>= xRow ) + { + maResults[ nIndex ]->xRow = xRow; + return xRow; + } + } + catch ( uno::Exception const & ) + { + } + } } return uno::Reference< sdbc::XRow >(); } diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.cxx b/ucb/source/ucp/webdav/DAVResourceAccess.cxx index ea1c09efaa3f..4ffc8dd88cf5 100644 --- a/ucb/source/ucp/webdav/DAVResourceAccess.cxx +++ b/ucb/source/ucp/webdav/DAVResourceAccess.cxx @@ -960,6 +960,7 @@ void DAVResourceAccess::LOCK( while ( bRetry ); } +#if 0 // currently not used, but please don't remove code //========================================================================= // refresh existing lock. sal_Int64 DAVResourceAccess::LOCK( @@ -1003,6 +1004,7 @@ sal_Int64 DAVResourceAccess::LOCK( return nNewTimeout; } +#endif //========================================================================= void DAVResourceAccess::UNLOCK( diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.hxx b/ucb/source/ucp/webdav/DAVResourceAccess.hxx index 87e306d94e02..53a98847078b 100644 --- a/ucb/source/ucp/webdav/DAVResourceAccess.hxx +++ b/ucb/source/ucp/webdav/DAVResourceAccess.hxx @@ -209,12 +209,14 @@ public: com::sun::star::ucb::XCommandEnvironment > & xEnv ) throw( DAVException ); +#if 0 // currently not used, but please don't remove code // refresh existing lock. sal_Int64 LOCK( sal_Int64 nTimeout, const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) throw ( DAVException ); +#endif void UNLOCK( const com::sun::star::uno::Reference< diff --git a/ucb/source/ucp/webdav/NeonSession.cxx b/ucb/source/ucp/webdav/NeonSession.cxx index 0d979ae72ada..8fc1730ba018 100644 --- a/ucb/source/ucp/webdav/NeonSession.cxx +++ b/ucb/source/ucp/webdav/NeonSession.cxx @@ -435,7 +435,7 @@ extern "C" int NeonSession_CertificationNotify( void *userdata, char * dn = ne_ssl_readable_dname( ne_ssl_cert_subject( cert ) ); rtl::OUString cert_subject( dn, strlen( dn ), RTL_TEXTENCODING_UTF8, 0 ); - free( dn ); + ne_free( dn ); security::CertificateContainerStatus certificateContainer( xCertificateContainer->hasCertificate( diff --git a/ucb/source/ucp/webdav/NeonUri.cxx b/ucb/source/ucp/webdav/NeonUri.cxx index f71056ba83a9..774faa06b9dd 100644 --- a/ucb/source/ucp/webdav/NeonUri.cxx +++ b/ucb/source/ucp/webdav/NeonUri.cxx @@ -32,6 +32,7 @@ #include <rtl/uri.hxx> #include <rtl/ustring.hxx> #include <rtl/ustrbuf.hxx> +#include "ne_alloc.h" #include "NeonUri.hxx" #include "DAVException.hxx" @@ -127,7 +128,7 @@ NeonUri::NeonUri( const ne_uri * inUri ) throw DAVException( DAVException::DAV_INVALID_ARG ); init( rtl::OString( uri ), inUri ); - free( uri ); + ne_free( uri ); calculateURI(); } diff --git a/uui/source/lockfailed.src b/uui/source/lockfailed.src index 66d6a1d4bb7e..1a3e1534d0ff 100644 --- a/uui/source/lockfailed.src +++ b/uui/source/lockfailed.src @@ -37,7 +37,7 @@ String STR_LOCKFAILED_TITLE }; String STR_LOCKFAILED_MSG { - Text [ en-US ] = "The file could not be locked for exclusive access by %PRODUCTNAME, due to missing permission to created a lock file on that file location."; + Text [ en-US ] = "The file could not be locked for exclusive access by %PRODUCTNAME, due to missing permission to create a lock file on that file location."; }; String STR_LOCKFAILED_DONTSHOWAGAIN { diff --git a/vcl/aqua/source/gdi/salatsuifontutils.cxx b/vcl/aqua/source/gdi/salatsuifontutils.cxx index 1566f0961f54..8281c41ceeab 100644 --- a/vcl/aqua/source/gdi/salatsuifontutils.cxx +++ b/vcl/aqua/source/gdi/salatsuifontutils.cxx @@ -217,9 +217,6 @@ static bool GetDevFontAttributes( ATSUFontID nFontID, ImplDevFontAttributes& rDF // all scalable fonts on this platform are subsettable rDFA.mbSubsettable = true; rDFA.mbEmbeddable = false; - // TODO: these members are needed only for our X11 platform targets - rDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - rDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; // prepare iterating over all name strings of the font ItemCount nFontNameCount = 0; diff --git a/vcl/inc/vcl/fontmanager.hxx b/vcl/inc/vcl/fontmanager.hxx index 7e1733b49bca..6ebd777f1c61 100644 --- a/vcl/inc/vcl/fontmanager.hxx +++ b/vcl/inc/vcl/fontmanager.hxx @@ -49,6 +49,7 @@ // forward declarations namespace utl { class MultiAtomProvider; } // see unotools/atom.hxx class FontSubsetInfo; +class ImplFontOptions; namespace psp { class PPDParser; // see ppdparser.hxx @@ -162,8 +163,6 @@ struct FastPrintFontInfo weight::type m_eWeight; pitch::type m_ePitch; rtl_TextEncoding m_aEncoding; - fcstatus::type m_eEmbeddedbitmap; - fcstatus::type m_eAntialias; bool m_bSubsettable; bool m_bEmbeddable; @@ -175,9 +174,7 @@ struct FastPrintFontInfo m_eWidth( width::Unknown ), m_eWeight( weight::Unknown ), m_ePitch( pitch::Unknown ), - m_aEncoding( RTL_TEXTENCODING_DONTKNOW ), - m_eEmbeddedbitmap( fcstatus::isunset ), - m_eAntialias( fcstatus::isunset ) + m_aEncoding( RTL_TEXTENCODING_DONTKNOW ) {} }; @@ -294,9 +291,6 @@ class VCL_DLLPUBLIC PrintFontManager bool m_bHaveVerticalSubstitutedGlyphs; bool m_bUserOverride; - fcstatus::type m_eEmbeddedbitmap; - fcstatus::type m_eAntialias; - std::map< sal_Unicode, sal_Int32 > m_aEncodingVector; std::map< sal_Unicode, rtl::OString > m_aNonEncoded; @@ -736,10 +730,11 @@ public: false else */ bool matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale ); + bool getFontOptions( const FastPrintFontInfo&, int nSize, void (*subcallback)(void*), ImplFontOptions& rResult ) const; rtl::OUString Substitute( const rtl::OUString& rFontName, rtl::OUString& rMissingCodes, - const rtl::OString& rLangAttrib, italic::type eItalic, weight::type eWeight, - width::type eWidth, pitch::type ePitch) const; + const rtl::OString& rLangAttrib, italic::type& rItalic, weight::type& rWeight, + width::type& rWidth, pitch::type& rPitch) const; bool hasFontconfig() const { return m_bFontconfigSuccess; } int FreeTypeCharIndex( void *pFace, sal_uInt32 aChar ); diff --git a/vcl/inc/vcl/glyphcache.hxx b/vcl/inc/vcl/glyphcache.hxx index 8c7d6e41b168..fa3e99f2373f 100644 --- a/vcl/inc/vcl/glyphcache.hxx +++ b/vcl/inc/vcl/glyphcache.hxx @@ -39,6 +39,7 @@ class ServerFontLayoutEngine; class ServerFontLayout; class ExtraKernInfo; struct ImplKernPairData; +class ImplFontOptions; #include <tools/gen.hxx> #include <hash_map> @@ -59,8 +60,8 @@ class ServerFontLayout; class VCL_DLLPUBLIC GlyphCache { public: - GlyphCache( GlyphCachePeer& ); - ~GlyphCache(); + explicit GlyphCache( GlyphCachePeer& ); + /*virtual*/ ~GlyphCache(); static GlyphCache& GetInstance(); void LoadFonts(); @@ -74,6 +75,7 @@ public: ServerFont* CacheFont( const ImplFontSelectData& ); void UncacheFont( ServerFont& ); + void InvalidateAllGlyphs(); protected: GlyphCachePeer& mrPeer; @@ -96,7 +98,6 @@ private: struct IFSD_Hash{ size_t operator()( const ImplFontSelectData& ) const; }; typedef ::std::hash_map<ImplFontSelectData,ServerFont*,IFSD_Hash,IFSD_Equal > FontList; FontList maFontList; - ULONG mnMaxSize; // max overall cache size in bytes mutable ULONG mnBytesUsed; mutable long mnLruIndex; @@ -179,6 +180,7 @@ public: virtual bool TestFont() const { return true; } virtual void* GetFtFace() const { return 0; } virtual int GetLoadFlags() const { return 0; } + virtual void SetFontOptions( const ImplFontOptions&) {} virtual bool NeedsArtificialBold() const { return false; } virtual bool NeedsArtificialItalic() const { return false; } @@ -208,7 +210,7 @@ public: protected: friend class GlyphCache; friend class ServerFontLayout; - ServerFont( const ImplFontSelectData& ); + explicit ServerFont( const ImplFontSelectData& ); virtual ~ServerFont(); void AddRef() const { ++mnRefCount; } diff --git a/vcl/inc/vcl/impfont.hxx b/vcl/inc/vcl/impfont.hxx index d53785bc691a..6ce9f21500b5 100644 --- a/vcl/inc/vcl/impfont.hxx +++ b/vcl/inc/vcl/impfont.hxx @@ -133,6 +133,41 @@ public: bool operator==( const ImplFontMetric& ) const; }; +// ------------------ +// - ImplFontHints - +// ------------------ + +class ImplFontOptions +{ +public: + FontEmbeddedBitmap meEmbeddedBitmap; // whether the embedded bitmaps should be used + FontAntiAlias meAntiAlias; // whether the font should be antialiased + FontAutoHint meAutoHint; // whether the font should be autohinted + FontHinting meHinting; // whether the font should be hinted + FontHintStyle meHintStyle; // type of font hinting to be used +public: + ImplFontOptions() : + meEmbeddedBitmap(EMBEDDEDBITMAP_DONTKNOW), + meAntiAlias(ANTIALIAS_DONTKNOW), + meAutoHint(AUTOHINT_DONTKNOW), + meHinting(HINTING_DONTKNOW), + meHintStyle(HINT_SLIGHT) + {} + ImplFontOptions( FontEmbeddedBitmap eEmbeddedBitmap, FontAntiAlias eAntiAlias, + FontAutoHint eAutoHint, FontHinting eHinting, FontHintStyle eHintStyle) : + meEmbeddedBitmap(eEmbeddedBitmap), + meAntiAlias(eAntiAlias), + meAutoHint(eAutoHint), + meHinting(eHinting), + meHintStyle(eHintStyle) + {} + FontAutoHint GetUseAutoHint() const { return meAutoHint; } + FontHintStyle GetHintStyle() const { return meHintStyle; } + bool DontUseEmbeddedBitmaps() const { return meEmbeddedBitmap == EMBEDDEDBITMAP_FALSE; } + bool DontUseAntiAlias() const { return meAntiAlias == ANTIALIAS_FALSE; } + bool DontUseHinting() const { return (meHinting == HINTING_FALSE) || (GetHintStyle() == HINT_NONE); } +}; + // ------------------- // - ImplFontCharMap - // ------------------- diff --git a/vcl/inc/vcl/outdev.hxx b/vcl/inc/vcl/outdev.hxx index 101a368b0586..be5c0a880ed7 100644 --- a/vcl/inc/vcl/outdev.hxx +++ b/vcl/inc/vcl/outdev.hxx @@ -77,6 +77,7 @@ class AlphaMask; class FontCharMap; class SalLayout; class ImplLayoutArgs; +class ImplFontAttributes; class VirtualDevice; namespace com { @@ -541,7 +542,6 @@ public: SAL_DLLPRIVATE static FontEmphasisMark ImplGetEmphasisMarkStyle( const Font& rFont ); SAL_DLLPRIVATE static BOOL ImplIsUnderlineAbove( const Font& ); - // tells whether this output device is RTL in an LTR UI or LTR in a RTL UI SAL_DLLPRIVATE bool ImplIsAntiparallel() const ; diff --git a/vcl/inc/vcl/outfont.hxx b/vcl/inc/vcl/outfont.hxx index 87c20ebfd7f9..995fcd6009ff 100644 --- a/vcl/inc/vcl/outfont.hxx +++ b/vcl/inc/vcl/outfont.hxx @@ -94,8 +94,6 @@ public: // TODO: create matching interface class bool IsDeviceFont() const { return mbDevice; } bool IsEmbeddable() const { return mbEmbeddable; } bool IsSubsettable() const { return mbSubsettable; } - FontEmbeddedBitmap UseEmbeddedBitmap() const { return meEmbeddedBitmap; } - FontAntiAlias UseAntiAlias() const { return meAntiAlias; } public: // TODO: hide members behind accessor methods String maMapNames; // List of family name aliass separated with ';' @@ -104,8 +102,6 @@ public: // TODO: hide members behind accessor methods bool mbDevice; // true: built in font bool mbSubsettable; // true: a subset of the font can be created bool mbEmbeddable; // true: the font can be embedded - FontEmbeddedBitmap meEmbeddedBitmap; // whether the embedded bitmaps should be used - FontAntiAlias meAntiAlias; // whether the font should be antialiased }; // ---------------- @@ -339,15 +335,17 @@ public: // TODO: make data members private short mnOrientation; // text angle in 3600 system bool mbInit; // true if maMetric member is valid - void AddFallbackForUnicode( sal_UCS4, const String& rFontName ); - bool GetFallbackForUnicode( sal_UCS4, String* pFontName ) const; - void IgnoreFallbackForUnicode( sal_UCS4, const String& rFontName ); + void AddFallbackForUnicode( sal_UCS4, FontWeight eWeight, const String& rFontName ); + bool GetFallbackForUnicode( sal_UCS4, FontWeight eWeight, String* pFontName ) const; + void IgnoreFallbackForUnicode( sal_UCS4, FontWeight eWeight, const String& rFontName ); private: // cache of Unicode characters and replacement font names // TODO: a fallback map can be shared with many other ImplFontEntries // TODO: at least the ones which just differ in orientation, stretching or height - typedef ::std::hash_map<sal_UCS4,String> UnicodeFallbackList; + typedef ::std::pair<sal_UCS4,FontWeight> GFBCacheKey; + struct GFBCacheKey_Hash{ size_t operator()( const GFBCacheKey& ) const; }; + typedef ::std::hash_map<GFBCacheKey,String,GFBCacheKey_Hash> UnicodeFallbackList; UnicodeFallbackList* mpUnicodeFallbackList; }; diff --git a/vcl/inc/vcl/salgdi.hxx b/vcl/inc/vcl/salgdi.hxx index f72c4df57481..02e9efbc0f94 100644 --- a/vcl/inc/vcl/salgdi.hxx +++ b/vcl/inc/vcl/salgdi.hxx @@ -234,9 +234,10 @@ public: void ReleaseFonts() { SetFont( NULL, 0 ); } // get the current font's metrics virtual void GetFontMetric( ImplFontMetricData* ) = 0; + // get kernign pairs of the current font // return only PairCount if (pKernPairs == NULL) - virtual ULONG GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ) = 0; + virtual ULONG GetKernPairs( ULONG nMaxPairCount, ImplKernPairData* ) = 0; // get the repertoire of the current font virtual ImplFontCharMap* GetImplFontCharMap() const = 0; // graphics must fill supplied font list diff --git a/vcl/inc/vcl/settings.hxx b/vcl/inc/vcl/settings.hxx index e55c2a53345b..24fd30750501 100644 --- a/vcl/inc/vcl/settings.hxx +++ b/vcl/inc/vcl/settings.hxx @@ -437,6 +437,7 @@ private: ULONG mnPreferredSymbolsStyle; USHORT mnSkipDisabledInMenus; Wallpaper maWorkspaceGradient; + const void* mpFontOptions; }; #define DEFAULT_WORKSPACE_GRADIENT_START_COLOR Color( 0xa3, 0xae, 0xb8 ) @@ -754,6 +755,11 @@ public: BOOL GetSkipDisabledInMenus() const { return (BOOL) mpData->mnSkipDisabledInMenus; } + void SetCairoFontOptions( const void *pOptions ) + { CopyData(); mpData->mpFontOptions = pOptions; } + const void* GetCairoFontOptions() const + { return mpData->mpFontOptions; } + void SetAppFont( const Font& rFont ) { CopyData(); mpData->maAppFont = rFont; } const Font& GetAppFont() const diff --git a/vcl/inc/vcl/vclenum.hxx b/vcl/inc/vcl/vclenum.hxx index ded36cc163f0..a34c633479e7 100644 --- a/vcl/inc/vcl/vclenum.hxx +++ b/vcl/inc/vcl/vclenum.hxx @@ -281,6 +281,27 @@ enum FontAntiAlias { ANTIALIAS_DONTKNOW, ANTIALIAS_FALSE, ANTIALIAS_TRUE }; #endif +#ifndef ENUM_FONTAUTOHINT_DECLARED +#define ENUM_FONTAUTOHINT_DECLARED + +enum FontAutoHint { AUTOHINT_DONTKNOW, AUTOHINT_FALSE, AUTOHINT_TRUE }; + +#endif + +#ifndef ENUM_FONTHINTING_DECLARED +#define ENUM_FONTHINTING_DECLARED + +enum FontHinting { HINTING_DONTKNOW, HINTING_FALSE, HINTING_TRUE }; + +#endif + +#ifndef ENUM_FONTHINTSTYLE_DECLARED +#define ENUM_FONTHINTSTYLE_DECLARED + +enum FontHintStyle { HINT_NONE, HINT_SLIGHT, HINT_MEDIUM, HINT_FULL }; + +#endif + // ------------------------------------------------------------ #ifndef ENUM_KEYFUNCTYPE_DECLARED diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx index 1aebe5913959..5ad3f6787461 100644 --- a/vcl/source/app/settings.cxx +++ b/vcl/source/app/settings.cxx @@ -433,6 +433,7 @@ ImplStyleData::ImplStyleData() mnToolbarIconSize = STYLE_TOOLBAR_ICONSIZE_UNKNOWN; mnSymbolsStyle = STYLE_SYMBOLS_AUTO; mnPreferredSymbolsStyle = STYLE_SYMBOLS_AUTO; + mpFontOptions = NULL; SetStandardStyles(); } @@ -539,6 +540,7 @@ ImplStyleData::ImplStyleData( const ImplStyleData& rData ) : mnToolbarIconSize = rData.mnToolbarIconSize; mnSymbolsStyle = rData.mnSymbolsStyle; mnPreferredSymbolsStyle = rData.mnPreferredSymbolsStyle; + mpFontOptions = rData.mpFontOptions; } // ----------------------------------------------------------------------- diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index 895a98dfaf1a..6ca90540d8ee 100644 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -68,6 +68,9 @@ #ifdef ENABLE_GRAPHITE #include <vcl/graphite_features.hxx> #endif +#ifdef USE_BUILTIN_RASTERIZER +#include <vcl/glyphcache.hxx> +#endif #include <vcl/unohelp.hxx> #include <pdfwriter_impl.hxx> @@ -995,21 +998,28 @@ ImplFontEntry::~ImplFontEntry() // ----------------------------------------------------------------------- -inline void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, const String& rFontName ) +size_t ImplFontEntry::GFBCacheKey_Hash::operator()( const GFBCacheKey& rData ) const +{ + std::hash<sal_UCS4> a; + std::hash<int > b; + return a(rData.first) ^ b(rData.second); +} + +inline void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const String& rFontName ) { if( !mpUnicodeFallbackList ) mpUnicodeFallbackList = new UnicodeFallbackList; - (*mpUnicodeFallbackList)[cChar] = rFontName; + (*mpUnicodeFallbackList)[ GFBCacheKey(cChar,eWeight) ] = rFontName; } // ----------------------------------------------------------------------- -inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, String* pFontName ) const +inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, String* pFontName ) const { if( !mpUnicodeFallbackList ) return false; - UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( cChar ); + UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) ); if( it == mpUnicodeFallbackList->end() ) return false; @@ -1019,10 +1029,10 @@ inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, String* pFontN // ----------------------------------------------------------------------- -inline void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, const String& rFontName ) +inline void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const String& rFontName ) { // DBG_ASSERT( mpUnicodeFallbackList, "ImplFontEntry::IgnoreFallbackForUnicode no list" ); - UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( cChar ); + UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) ); // DBG_ASSERT( it != mpUnicodeFallbackList->end(), "ImplFontEntry::IgnoreFallbackForUnicode no match" ); if( it == mpUnicodeFallbackList->end() ) return; @@ -1417,7 +1427,7 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& while( nStrIndex < rMissingCodes.getLength() ) { cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); - bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, &rFontSelData.maSearchName ); + bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ); // ignore entries which don't have a fallback if( !bCached || (rFontSelData.maSearchName.Len() != 0) ) break; @@ -1433,7 +1443,7 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& while( nStrIndex < rMissingCodes.getLength() ) { cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); - bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, &aFontName ); + bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &aFontName ); if( !bCached || (rFontSelData.maSearchName != aFontName) ) pRemainingCodes[ nRemainingLength++ ] = cChar; } @@ -1452,8 +1462,8 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& // cache the result even if there was no match for(;;) { - if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, &rFontSelData.maSearchName ) ) - rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.maSearchName ); + if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) ) + rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); if( nStrIndex >= aOldMissingCodes.getLength() ) break; cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex ); @@ -1464,7 +1474,7 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); ) { cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); - rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.maSearchName ); + rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); } } } @@ -2780,6 +2790,11 @@ void ImplFontCache::Invalidate() maFontInstanceList.clear(); DBG_ASSERT( (mnRef0Count==0), "ImplFontCache::Invalidate() - mnRef0Count non-zero" ); + +#ifdef USE_BUILTIN_RASTERIZER + // TODO: eventually move into SalGraphics layer + GlyphCache::GetInstance().InvalidateAllGlyphs(); +#endif } // ======================================================================= diff --git a/vcl/source/glyphs/gcach_ftyp.cxx b/vcl/source/glyphs/gcach_ftyp.cxx index a337f2553ff7..ebdd59f517af 100644 --- a/vcl/source/glyphs/gcach_ftyp.cxx +++ b/vcl/source/glyphs/gcach_ftyp.cxx @@ -38,8 +38,6 @@ #include "vcl/svapp.hxx" #include "vcl/outfont.hxx" #include "vcl/impfont.hxx" -#include "vcl/bitmap.hxx" -#include "vcl/bmpacc.hxx" #include "tools/poly.hxx" #include "basegfx/matrix/b2dhommatrix.hxx" @@ -80,7 +78,7 @@ typedef FT_Vector* FT_Vector_CPtr; // TODO: move file mapping stuff to OSL #if defined(UNX) #if !defined(HPUX) - // PORTERS: dlfcn is used for code dependend on FT version + // PORTERS: dlfcn is used for getting symbols from FT versions newer than baseline #include <dlfcn.h> #endif #include <unistd.h> @@ -93,10 +91,6 @@ typedef FT_Vector* FT_Vector_CPtr; #define strncasecmp strnicmp #endif -#include "vcl/svapp.hxx" -#include "vcl/settings.hxx" -#include "i18npool/lang.h" - typedef const unsigned char* CPU8; inline sal_uInt16 NEXT_U16( CPU8& p ) { p+=2; return (p[-2]<<8)|p[-1]; } inline sal_Int16 NEXT_S16( CPU8& p ) { return (sal_Int16)NEXT_U16(p); } @@ -623,9 +617,6 @@ long FreetypeManager::AddFontDir( const String& rUrlName ) aDFA.mbSubsettable= false; aDFA.mbEmbeddable = false; - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - FT_Done_Face( aFaceFT ); AddFontFile( aCFileName, nFaceNum, ++mnNextFontId, aDFA, NULL ); ++nCount; @@ -705,6 +696,7 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn : ServerFont( rFSD ), mnPrioEmbedded(nDefaultPrioEmbedded), mnPrioAntiAlias(nDefaultPrioAntiAlias), + mnPrioAutoHint(nDefaultPrioAutoHint), mpFontInfo( pFI ), maFaceFT( NULL ), maSizeFT( NULL ), @@ -838,46 +830,71 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn mbArtItalic = (rFSD.meItalic != ITALIC_NONE && pFI->GetFontAttributes().GetSlant() == ITALIC_NONE); mbArtBold = (rFSD.meWeight > WEIGHT_MEDIUM && pFI->GetFontAttributes().GetWeight() <= WEIGHT_MEDIUM); - - //static const int TT_CODEPAGE_RANGE_874 = (1L << 16); // Thai - //static const int TT_CODEPAGE_RANGE_932 = (1L << 17); // JIS/Japan - //static const int TT_CODEPAGE_RANGE_936 = (1L << 18); // Chinese: Simplified - //static const int TT_CODEPAGE_RANGE_949 = (1L << 19); // Korean Wansung - //static const int TT_CODEPAGE_RANGE_950 = (1L << 20); // Chinese: Traditional - //static const int TT_CODEPAGE_RANGE_1361 = (1L << 21); // Korean Johab - static const int TT_CODEPAGE_RANGES1_CJKT = 0x3F0000; // all of the above - const TT_OS2* pOs2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 ); - if ((pOs2) && (pOs2->ulCodePageRange1 & TT_CODEPAGE_RANGES1_CJKT ) + mbUseGamma = false; + if( mbArtBold ) + { + //static const int TT_CODEPAGE_RANGE_874 = (1L << 16); // Thai + //static const int TT_CODEPAGE_RANGE_932 = (1L << 17); // JIS/Japan + //static const int TT_CODEPAGE_RANGE_936 = (1L << 18); // Chinese: Simplified + //static const int TT_CODEPAGE_RANGE_949 = (1L << 19); // Korean Wansung + //static const int TT_CODEPAGE_RANGE_950 = (1L << 20); // Chinese: Traditional + //static const int TT_CODEPAGE_RANGE_1361 = (1L << 21); // Korean Johab + static const int TT_CODEPAGE_RANGES1_CJKT = 0x3F0000; // all of the above + const TT_OS2* pOs2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 ); + if ((pOs2) && (pOs2->ulCodePageRange1 & TT_CODEPAGE_RANGES1_CJKT ) && rFSD.mnHeight < 20) mbUseGamma = true; - else - mbUseGamma = false; + } + + if( ((mnCos != 0) && (mnSin != 0)) || (mnPrioEmbedded <= 0) ) + mnLoadFlags |= FT_LOAD_NO_BITMAP; +} + +void FreetypeServerFont::SetFontOptions( const ImplFontOptions& rFontOptions) +{ + FontAutoHint eHint = rFontOptions.GetUseAutoHint(); + if( eHint == AUTOHINT_DONTKNOW ) + eHint = mbUseGamma ? AUTOHINT_TRUE : AUTOHINT_FALSE; - if (mbUseGamma) + if( eHint == AUTOHINT_TRUE ) mnLoadFlags |= FT_LOAD_FORCE_AUTOHINT; if( (mnSin != 0) && (mnCos != 0) ) // hinting for 0/90/180/270 degrees only mnLoadFlags |= FT_LOAD_NO_HINTING; mnLoadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; //#88334# - if (mpFontInfo->DontUseAntiAlias()) - mnPrioAntiAlias = 0; - if (mpFontInfo->DontUseEmbeddedBitmaps()) - mnPrioEmbedded = 0; + if( rFontOptions.DontUseAntiAlias() ) + mnPrioAntiAlias = 0; + if( rFontOptions.DontUseEmbeddedBitmaps() ) + mnPrioEmbedded = 0; + if( rFontOptions.DontUseHinting() ) + mnPrioAutoHint = 0; #if (FTVERSION >= 2005) || defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) - if( nDefaultPrioAutoHint <= 0 ) + if( mnPrioAutoHint <= 0 ) #endif mnLoadFlags |= FT_LOAD_NO_HINTING; -#ifdef FT_LOAD_TARGET_LIGHT - // enable "light hinting" if available +#if defined(FT_LOAD_TARGET_LIGHT) && defined(FT_LOAD_TARGET_NORMAL) if( !(mnLoadFlags & FT_LOAD_NO_HINTING) && (nFTVERSION >= 2103)) - mnLoadFlags |= FT_LOAD_TARGET_LIGHT; + { + mnLoadFlags |= FT_LOAD_TARGET_NORMAL; + switch( rFontOptions.GetHintStyle() ) + { + case HINT_NONE: + mnLoadFlags |= FT_LOAD_NO_HINTING; + break; + case HINT_SLIGHT: + mnLoadFlags |= FT_LOAD_TARGET_LIGHT; + break; + case HINT_MEDIUM: + break; + case HINT_FULL: + default: + break; + } + } #endif - - if( ((mnCos != 0) && (mnSin != 0)) || (mnPrioEmbedded <= 0) ) - mnLoadFlags |= FT_LOAD_NO_BITMAP; } // ----------------------------------------------------------------------- @@ -1231,13 +1248,15 @@ int FreetypeServerFont::FixupGlyphIndex( int nGlyphIndex, sal_UCS4 aChar ) const } } -#if !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) +#if 0 // #95556# autohinting not yet optimized for non-western glyph styles if( !(mnLoadFlags & (FT_LOAD_NO_HINTING | FT_LOAD_FORCE_AUTOHINT) ) && ( (aChar >= 0x0600 && aChar < 0x1E00) // south-east asian + arabic ||(aChar >= 0x2900 && aChar < 0xD800) // CJKV ||(aChar >= 0xF800) ) ) // presentation + symbols + { nGlyphFlags |= GF_UNHINTED; + } #endif if( nGlyphIndex != 0 ) @@ -1377,13 +1396,13 @@ bool FreetypeServerFont::GetGlyphBitmap1( int nGlyphIndex, RawBitmap& rRawBitmap nLoadFlags |= FT_LOAD_NO_BITMAP; #if (FTVERSION >= 2002) - // for 0/90/180/270 degree fonts enable autohinting even if not advisable + // for 0/90/180/270 degree fonts enable hinting even if not advisable // non-hinted and non-antialiased bitmaps just look too ugly - if( (mnCos==0 || mnSin==0) && (nDefaultPrioAutoHint > 0) ) + if( (mnCos==0 || mnSin==0) && (mnPrioAutoHint > 0) ) nLoadFlags &= ~FT_LOAD_NO_HINTING; #endif - if( mnPrioEmbedded <= nDefaultPrioAutoHint ) + if( mnPrioEmbedded <= mnPrioAutoHint ) nLoadFlags |= FT_LOAD_NO_BITMAP; FT_Error rc = -1; @@ -1548,7 +1567,7 @@ bool FreetypeServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap // autohinting in FT<=2.0.4 makes antialiased glyphs look worse nLoadFlags |= FT_LOAD_NO_HINTING; #else - if( (nGlyphFlags & GF_UNHINTED) || (nDefaultPrioAutoHint < mnPrioAntiAlias) ) + if( (nGlyphFlags & GF_UNHINTED) || (mnPrioAutoHint < mnPrioAntiAlias) ) nLoadFlags |= FT_LOAD_NO_HINTING; #endif diff --git a/vcl/source/glyphs/gcach_ftyp.hxx b/vcl/source/glyphs/gcach_ftyp.hxx index 2a181b494c9f..5ebe70bcbdf9 100644 --- a/vcl/source/glyphs/gcach_ftyp.hxx +++ b/vcl/source/glyphs/gcach_ftyp.hxx @@ -33,6 +33,7 @@ #include <ft2build.h> #include FT_FREETYPE_H + class FreetypeServerFont; struct FT_GlyphRec_; @@ -85,10 +86,6 @@ public: int GetFaceNum() const { return mnFaceNum; } int GetSynthetic() const { return mnSynthetic; } sal_IntPtr GetFontId() const { return mnFontId; } - bool DontUseAntiAlias() const - { return maDevFontAttributes.UseAntiAlias() == ANTIALIAS_FALSE; } - bool DontUseEmbeddedBitmaps() const - { return maDevFontAttributes.UseEmbeddedBitmap() == EMBEDDEDBITMAP_FALSE; } bool IsSymbolFont() const { return maDevFontAttributes.IsSymbolFont(); } const ImplFontAttributes& GetFontAttributes() const { return maDevFontAttributes; } @@ -178,6 +175,7 @@ public: virtual int GetFontFaceNum() const { return mpFontInfo->GetFaceNum(); } virtual bool TestFont() const; virtual void* GetFtFace() const; + virtual void SetFontOptions( const ImplFontOptions&); virtual int GetLoadFlags() const { return (mnLoadFlags & ~FT_LOAD_IGNORE_TRANSFORM); } virtual bool NeedsArtificialBold() const { return mbArtBold; } virtual bool NeedsArtificialItalic() const { return mbArtItalic; } @@ -213,6 +211,7 @@ private: int mnWidth; int mnPrioEmbedded; int mnPrioAntiAlias; + int mnPrioAutoHint; FtFontInfo* mpFontInfo; FT_Int mnLoadFlags; double mfStretch; diff --git a/vcl/source/glyphs/glyphcache.cxx b/vcl/source/glyphs/glyphcache.cxx index 34133a39ac95..ea0f18896b7a 100644 --- a/vcl/source/glyphs/glyphcache.cxx +++ b/vcl/source/glyphs/glyphcache.cxx @@ -69,13 +69,22 @@ GlyphCache::GlyphCache( GlyphCachePeer& rPeer ) GlyphCache::~GlyphCache() { -// TODO: -// for( FontList::iterator it = maFontList.begin(); it != maFontList.end(); ++it ) -// delete const_cast<ServerFont*>( it->second ); + InvalidateAllGlyphs(); if( mpFtManager ) delete mpFtManager; } +// ----------------------------------------------------------------------- + +void GlyphCache::InvalidateAllGlyphs() +{ +#if 0 // TODO: implement uncaching of all glyph shapes and metrics + for( FontList::iterator it = maFontList.begin(); it != maFontList.end(); ++it ) + delete const_cast<ServerFont*>( it->second ); + maFontList.clear(); + mpCurrentGCFont = NULL; +#endif +} // ----------------------------------------------------------------------- @@ -582,3 +591,4 @@ int ExtraKernInfo::GetUnscaledKernValue( sal_Unicode cLeft, sal_Unicode cRight ) } // ======================================================================= + diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index 372d10fa5aaf..869189fb1415 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -45,6 +45,8 @@ #include "saldisp.hxx" #include "vcl/svapp.hxx" +typedef struct _cairo_font_options cairo_font_options_t; + // initialize statics BOOL GtkSalGraphics::bThemeChanged = TRUE; BOOL GtkSalGraphics::bNeedPixmapPaint = FALSE; @@ -3469,12 +3471,25 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings ) // preferred icon style gchar* pIconThemeName = NULL; g_object_get( gtk_settings_get_default(), "gtk-icon-theme-name", &pIconThemeName, (char *)NULL ); - aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii(pIconThemeName) ); - g_free (pIconThemeName); + aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii( pIconThemeName ) ); + g_free( pIconThemeName ); // FIXME: need some way of fetching toolbar icon size. // aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_SMALL ); + const cairo_font_options_t* pNewOptions = NULL; + if( GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), m_nScreen ) ) + { +//#if !GTK_CHECK_VERSION(2,8,1) +#if !GTK_CHECK_VERSION(2,9,0) + static cairo_font_options_t* (*gdk_screen_get_font_options)(GdkScreen*) = + (cairo_font_options_t*(*)(GdkScreen*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_screen_get_font_options" ); + if( gdk_screen_get_font_options != NULL ) +#endif + pNewOptions = gdk_screen_get_font_options( pScreen ); + } + aStyleSet.SetCairoFontOptions( pNewOptions ); + // finally update the collected settings rSettings.SetStyleSettings( aStyleSet ); diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx index 5d7fcabb7c8f..ba42cfc5ae82 100644 --- a/vcl/unx/gtk/window/gtkframe.cxx +++ b/vcl/unx/gtk/window/gtkframe.cxx @@ -3124,10 +3124,13 @@ void GtkSalFrame::signalStyleSet( GtkWidget*, GtkStyle* pPrevious, gpointer fram // redraw itself to adjust to the new style // where there IS no new style resulting in tremendous unnecessary flickering if( pPrevious != NULL ) + { // signalStyleSet does NOT usually have the gdk lock // so post user event to safely dispatch the SALEVENT_SETTINGSCHANGED // note: settings changed for multiple frames is avoided in winproc.cxx ImplHandleSettings pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_SETTINGSCHANGED ); + pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_FONTCHANGED ); + } /* #i64117# gtk sets a nice background pixmap * but we actually don't really want that, so save diff --git a/vcl/unx/headless/svpgdi.cxx b/vcl/unx/headless/svpgdi.cxx index 114bd4c8a5bc..e65c9faf1432 100644 --- a/vcl/unx/headless/svpgdi.cxx +++ b/vcl/unx/headless/svpgdi.cxx @@ -584,3 +584,4 @@ bool SvpSalGraphics::supportsOperation( OutDevSupportType ) const { return false; } + diff --git a/vcl/unx/headless/svpgdi.hxx b/vcl/unx/headless/svpgdi.hxx index 9e25b67394e7..132dafaa9adf 100644 --- a/vcl/unx/headless/svpgdi.hxx +++ b/vcl/unx/headless/svpgdi.hxx @@ -170,3 +170,4 @@ public: }; #endif + diff --git a/vcl/unx/headless/svppspgraphics.cxx b/vcl/unx/headless/svppspgraphics.cxx index 353b10467d40..7f551051c1a7 100644 --- a/vcl/unx/headless/svppspgraphics.cxx +++ b/vcl/unx/headless/svppspgraphics.cxx @@ -1160,32 +1160,6 @@ ImplDevFontAttributes PspGraphics::Info2DevFontAttributes( const psp::FastPrintF aDFA.mePitch = ToFontPitch (rInfo.m_ePitch); aDFA.mbSymbolFlag = (rInfo.m_aEncoding == RTL_TEXTENCODING_SYMBOL); - switch (rInfo.m_eEmbeddedbitmap) - { - default: - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - break; - case psp::fcstatus::istrue: - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_TRUE; - break; - case psp::fcstatus::isfalse: - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_FALSE; - break; - } - - switch (rInfo.m_eAntialias) - { - default: - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - break; - case psp::fcstatus::istrue: - aDFA.meAntiAlias = ANTIALIAS_TRUE; - break; - case psp::fcstatus::isfalse: - aDFA.meAntiAlias = ANTIALIAS_FALSE; - break; - } - switch( rInfo.m_eType ) { case psp::fonttype::Builtin: diff --git a/vcl/unx/headless/svppspgraphics.hxx b/vcl/unx/headless/svppspgraphics.hxx index 8addbc3de5f7..82ba613615cb 100644 --- a/vcl/unx/headless/svppspgraphics.hxx +++ b/vcl/unx/headless/svppspgraphics.hxx @@ -190,3 +190,4 @@ public: }; #endif // _SVP_PSPGRAPHICS_HXX + diff --git a/vcl/unx/inc/pspgraphics.h b/vcl/unx/inc/pspgraphics.h index 4dce4ee8b06c..2eae73cdaa86 100644 --- a/vcl/unx/inc/pspgraphics.h +++ b/vcl/unx/inc/pspgraphics.h @@ -103,7 +103,7 @@ public: virtual void SetTextColor( SalColor nSalColor ); virtual USHORT SetFont( ImplFontSelectData*, int nFallbackLevel ); virtual void GetFontMetric( ImplFontMetricData* ); - virtual ULONG GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ); + virtual ULONG GetKernPairs( ULONG nMaxPairs, ImplKernPairData* ); virtual ImplFontCharMap* GetImplFontCharMap() const; virtual void GetDevFontList( ImplDevFontList* ); virtual void GetDevFontSubstList( OutputDevice* ); diff --git a/vcl/unx/inc/salgdi.h b/vcl/unx/inc/salgdi.h index 09e85c6840b8..da69f04b6f8f 100644 --- a/vcl/unx/inc/salgdi.h +++ b/vcl/unx/inc/salgdi.h @@ -250,7 +250,7 @@ public: virtual void SetTextColor( SalColor nSalColor ); virtual USHORT SetFont( ImplFontSelectData*, int nFallbackLevel ); virtual void GetFontMetric( ImplFontMetricData* ); - virtual ULONG GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ); + virtual ULONG GetKernPairs( ULONG nMaxPairs, ImplKernPairData* ); virtual ImplFontCharMap* GetImplFontCharMap() const; virtual void GetDevFontList( ImplDevFontList* ); virtual void GetDevFontSubstList( OutputDevice* ); diff --git a/vcl/unx/source/fontmanager/fontcache.cxx b/vcl/unx/source/fontmanager/fontcache.cxx index 803e92d3cb14..db4a7d05e5fc 100644 --- a/vcl/unx/source/fontmanager/fontcache.cxx +++ b/vcl/unx/source/fontmanager/fontcache.cxx @@ -212,9 +212,9 @@ void FontCache::flush() aLine.Append( ';' ); aLine.Append( (*it)->m_bUserOverride ? "1" : "0" ); aLine.Append( ';' ); - aLine.Append( ByteString::CreateFromInt32( (*it)->m_eEmbeddedbitmap ) ); + aLine.Append( ByteString::CreateFromInt32( 0 ) ); aLine.Append( ';' ); - aLine.Append( ByteString::CreateFromInt32( (*it)->m_eAntialias ) ); + aLine.Append( ByteString::CreateFromInt32( 0 ) ); switch( (*it)->m_eType ) { @@ -424,9 +424,6 @@ void FontCache::read() = atoi( pLine + nTokenPos[14] ); pFont->m_bUserOverride = (atoi( pLine + nTokenPos[15] ) != 0); - pFont->m_eEmbeddedbitmap - = (fcstatus::type)atoi(pLine+nTokenPos[16]); - pFont->m_eAntialias = (fcstatus::type)atoi(pLine+nTokenPos[17]); int nStyleTokenNr = 18; switch( eType ) { @@ -558,8 +555,6 @@ void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFo pTo->m_nYMax = pFrom->m_nYMax; pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs; pTo->m_bUserOverride = pFrom->m_bUserOverride; - pTo->m_eEmbeddedbitmap = pFrom->m_eEmbeddedbitmap; - pTo->m_eAntialias = pFrom->m_eAntialias; } /* @@ -621,9 +616,7 @@ bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, Print pRight->m_nXMax != pLeft->m_nXMax || pRight->m_nYMax != pLeft->m_nYMax || pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs || - pRight->m_bUserOverride != pLeft->m_bUserOverride || - pRight->m_eEmbeddedbitmap != pLeft->m_eEmbeddedbitmap || - pRight->m_eAntialias != pLeft->m_eAntialias + pRight->m_bUserOverride != pLeft->m_bUserOverride ) return false; std::list< int >::const_iterator lit, rit; diff --git a/vcl/unx/source/fontmanager/fontconfig.cxx b/vcl/unx/source/fontmanager/fontconfig.cxx index 1d4573518879..18d8a8d85a43 100644 --- a/vcl/unx/source/fontmanager/fontconfig.cxx +++ b/vcl/unx/source/fontmanager/fontconfig.cxx @@ -30,37 +30,45 @@ #include "vcl/fontmanager.hxx" #include "vcl/fontcache.hxx" +#include "vcl/impfont.hxx" using namespace psp; #ifdef ENABLE_FONTCONFIG -#include <fontconfig/fontconfig.h> -#include <ft2build.h> -#include <fontconfig/fcfreetype.h> -// be compatible with fontconfig 2.2.0 release -#ifndef FC_WEIGHT_BOOK - #define FC_WEIGHT_BOOK 75 -#endif -#ifndef FC_EMBEDDED_BITMAP - #define FC_EMBEDDED_BITMAP "embeddedbitmap" -#endif -#ifndef FC_FAMILYLANG - #define FC_FAMILYLANG "familylang" -#endif + #include <fontconfig/fontconfig.h> + #include <ft2build.h> + #include <fontconfig/fcfreetype.h> + // allow compile on baseline (currently with fontconfig 2.2.0) + #ifndef FC_WEIGHT_BOOK // TODO: remove when baseline moves to fc>=2.2.1 + #define FC_WEIGHT_BOOK 75 + #endif + #ifndef FC_EMBEDDED_BITMAP // TODO: remove when baseline moves to fc>=2.3.92 + #define FC_EMBEDDED_BITMAP "embeddedbitmap" + #endif + #ifndef FC_FAMILYLANG // TODO: remove when baseline moves to fc>=2.2.97 + #define FC_FAMILYLANG "familylang" + #endif + #ifndef FC_HINT_STYLE // TODO: remove when baseline moves to fc>=2.2.91 + #define FC_HINT_STYLE "hintstyle" + #define FC_HINT_NONE 0 + #define FC_HINT_SLIGHT 1 + #define FC_HINT_MEDIUM 2 + #define FC_HINT_FULL 3 + #endif #else -typedef void FcConfig; -typedef void FcObjectSet; -typedef void FcPattern; -typedef void FcFontSet; -typedef void FcCharSet; -typedef int FcResult; -typedef int FcBool; -typedef int FcMatchKind; -typedef char FcChar8; -typedef int FcChar32; -typedef unsigned int FT_UInt; -typedef void* FT_Face; -typedef int FcSetName; + typedef void FcConfig; + typedef void FcObjectSet; + typedef void FcPattern; + typedef void FcFontSet; + typedef void FcCharSet; + typedef int FcResult; + typedef int FcBool; + typedef int FcMatchKind; + typedef char FcChar8; + typedef int FcChar32; + typedef unsigned int FT_UInt; + typedef void* FT_Face; + typedef int FcSetName; #endif #include <cstdio> @@ -117,6 +125,7 @@ class FontCfgWrapper FcBool (*m_pFcConfigAppFontAddDir)(FcConfig*, const FcChar8*); FcBool (*m_pFcConfigSubstitute)(FcConfig*,FcPattern*,FcMatchKind); FcBool (*m_pFcPatternAddInteger)(FcPattern*,const char*,int); + FcBool (*m_pFcPatternAddDouble)(FcPattern*,const char*,double); FcBool (*m_pFcPatternAddBool)(FcPattern*,const char*,FcBool); FcBool (*m_pFcPatternAddCharSet)(FcPattern*,const char*,const FcCharSet*); FcBool (*m_pFcPatternAddString)(FcPattern*,const char*,const FcChar8*); @@ -220,6 +229,8 @@ public: { return m_pFcConfigSubstitute( pConfig, pPattern, eKind ); } FcBool FcPatternAddInteger( FcPattern* pPattern, const char* pObject, int nValue ) { return m_pFcPatternAddInteger( pPattern, pObject, nValue ); } + FcBool FcPatternAddDouble( FcPattern* pPattern, const char* pObject, double nValue ) + { return m_pFcPatternAddDouble( pPattern, pObject, nValue ); } FcBool FcPatternAddString( FcPattern* pPattern, const char* pObject, const FcChar8* pString ) { return m_pFcPatternAddString( pPattern, pObject, pString ); } FcBool FcPatternAddBool( FcPattern* pPattern, const char* pObject, bool nValue ) @@ -231,7 +242,9 @@ public: { return m_pFcFreeTypeCharIndex ? m_pFcFreeTypeCharIndex( face, ucs4 ) : 0; } public: // TODO: cleanup - std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aFontconfigNameToLocalized; + FcResult FamilyFromPattern(FcPattern* pPattern, FcChar8 **family); + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aFontNameToLocalized; + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aLocalizedToCanonical; }; oslGenericFunction FontCfgWrapper::loadSymbol( const char* pSymbol ) @@ -321,6 +334,8 @@ FontCfgWrapper::FontCfgWrapper() loadSymbol( "FcConfigSubstitute" ); m_pFcPatternAddInteger = (FcBool(*)(FcPattern*,const char*,int)) loadSymbol( "FcPatternAddInteger" ); + m_pFcPatternAddDouble = (FcBool(*)(FcPattern*,const char*,double)) + loadSymbol( "FcPatternAddDouble" ); m_pFcPatternAddBool = (FcBool(*)(FcPattern*,const char*,FcBool)) loadSymbol( "FcPatternAddBool" ); m_pFcPatternAddCharSet = (FcBool(*)(FcPattern*,const char*,const FcCharSet *)) @@ -371,6 +386,7 @@ FontCfgWrapper::FontCfgWrapper() m_pFcDefaultSubstitute && m_pFcConfigSubstitute && m_pFcPatternAddInteger && + m_pFcPatternAddDouble && m_pFcPatternAddCharSet && m_pFcPatternAddBool && m_pFcPatternAddString @@ -503,53 +519,52 @@ namespace return candidate; } +} +FcResult FontCfgWrapper::FamilyFromPattern(FcPattern* pPattern, FcChar8 **family) +{ + FcChar8 *origfamily; + FcResult eFamilyRes = FcPatternGetString( pPattern, FC_FAMILY, 0, &origfamily ); + *family = origfamily; - FcResult lcl_FamilyFromPattern(FontCfgWrapper& rWrapper, FcPattern* pPattern, FcChar8 **family, - std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > &aFontconfigNameToLocalized) + if( eFamilyRes == FcResultMatch) { - FcChar8 *origfamily; - FcResult eFamilyRes = rWrapper.FcPatternGetString( pPattern, FC_FAMILY, 0, &origfamily ); - *family = origfamily; - - if( eFamilyRes == FcResultMatch) + FcChar8* familylang = NULL; + if (FcPatternGetString( pPattern, FC_FAMILYLANG, 0, &familylang ) == FcResultMatch) { - FcChar8* familylang = NULL; - if (rWrapper.FcPatternGetString( pPattern, FC_FAMILYLANG, 0, &familylang ) == FcResultMatch) + std::vector< lang_and_family > lang_and_families; + lang_and_families.push_back(lang_and_family(familylang, *family)); + int k = 1; + while (1) { - std::vector< lang_and_family > lang_and_families; + if (FcPatternGetString( pPattern, FC_FAMILYLANG, k, &familylang ) != FcResultMatch) + break; + if (FcPatternGetString( pPattern, FC_FAMILY, k, family ) != FcResultMatch) + break; lang_and_families.push_back(lang_and_family(familylang, *family)); - int k = 1; - while (1) - { - if (rWrapper.FcPatternGetString( pPattern, FC_FAMILYLANG, k, &familylang ) != FcResultMatch) - break; - if (rWrapper.FcPatternGetString( pPattern, FC_FAMILY, k, family ) != FcResultMatch) - break; - lang_and_families.push_back(lang_and_family(familylang, *family)); - ++k; - } + ++k; + } - //possible to-do, sort by UILocale instead of process locale - rtl_Locale* pLoc; - osl_getProcessLocale(&pLoc); - localizedsorter aSorter(pLoc); - *family = aSorter.bestname(lang_and_families); + //possible to-do, sort by UILocale instead of process locale + rtl_Locale* pLoc; + osl_getProcessLocale(&pLoc); + localizedsorter aSorter(pLoc); + *family = aSorter.bestname(lang_and_families); - std::vector<lang_and_family>::const_iterator aEnd = lang_and_families.end(); - for (std::vector<lang_and_family>::const_iterator aIter = lang_and_families.begin(); aIter != aEnd; ++aIter) - { - const char *candidate = (const char*)(aIter->second); - if (rtl_str_compare(candidate, (const char*)(*family)) != 0) - aFontconfigNameToLocalized[OString(candidate)] = OString((const char*)(*family)); - } + std::vector<lang_and_family>::const_iterator aEnd = lang_and_families.end(); + for (std::vector<lang_and_family>::const_iterator aIter = lang_and_families.begin(); aIter != aEnd; ++aIter) + { + const char *candidate = (const char*)(aIter->second); + if (rtl_str_compare(candidate, (const char*)(*family)) != 0) + m_aFontNameToLocalized[OString(candidate)] = OString((const char*)(*family)); } + if (rtl_str_compare((const char*)origfamily, (const char*)(*family)) != 0) + m_aLocalizedToCanonical[OString((const char*)(*family))] = OString((const char*)origfamily); } - - return eFamilyRes; } -} + return eFamilyRes; +} /* * PrintFontManager::initFontconfig @@ -562,6 +577,72 @@ bool PrintFontManager::initFontconfig() return true; } +namespace +{ + weight::type convertWeight(int weight) + { + // set weight + if( weight <= FC_WEIGHT_THIN ) + return weight::Thin; + else if( weight <= FC_WEIGHT_ULTRALIGHT ) + return weight::UltraLight; + else if( weight <= FC_WEIGHT_LIGHT ) + return weight::Light; + else if( weight <= FC_WEIGHT_BOOK ) + return weight::SemiLight; + else if( weight <= FC_WEIGHT_NORMAL ) + return weight::Normal; + else if( weight <= FC_WEIGHT_MEDIUM ) + return weight::Medium; + else if( weight <= FC_WEIGHT_SEMIBOLD ) + return weight::SemiBold; + else if( weight <= FC_WEIGHT_BOLD ) + return weight::Bold; + else if( weight <= FC_WEIGHT_ULTRABOLD ) + return weight::UltraBold; + return weight::Black; + } + + italic::type convertSlant(int slant) + { + // set italic + if( slant == FC_SLANT_ITALIC ) + return italic::Italic; + else if( slant == FC_SLANT_OBLIQUE ) + return italic::Oblique; + return italic::Upright; + } + + pitch::type convertSpacing(int spacing) + { + // set pitch + if( spacing == FC_MONO || spacing == FC_CHARCELL ) + return pitch::Fixed; + return pitch::Variable; + } + + width::type convertWidth(int width) + { + if (width == FC_WIDTH_ULTRACONDENSED) + return width::UltraCondensed; + else if (width == FC_WIDTH_EXTRACONDENSED) + return width::ExtraCondensed; + else if (width == FC_WIDTH_CONDENSED) + return width::Condensed; + else if (width == FC_WIDTH_SEMICONDENSED) + return width::SemiCondensed; + else if (width == FC_WIDTH_SEMIEXPANDED) + return width::SemiExpanded; + else if (width == FC_WIDTH_EXPANDED) + return width::Expanded; + else if (width == FC_WIDTH_EXTRAEXPANDED) + return width::ExtraExpanded; + else if (width == FC_WIDTH_ULTRAEXPANDED) + return width::UltraExpanded; + return width::Normal; + } +} + int PrintFontManager::countFontconfigFonts() { int nFonts = 0; @@ -585,18 +666,16 @@ int PrintFontManager::countFontconfigFonts() int weight = 0; int spacing = 0; int nCollectionEntry = -1; - FcBool outline = false, embitmap = true, antialias = true; + FcBool outline = false; FcResult eFileRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FILE, 0, &file ); - FcResult eFamilyRes = lcl_FamilyFromPattern(rWrapper, pFSet->fonts[i], &family, rWrapper.m_aFontconfigNameToLocalized ); + FcResult eFamilyRes = rWrapper.FamilyFromPattern( pFSet->fonts[i], &family ); FcResult eStyleRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_STYLE, 0, &style ); FcResult eSlantRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SLANT, 0, &slant ); FcResult eWeightRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_WEIGHT, 0, &weight ); FcResult eSpacRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SPACING, 0, &spacing ); FcResult eOutRes = rWrapper.FcPatternGetBool( pFSet->fonts[i], FC_OUTLINE, 0, &outline ); FcResult eIndexRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_INDEX, 0, &nCollectionEntry ); - FcResult eEmbeddedBitmap = rWrapper.FcPatternGetBool( pFSet->fonts[i], FC_EMBEDDED_BITMAP, 0, &embitmap ); - FcResult eAntialias = rWrapper.FcPatternGetBool( pFSet->fonts[i], FC_ANTIALIAS, 0, &antialias ); if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch ) continue; @@ -691,60 +770,15 @@ int PrintFontManager::countFontconfigFonts() pUpdate->m_nFamilyName = nFamilyName; } if( eWeightRes == FcResultMatch ) - { - // set weight - if( weight <= FC_WEIGHT_THIN ) - pUpdate->m_eWeight = weight::Thin; - else if( weight <= FC_WEIGHT_ULTRALIGHT ) - pUpdate->m_eWeight = weight::UltraLight; - else if( weight <= FC_WEIGHT_LIGHT ) - pUpdate->m_eWeight = weight::Light; - else if( weight <= FC_WEIGHT_BOOK ) - pUpdate->m_eWeight = weight::SemiLight; - else if( weight <= FC_WEIGHT_NORMAL ) - pUpdate->m_eWeight = weight::Normal; - else if( weight <= FC_WEIGHT_MEDIUM ) - pUpdate->m_eWeight = weight::Medium; - else if( weight <= FC_WEIGHT_SEMIBOLD ) - pUpdate->m_eWeight = weight::SemiBold; - else if( weight <= FC_WEIGHT_BOLD ) - pUpdate->m_eWeight = weight::Bold; - else if( weight <= FC_WEIGHT_ULTRABOLD ) - pUpdate->m_eWeight = weight::UltraBold; - else - pUpdate->m_eWeight = weight::Black; - } + pUpdate->m_eWeight = convertWeight(weight); if( eSpacRes == FcResultMatch ) - { - // set pitch - if( spacing == FC_PROPORTIONAL ) - pUpdate->m_ePitch = pitch::Variable; - else if( spacing == FC_MONO || spacing == FC_CHARCELL ) - pUpdate->m_ePitch = pitch::Fixed; - } + pUpdate->m_ePitch = convertSpacing(spacing); if( eSlantRes == FcResultMatch ) - { - // set italic - if( slant == FC_SLANT_ROMAN ) - pUpdate->m_eItalic = italic::Upright; - else if( slant == FC_SLANT_ITALIC ) - pUpdate->m_eItalic = italic::Italic; - else if( slant == FC_SLANT_OBLIQUE ) - pUpdate->m_eItalic = italic::Oblique; - } + pUpdate->m_eItalic = convertSlant(slant); if( eStyleRes == FcResultMatch ) { pUpdate->m_aStyleName = OStringToOUString( OString( (sal_Char*)style ), RTL_TEXTENCODING_UTF8 ); } - if( eEmbeddedBitmap == FcResultMatch ) - { - pUpdate->m_eEmbeddedbitmap = embitmap ? fcstatus::istrue : fcstatus::isfalse; - } - if( eAntialias == FcResultMatch ) - { - pUpdate->m_eAntialias = antialias ? fcstatus::istrue : fcstatus::isfalse; - } - // update font cache m_pFontCache->updateFontCacheEntry( pUpdate, false ); @@ -880,8 +914,8 @@ static void addtopattern(FontCfgWrapper& rWrapper, FcPattern *pPattern, rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName, rtl::OUString& rMissingCodes, const rtl::OString &rLangAttrib, - italic::type eItalic, weight::type eWeight, - width::type eWidth, pitch::type ePitch) const + italic::type &rItalic, weight::type &rWeight, + width::type &rWidth, pitch::type &rPitch) const { rtl::OUString aName; FontCfgWrapper& rWrapper = FontCfgWrapper::get(); @@ -916,7 +950,7 @@ rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName, rWrapper.FcCharSetDestroy( unicodes ); } - addtopattern(rWrapper, pPattern, eItalic, eWeight, eWidth, ePitch); + addtopattern(rWrapper, pPattern, rItalic, rWeight, rWidth, rPitch); // query fontconfig for a substitute rWrapper.FcConfigSubstitute( rWrapper.FcConfigGetCurrent(), pPattern, FcMatchPattern ); @@ -949,10 +983,21 @@ rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName, if( eFileRes == FcResultMatch ) { OString sFamily((sal_Char*)family); - std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = rWrapper.m_aFontconfigNameToLocalized.find(sFamily); - if (aI != rWrapper.m_aFontconfigNameToLocalized.end()) + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = rWrapper.m_aFontNameToLocalized.find(sFamily); + if (aI != rWrapper.m_aFontNameToLocalized.end()) sFamily = aI->second; aName = rtl::OStringToOUString( sFamily, RTL_TEXTENCODING_UTF8 ); + + + int val = 0; + if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_WEIGHT, 0, &val)) + rWeight = convertWeight(val); + if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_SLANT, 0, &val)) + rItalic = convertSlant(val); + if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_SPACING, 0, &val)) + rPitch = convertSpacing(val); + if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_WIDTH, 0, &val)) + rWidth = convertWidth(val); } // update rMissingCodes by removing resolved unicodes @@ -981,6 +1026,89 @@ rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName, return aName; } +bool PrintFontManager::getFontOptions( + const FastPrintFontInfo& rInfo, int nSize, void (*subcallback)(void*), + ImplFontOptions& rOptions) const +{ +#ifndef ENABLE_FONTCONFIG + return false; +#else // ENABLE_FONTCONFIG + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); + if( ! rWrapper.isValid() ) + return false; + + FcConfig* pConfig = rWrapper.FcConfigGetCurrent(); + FcPattern* pPattern = rWrapper.FcPatternCreate(); + + OString sFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 ); + + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = rWrapper.m_aLocalizedToCanonical.find(sFamily); + if (aI != rWrapper.m_aLocalizedToCanonical.end()) + sFamily = aI->second; + if( sFamily.getLength() ) + rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)sFamily.getStr() ); + + addtopattern(rWrapper, pPattern, rInfo.m_eItalic, rInfo.m_eWeight, rInfo.m_eWidth, rInfo.m_ePitch); + rWrapper.FcPatternAddDouble( pPattern, FC_PIXEL_SIZE, nSize); + + FcBool embitmap = true, antialias = true, autohint = true, hinting = true; + int hintstyle = FC_HINT_FULL; + + rWrapper.FcConfigSubstitute( pConfig, pPattern, FcMatchPattern ); + if (subcallback) subcallback(pPattern); + rWrapper.FcDefaultSubstitute( pPattern ); + + FcResult eResult = FcResultNoMatch; + FcFontSet* pFontSet = rWrapper.getFontSet(); + FcPattern* pResult = rWrapper.FcFontSetMatch( pConfig, &pFontSet, 1, pPattern, &eResult ); + if( pResult ) + { + FcFontSet* pSet = rWrapper.FcFontSetCreate(); + rWrapper.FcFontSetAdd( pSet, pResult ); + if( pSet->nfont > 0 ) + { + FcResult eEmbeddedBitmap = rWrapper.FcPatternGetBool(pSet->fonts[0], + FC_EMBEDDED_BITMAP, 0, &embitmap); + FcResult eAntialias = rWrapper.FcPatternGetBool(pSet->fonts[0], + FC_ANTIALIAS, 0, &antialias); + FcResult eAutoHint = rWrapper.FcPatternGetBool(pSet->fonts[0], + FC_AUTOHINT, 0, &autohint); + FcResult eHinting = rWrapper.FcPatternGetBool(pSet->fonts[0], + FC_HINTING, 0, &hinting); + /*FcResult eHintStyle =*/ rWrapper.FcPatternGetInteger( pSet->fonts[0], + FC_HINT_STYLE, 0, &hintstyle); + + if( eEmbeddedBitmap == FcResultMatch ) + rOptions.meEmbeddedBitmap = embitmap ? EMBEDDEDBITMAP_TRUE : EMBEDDEDBITMAP_FALSE; + if( eAntialias == FcResultMatch ) + rOptions.meAntiAlias = antialias ? ANTIALIAS_TRUE : ANTIALIAS_FALSE; + if( eAutoHint == FcResultMatch ) + rOptions.meAutoHint = autohint ? AUTOHINT_TRUE : AUTOHINT_FALSE; + if( eHinting == FcResultMatch ) + rOptions.meHinting = hinting ? HINTING_TRUE : HINTING_FALSE; + switch (hintstyle) + { + case FC_HINT_NONE: rOptions.meHintStyle = HINT_NONE; break; + case FC_HINT_SLIGHT: rOptions.meHintStyle = HINT_SLIGHT; break; + case FC_HINT_MEDIUM: rOptions.meHintStyle = HINT_MEDIUM; break; + default: // fall through + case FC_HINT_FULL: rOptions.meHintStyle = HINT_FULL; break; + } + } + // info: destroying the pSet destroys pResult implicitly + // since pResult was "added" to pSet + rWrapper.FcFontSetDestroy( pSet ); + } + + // cleanup + rWrapper.FcPatternDestroy( pPattern ); + + // TODO: return true only if non-default font options are set + const bool bOK = (pResult != NULL); + return bOK; +#endif +} + bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale ) { FontCfgWrapper& rWrapper = FontCfgWrapper::get(); diff --git a/vcl/unx/source/fontmanager/fontmanager.cxx b/vcl/unx/source/fontmanager/fontmanager.cxx index aad53549f1ea..7d5224707f72 100644 --- a/vcl/unx/source/fontmanager/fontmanager.cxx +++ b/vcl/unx/source/fontmanager/fontmanager.cxx @@ -353,9 +353,7 @@ PrintFontManager::PrintFont::PrintFont( fonttype::type eType ) : m_nXMax( 0 ), m_nYMax( 0 ), m_bHaveVerticalSubstitutedGlyphs( false ), - m_bUserOverride( false ), - m_eEmbeddedbitmap( fcstatus::isunset ), - m_eAntialias( fcstatus::isunset ) + m_bUserOverride( false ) { } @@ -2630,8 +2628,6 @@ void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& r rInfo.m_eWeight = pFont->m_eWeight; rInfo.m_ePitch = pFont->m_ePitch; rInfo.m_aEncoding = pFont->m_aEncoding; - rInfo.m_eEmbeddedbitmap = pFont->m_eEmbeddedbitmap; - rInfo.m_eAntialias = pFont->m_eAntialias; rInfo.m_bEmbeddable = (pFont->m_eType == fonttype::Type1); rInfo.m_bSubsettable = (pFont->m_eType == fonttype::TrueType); // TODO: rename to SfntType @@ -3936,8 +3932,6 @@ bool PrintFontManager::readOverrideMetrics() BuiltinFont* pFont = new BuiltinFont(); pFont->m_nDirectory = 0; pFont->m_bUserOverride = false; - pFont->m_eEmbeddedbitmap = fcstatus::isunset; - pFont->m_eAntialias = fcstatus::isunset; pFont->m_pMetrics = new PrintFontMetrics; memset( pFont->m_pMetrics->m_aPages, 0xff, sizeof( pFont->m_pMetrics->m_aPages ) ); pFont->m_pMetrics->m_bKernPairsQueried = true; diff --git a/vcl/unx/source/gdi/pspgraphics.cxx b/vcl/unx/source/gdi/pspgraphics.cxx index 10a51afeb696..d599e09e71f2 100644 --- a/vcl/unx/source/gdi/pspgraphics.cxx +++ b/vcl/unx/source/gdi/pspgraphics.cxx @@ -1284,32 +1284,6 @@ ImplDevFontAttributes PspGraphics::Info2DevFontAttributes( const psp::FastPrintF aDFA.mbSubsettable = rInfo.m_bSubsettable; aDFA.mbEmbeddable = rInfo.m_bEmbeddable; - switch (rInfo.m_eEmbeddedbitmap) - { - default: - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - break; - case psp::fcstatus::istrue: - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_TRUE; - break; - case psp::fcstatus::isfalse: - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_FALSE; - break; - } - - switch (rInfo.m_eAntialias) - { - default: - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - break; - case psp::fcstatus::istrue: - aDFA.meAntiAlias = ANTIALIAS_TRUE; - break; - case psp::fcstatus::isfalse: - aDFA.meAntiAlias = ANTIALIAS_FALSE; - break; - } - switch( rInfo.m_eType ) { case psp::fonttype::Builtin: diff --git a/vcl/unx/source/gdi/salgdi3.cxx b/vcl/unx/source/gdi/salgdi3.cxx index bb5e7c68b356..0c1fcd7c77bd 100644 --- a/vcl/unx/source/gdi/salgdi3.cxx +++ b/vcl/unx/source/gdi/salgdi3.cxx @@ -630,12 +630,26 @@ bool X11SalGraphics::setFont( const ImplFontSelectData *pEntry, int nFallbackLev ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry ); if( pServerFont != NULL ) { + // ignore fonts with e.g. corrupted font files if( !pServerFont->TestFont() ) { GlyphCache::GetInstance().UncacheFont( *pServerFont ); return false; } + + // register to use the font mpServerFont[ nFallbackLevel ] = pServerFont; + + // apply font specific-hint settings if needed + if( !bPrinter_ ) + { + // TODO: is it worth it to cache the hint settings, e.g. in the ImplFontEntry? + ImplFontOptions aFontOptions; + bool GetFCFontOptions( const ImplFontAttributes&, int nSize, ImplFontOptions&); + if( GetFCFontOptions( *pEntry->mpFontData, pEntry->mnHeight, aFontOptions ) ) + pServerFont->SetFontOptions( aFontOptions ); + } + return true; } @@ -743,6 +757,8 @@ private: void (*mp_set_font_matrix)(cairo_t *, const cairo_matrix_t *); void (*mp_show_glyphs)(cairo_t *, const cairo_glyph_t *, int ); void (*mp_set_source_rgb)(cairo_t *, double , double , double ); + void (*mp_set_font_options)(cairo_t *, const void *); + void (*mp_ft_font_options_substitute)(const void*, void*); bool canEmbolden() const { return false; } @@ -778,6 +794,10 @@ public: { (*mp_show_glyphs)(cr, glyphs, no_glyphs); } void set_source_rgb(cairo_t *cr, double red, double green, double blue) { (*mp_set_source_rgb)(cr, red, green, blue); } + void set_font_options(cairo_t *cr, const void *options) + { (*mp_set_font_options)(cr, options); } + void ft_font_options_substitute(const void *options, void *pattern) + { (*mp_ft_font_options_substitute)(options, pattern); } }; static CairoWrapper* pCairoInstance = NULL; @@ -847,6 +867,10 @@ CairoWrapper::CairoWrapper() osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_show_glyphs" ); mp_set_source_rgb = (void (*)(cairo_t *, double , double , double )) osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_source_rgb" ); + mp_set_font_options = (void (*)(cairo_t *, const void *options )) + osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_options" ); + mp_ft_font_options_substitute = (void (*)(const void *, void *)) + osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_ft_font_options_substitute" ); if( !( mp_xlib_surface_create_with_xrender_format && @@ -863,7 +887,9 @@ CairoWrapper::CairoWrapper() mp_matrix_rotate && mp_set_font_matrix && mp_show_glyphs && - mp_set_source_rgb + mp_set_source_rgb && + mp_set_font_options && + mp_ft_font_options_substitute ) ) { osl_unloadModule( mpCairoLib ); @@ -971,6 +997,9 @@ void X11SalGraphics::DrawCairoAAFontString( const ServerFontLayout& rLayout ) cairo_t *cr = rCairo.create(surface); rCairo.surface_destroy(surface); + if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions()) + rCairo.set_font_options( cr, pOptions); + if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) ) { for (long i = 0; i < pClipRegion_->numRects; ++i) @@ -1601,6 +1630,122 @@ void X11SalGraphics::GetDevFontSubstList( OutputDevice* ) // ---------------------------------------------------------------------------- +void cairosubcallback( void* pPattern ) +{ + CairoWrapper& rCairo = CairoWrapper::get(); + if( rCairo.isValid() ) + { + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + rCairo.ft_font_options_substitute( rStyleSettings.GetCairoFontOptions(), pPattern); + } +} + +bool GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize, + ImplFontOptions& rFontOptions) +{ + // TODO: get rid of these insane enum-conversions + // e.g. by using the classic vclenum values inside VCL + + psp::FastPrintFontInfo aInfo; + // set family name + aInfo.m_aFamilyName = rFontAttributes.GetFamilyName(); + // set italic + switch( rFontAttributes.GetSlant() ) + { + case ITALIC_NONE: + aInfo.m_eItalic = psp::italic::Upright; + break; + case ITALIC_NORMAL: + aInfo.m_eItalic = psp::italic::Italic; + break; + case ITALIC_OBLIQUE: + aInfo.m_eItalic = psp::italic::Oblique; + break; + default: + aInfo.m_eItalic = psp::italic::Unknown; + break; + + } + // set weight + switch( rFontAttributes.GetWeight() ) + { + case WEIGHT_THIN: + aInfo.m_eWeight = psp::weight::Thin; + break; + case WEIGHT_ULTRALIGHT: + aInfo.m_eWeight = psp::weight::UltraLight; + break; + case WEIGHT_LIGHT: + aInfo.m_eWeight = psp::weight::Light; + break; + case WEIGHT_SEMILIGHT: + aInfo.m_eWeight = psp::weight::SemiLight; + break; + case WEIGHT_NORMAL: + aInfo.m_eWeight = psp::weight::Normal; + break; + case WEIGHT_MEDIUM: + aInfo.m_eWeight = psp::weight::Medium; + break; + case WEIGHT_SEMIBOLD: + aInfo.m_eWeight = psp::weight::SemiBold; + break; + case WEIGHT_BOLD: + aInfo.m_eWeight = psp::weight::Bold; + break; + case WEIGHT_ULTRABOLD: + aInfo.m_eWeight = psp::weight::UltraBold; + break; + case WEIGHT_BLACK: + aInfo.m_eWeight = psp::weight::Black; + break; + default: + aInfo.m_eWeight = psp::weight::Unknown; + break; + } + // set width + switch( rFontAttributes.GetWidthType() ) + { + case WIDTH_ULTRA_CONDENSED: + aInfo.m_eWidth = psp::width::UltraCondensed; + break; + case WIDTH_EXTRA_CONDENSED: + aInfo.m_eWidth = psp::width::ExtraCondensed; + break; + case WIDTH_CONDENSED: + aInfo.m_eWidth = psp::width::Condensed; + break; + case WIDTH_SEMI_CONDENSED: + aInfo.m_eWidth = psp::width::SemiCondensed; + break; + case WIDTH_NORMAL: + aInfo.m_eWidth = psp::width::Normal; + break; + case WIDTH_SEMI_EXPANDED: + aInfo.m_eWidth = psp::width::SemiExpanded; + break; + case WIDTH_EXPANDED: + aInfo.m_eWidth = psp::width::Expanded; + break; + case WIDTH_EXTRA_EXPANDED: + aInfo.m_eWidth = psp::width::ExtraExpanded; + break; + case WIDTH_ULTRA_EXPANDED: + aInfo.m_eWidth = psp::width::UltraExpanded; + break; + default: + aInfo.m_eWidth = psp::width::Unknown; + break; + } + + const psp::PrintFontManager& rPFM = psp::PrintFontManager::get(); + bool bOK = rPFM.getFontOptions( aInfo, nSize, cairosubcallback, rFontOptions); + + return bOK; +} + +// ---------------------------------------------------------------------------- + void X11SalGraphics::GetFontMetric( ImplFontMetricData *pMetric ) { @@ -1876,8 +2021,10 @@ void RegisterFontSubstitutors( ImplDevFontList* pList ) // ----------------------------------------------------------------------- -static rtl::OUString GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUString& rMissingCodes ) +static ImplFontSelectData GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUString& rMissingCodes ) { + ImplFontSelectData aRet(rFontSelData); + const rtl::OString aLangAttrib; //TODO: = MsLangId::convertLanguageToIsoByteString( rFontSelData.meLanguage ); psp::italic::type eItalic = psp::italic::Unknown; @@ -1945,7 +2092,72 @@ static rtl::OUString GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUS } const psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); - return rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch); + aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch); + + switch (eItalic) + { + case psp::italic::Upright: aRet.meItalic = ITALIC_NONE; break; + case psp::italic::Italic: aRet.meItalic = ITALIC_NORMAL; break; + case psp::italic::Oblique: aRet.meItalic = ITALIC_OBLIQUE; break; + default: + break; + } + + switch (eWeight) + { + case psp::weight::Thin: aRet.meWeight = WEIGHT_THIN; break; + case psp::weight::UltraLight: aRet.meWeight = WEIGHT_ULTRALIGHT; break; + case psp::weight::Light: aRet.meWeight = WEIGHT_LIGHT; break; + case psp::weight::SemiLight: aRet.meWeight = WEIGHT_SEMILIGHT; break; + case psp::weight::Normal: aRet.meWeight = WEIGHT_NORMAL; break; + case psp::weight::Medium: aRet.meWeight = WEIGHT_MEDIUM; break; + case psp::weight::SemiBold: aRet.meWeight = WEIGHT_SEMIBOLD; break; + case psp::weight::Bold: aRet.meWeight = WEIGHT_BOLD; break; + case psp::weight::UltraBold: aRet.meWeight = WEIGHT_ULTRABOLD; break; + case psp::weight::Black: aRet.meWeight = WEIGHT_BLACK; break; + default: + break; + } + + switch (eWidth) + { + case psp::width::UltraCondensed: aRet.meWidthType = WIDTH_ULTRA_CONDENSED; break; + case psp::width::ExtraCondensed: aRet.meWidthType = WIDTH_EXTRA_CONDENSED; break; + case psp::width::Condensed: aRet.meWidthType = WIDTH_CONDENSED; break; + case psp::width::SemiCondensed: aRet.meWidthType = WIDTH_SEMI_CONDENSED; break; + case psp::width::Normal: aRet.meWidthType = WIDTH_NORMAL; break; + case psp::width::SemiExpanded: aRet.meWidthType = WIDTH_SEMI_EXPANDED; break; + case psp::width::Expanded: aRet.meWidthType = WIDTH_EXPANDED; break; + case psp::width::ExtraExpanded: aRet.meWidthType = WIDTH_EXTRA_EXPANDED; break; + case psp::width::UltraExpanded: aRet.meWidthType = WIDTH_ULTRA_EXPANDED; break; + default: + break; + } + + switch (ePitch) + { + case psp::pitch::Fixed: aRet.mePitch = PITCH_FIXED; break; + case psp::pitch::Variable: aRet.mePitch = PITCH_VARIABLE; break; + default: + break; + } + + return aRet; +} + +namespace +{ + bool uselessmatch(const ImplFontSelectData &rOrig, const ImplFontSelectData &rNew) + { + return + ( + rOrig.maTargetName == rNew.maSearchName && + rOrig.meWeight == rNew.meWeight && + rOrig.meItalic == rNew.meItalic && + rOrig.mePitch == rNew.mePitch && + rOrig.meWidthType == rNew.meWidthType + ); + } } //-------------------------------------------------------------------------- @@ -1953,7 +2165,7 @@ static rtl::OUString GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUS bool FcPreMatchSubstititution::FindFontSubstitute( ImplFontSelectData &rFontSelData ) const { // We dont' actually want to talk to Fontconfig at all for symbol fonts - if (rFontSelData.IsSymbolFont()) + if( rFontSelData.IsSymbolFont() ) return false; // StarSymbol is a unicode font, but it still deserves the symbol flag if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10) @@ -1961,21 +2173,33 @@ bool FcPreMatchSubstititution::FindFontSubstitute( ImplFontSelectData &rFontSelD return false; rtl::OUString aDummy; - const rtl::OUString aOUName = GetFcSubstitute( rFontSelData, aDummy ); - if( !aOUName.getLength() ) - return false; - const String aName( aOUName ); - if( aName == rFontSelData.maTargetName ) + const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, aDummy ); + // TODO: cache the font substitution suggestion + // FC doing it would be preferable because it knows the invariables + // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans + // whereas we would have to check for every size or attribute + if( !aOut.maSearchName.Len() ) return false; + const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut ); + #ifdef DEBUG - ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 ); - ByteString aSubstName( aName, RTL_TEXTENCODING_UTF8 ); - printf( "FcPreMatchSubstititution \"%s\" -> \"%s\"\n", - aOrigName.GetBuffer(), aSubstName.GetBuffer() ); + const ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 ); + const ByteString aSubstName( aOut.maSearchName, RTL_TEXTENCODING_UTF8 ); + printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ", + aOrigName.GetBuffer(), rFontSelData.meWeight, rFontSelData.meItalic, + rFontSelData.mePitch, rFontSelData.meWidthType ); + if( !bHaveSubstitute ) + printf( "no substitute available\n" ); + else + printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.GetBuffer(), + aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType ); #endif - rFontSelData.maSearchName = aName; - return true; + + if( bHaveSubstitute ) + rFontSelData = aOut; + + return bHaveSubstitute; } // ----------------------------------------------------------------------- @@ -1991,22 +2215,33 @@ bool FcGlyphFallbackSubstititution::FindFontSubstitute( ImplFontSelectData& rFon || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) ) return false; - const rtl::OUString aOUName = GetFcSubstitute( rFontSelData, rMissingCodes ); - // TODO: cache the unicode+font specific result - if( !aOUName.getLength() ) - return false; - const String aName( aOUName ); - if( aName == rFontSelData.maTargetName ) + const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, rMissingCodes ); + // TODO: cache the unicode + srcfont specific result + // FC doing it would be preferable because it knows the invariables + // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans + // whereas we would have to check for every size or attribute + if( !aOut.maSearchName.Len() ) return false; + const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut ); + #ifdef DEBUG - ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 ); - ByteString aSubstName( aName, RTL_TEXTENCODING_UTF8 ); - printf( "FcGlyphFallbackSubstititution \"%s\" -> \"%s\"\n", - aOrigName.GetBuffer(), aSubstName.GetBuffer() ); + const ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 ); + const ByteString aSubstName( aOut.maSearchName, RTL_TEXTENCODING_UTF8 ); + printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->", + aOrigName.GetBuffer(), rFontSelData.meWeight, rFontSelData.meItalic, + rFontSelData.mePitch, rFontSelData.meWidthType ); + if( !bHaveSubstitute ) + printf( "no substitute available\n" ); + else + printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.GetBuffer(), + aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType ); #endif - rFontSelData.maSearchName = aName; - return true; + + if( bHaveSubstitute ) + rFontSelData = aOut; + + return bHaveSubstitute; } // =========================================================================== diff --git a/vcl/unx/source/gdi/xlfd_extd.cxx b/vcl/unx/source/gdi/xlfd_extd.cxx index 8449fcc5872e..73731eddf115 100644 --- a/vcl/unx/source/gdi/xlfd_extd.cxx +++ b/vcl/unx/source/gdi/xlfd_extd.cxx @@ -102,9 +102,6 @@ ExtendedXlfd::ExtendedXlfd( bool bScalable ) mbSubsettable = false; mbEmbeddable = false; - meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - meAntiAlias = ANTIALIAS_DONTKNOW; - mnQuality = -1; } diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx index 84695baf3557..ebe470d3eb7e 100644 --- a/vcl/win/source/gdi/salgdi3.cxx +++ b/vcl/win/source/gdi/salgdi3.cxx @@ -590,11 +590,7 @@ static ImplDevFontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXA& rE aDFA.mnQuality += 500; } - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - // TODO: add alias names - return aDFA; } @@ -669,9 +665,6 @@ static ImplDevFontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXW& rE aDFA.mnQuality += 500; } - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - // TODO: add alias names return aDFA; } @@ -1998,8 +1991,6 @@ static bool ImplGetFontAttrFromFile( const String& rFontFileURL, rDFA.mePitch = PITCH_DONTKNOW;; rDFA.mbSubsettable= true; rDFA.mbEmbeddable = false; - rDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - rDFA.meAntiAlias = ANTIALIAS_DONTKNOW; // Create temporary file name char aFileName[] = "soAAT.fot"; @@ -2126,8 +2117,6 @@ bool WinSalGraphics::AddTempDevFont( ImplDevFontList* pFontList, aDFA.mePitch = PITCH_DONTKNOW;; aDFA.mbSubsettable= true; aDFA.mbEmbeddable = false; - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; /* // TODO: improve ImplDevFontAttributes using the "font resource file" diff --git a/xmloff/inc/SchXMLExport.hxx b/xmloff/inc/SchXMLExport.hxx index 2f943f100170..d6227754a5f2 100644 --- a/xmloff/inc/SchXMLExport.hxx +++ b/xmloff/inc/SchXMLExport.hxx @@ -38,7 +38,6 @@ namespace com { namespace sun { namespace star { namespace chart { class XDiagram; class XChartDocument; - class XChartDataArray; struct ChartSeriesAddress; } namespace drawing { diff --git a/xmloff/inc/xmloff/SchXMLExportHelper.hxx b/xmloff/inc/xmloff/SchXMLExportHelper.hxx index 5876ce989c30..64f579a7c252 100644 --- a/xmloff/inc/xmloff/SchXMLExportHelper.hxx +++ b/xmloff/inc/xmloff/SchXMLExportHelper.hxx @@ -44,7 +44,6 @@ namespace com { namespace sun { namespace star { namespace chart { class XDiagram; class XChartDocument; - class XChartDataArray; struct ChartSeriesAddress; } namespace chart2 { @@ -114,6 +113,7 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes; tDataSequenceCont m_aDataSequencesToExport; + rtl::OUString maCategoriesRange; /** first parseDocument: collect autostyles and store names in this queue second parseDocument: export content and use names from this queue @@ -179,8 +179,6 @@ private: SAL_DLLPRIVATE void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape ); /// fills the member msString with the appropriate String (i.e. "A3") SAL_DLLPRIVATE void getCellAddress( sal_Int32 nCol, sal_Int32 nRow ); - /// interchanges rows and columns of the sequence given - SAL_DLLPRIVATE void swapDataArray( com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< double > >& rSequence ); /// exports a string as a paragraph element SAL_DLLPRIVATE void exportText( const ::rtl::OUString& rText, bool bConvertTabsLFs = false ); SAL_DLLPRIVATE void exportErrorBarRanges(); diff --git a/xmloff/inc/xmloff/SchXMLImportHelper.hxx b/xmloff/inc/xmloff/SchXMLImportHelper.hxx index f3cb28a754e2..03fa8c8e16c0 100644 --- a/xmloff/inc/xmloff/SchXMLImportHelper.hxx +++ b/xmloff/inc/xmloff/SchXMLImportHelper.hxx @@ -136,10 +136,6 @@ public: static sal_uInt16 GetChartFamilyID() { return XML_STYLE_FAMILY_SCH_CHART_ID; } - sal_Int32 GetNumberOfSeries(); - sal_Int32 GetLengthOfSeries(); - void ResizeChartData( sal_Int32 nSeries, sal_Int32 nDataPoints = -1 ); - /** @param bPushLastChartType If </FALSE>, in case a new chart type has to be added (because it does not exist yet), it is appended at the end of the chart-type container. When </TRUE>, a new chart type diff --git a/xmloff/source/chart/SchXMLChartContext.cxx b/xmloff/source/chart/SchXMLChartContext.cxx index fa6481015e5c..e9e3771eb0d7 100644 --- a/xmloff/source/chart/SchXMLChartContext.cxx +++ b/xmloff/source/chart/SchXMLChartContext.cxx @@ -57,7 +57,6 @@ #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/drawing/XDrawPage.hpp> #include <com/sun/star/chart/ChartDataRowSource.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> #include <com/sun/star/awt/PosSize.hpp> #include <com/sun/star/embed/Aspects.hpp> #include <com/sun/star/embed/XVisualObject.hpp> @@ -874,6 +873,9 @@ void SchXMLChartContext::EndElement() { //own data or only rectangular range available + if( xNewDoc->hasInternalDataProvider() ) + SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc ); + bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( Reference< frame::XModel >( xNewDoc, uno::UNO_QUERY )); bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong. @@ -882,21 +884,12 @@ void SchXMLChartContext::EndElement() { //bHasOwnData is true in this case! //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress) - if( xNewDoc->hasInternalDataProvider() ) - SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc ); bSwitchRangesFromOuterToInternalIfNecessary = true; } else { //apply data from rectangular range - // apply data read from the table sub-element to the chart - // if the data provider supports the XChartDataArray interface like - // the internal data provider - uno::Reference< chart::XChartDataArray > xChartData( xNewDoc->getDataProvider(), uno::UNO_QUERY ); - if( xChartData.is()) - SchXMLTableHelper::applyTableSimple( maTable, xChartData ); - // create datasource from data provider with rectangular range // parameters and change the diagram via template mechanism try @@ -919,9 +912,7 @@ void SchXMLChartContext::EndElement() if( !xNewDoc->hasInternalDataProvider() ) { xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ ); - xChartData = uno::Reference< chart::XChartDataArray >( xNewDoc->getDataProvider(), uno::UNO_QUERY ); - if( xChartData.is()) - SchXMLTableHelper::applyTableSimple( maTable, xChartData ); + SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc ); try { lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans ); diff --git a/xmloff/source/chart/SchXMLExport.cxx b/xmloff/source/chart/SchXMLExport.cxx index 3dea947dcb8c..9940f99d9f7a 100644 --- a/xmloff/source/chart/SchXMLExport.cxx +++ b/xmloff/source/chart/SchXMLExport.cxx @@ -71,7 +71,7 @@ #include <com/sun/star/chart/XTwoAxisXSupplier.hpp> #include <com/sun/star/chart/XTwoAxisYSupplier.hpp> #include <com/sun/star/chart/XAxisZSupplier.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> #include <com/sun/star/chart/ChartDataRowSource.hpp> #include <com/sun/star/chart/ChartAxisAssign.hpp> #include <com/sun/star/chart/ChartSeriesAddress.hpp> @@ -116,6 +116,7 @@ using ::rtl::OUStringToOString; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Any; +using ::std::vector; namespace { @@ -166,6 +167,13 @@ template< typename T > ::std::back_inserter( rDestination )); } +template< typename T > + void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination ) +{ + rDestination.clear(); + lcl_SequenceToVectorAppend( rSource, rDestination ); +} + Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram ) { Reference< chart2::data::XLabeledDataSequence > xResult; @@ -209,24 +217,6 @@ Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Referen ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); } - /* - //unused ranges are very problematic as they bear the risk to damage the rectangular structure completly - if(!xResult.is()) - { - Sequence< Reference< chart2::data::XLabeledDataSequence > > aUnusedSequences( xDiagram->getUnusedData() ); - - lcl_MatchesRole aHasCategories( OUString::createFromAscii("categories" ) ); - for( sal_Int32 nN=0; nN<aUnusedSequences.getLength(); nN++ ) - { - if( aHasCategories( aUnusedSequences[nN] ) ) - { - xResult.set( aUnusedSequences[nN] ); - break; - } - } - } - */ - return xResult; } @@ -471,12 +461,6 @@ sal_Int32 lcl_getMaxSequenceLength( for( SchXMLExportHelper::tDataSequenceCont::const_iterator aIt( rContainer.begin()); aIt != rContainer.end(); ++aIt ) { - if( aIt->first.is()) - { - sal_Int32 nSeqLength = aIt->first->getData().getLength(); - if( nSeqLength > nResult ) - nResult = nSeqLength; - } if( aIt->second.is()) { sal_Int32 nSeqLength = aIt->second->getData().getLength(); @@ -487,30 +471,6 @@ sal_Int32 lcl_getMaxSequenceLength( return nResult; } -void lcl_fillCategoriesIntoStringVector( - const Reference< chart2::data::XDataSequence > & xCategories, - ::std::vector< OUString > & rOutCategories ) -{ - OSL_ASSERT( xCategories.is()); - if( !xCategories.is()) - return; - Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xCategories, uno::UNO_QUERY ); - if( xTextualDataSequence.is()) - { - rOutCategories.clear(); - Sequence< OUString > aTextData( xTextualDataSequence->getTextualData()); - ::std::copy( aTextData.getConstArray(), aTextData.getConstArray() + aTextData.getLength(), - ::std::back_inserter( rOutCategories )); - } - else - { - Sequence< uno::Any > aAnies( xCategories->getData()); - rOutCategories.resize( aAnies.getLength()); - for( sal_Int32 i=0; i<aAnies.getLength(); ++i ) - aAnies[i] >>= rOutCategories[i]; - } -} - double lcl_getValueFromSequence( const Reference< chart2::data::XDataSequence > & xSeq, sal_Int32 nIndex ) { double fResult = 0.0; @@ -579,17 +539,23 @@ bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSeque return false; } +typedef vector< OUString > tStringVector; +typedef vector< vector< OUString > > t2DStringVector; +typedef vector< vector< double > > t2DNumberContainer; + struct lcl_TableData { - typedef ::std::vector< OUString > tStringContainer; - typedef ::std::vector< ::std::vector< double > > tTwoDimNumberContainer; + t2DNumberContainer aDataInRows; + tStringVector aDataRangeRepresentations; - tTwoDimNumberContainer aDataInRows; - tStringContainer aDataRangeRepresentations; - tStringContainer aFirstRowStrings; - tStringContainer aFirstRowRangeRepresentations; - tStringContainer aFirstColumnStrings; - tStringContainer aFirstColumnRangeRepresentations; + tStringVector aColumnDescriptions; + tStringVector aColumnDescriptions_Ranges; + + tStringVector aRowDescriptions; + tStringVector aRowDescriptions_Ranges; + + Sequence< Sequence< OUString > > aComplexColumnDescriptions;//outer index is columns - inner index is level + Sequence< Sequence< OUString > > aComplexRowDescriptions;//outer index is rows - inner index is level ::std::vector< sal_Int32 > aHiddenColumns; }; @@ -613,39 +579,29 @@ typedef ::std::map< sal_Int32, SchXMLExportHelper::tLabelValuesDataPair > struct lcl_SequenceToMapElement : public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type > { - lcl_SequenceToMapElement( sal_Int32 nOffset = 0 ) : - m_nOffset( nOffset ) + lcl_SequenceToMapElement() {} result_type operator() ( const argument_type & rContent ) { sal_Int32 nIndex = -1; - if( rContent.second.is()) + if( rContent.second.is()) //has values { OUString aRangeRep( rContent.second->getSourceRangeRepresentation()); - if( aRangeRep.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("categories"))) - { - OSL_ASSERT( m_nOffset > 0 ); - nIndex = 0; - } - else - nIndex = aRangeRep.toInt32() + m_nOffset; + nIndex = aRangeRep.toInt32(); } - else if( rContent.first.is()) - nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32() + m_nOffset; + else if( rContent.first.is()) //has labels + nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32(); return result_type( nIndex, rContent ); } -private: - sal_Int32 m_nOffset; }; -void lcl_PrepareInternalSequencesForTableExport( - SchXMLExportHelper::tDataSequenceCont & rInOutSequences, bool bHasCategories ) +void lcl_ReorderInternalSequencesAccordingToTheirRangeName( + SchXMLExportHelper::tDataSequenceCont & rInOutSequences ) { lcl_DataSequenceMap aIndexSequenceMap; - const sal_Int32 nOffset = bHasCategories ? 1 : 0; ::std::transform( rInOutSequences.begin(), rInOutSequences.end(), ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()), - lcl_SequenceToMapElement( nOffset )); + lcl_SequenceToMapElement()); rInOutSequences.clear(); sal_Int32 nIndex = 0; @@ -665,113 +621,113 @@ void lcl_PrepareInternalSequencesForTableExport( lcl_TableData lcl_getDataForLocalTable( - const SchXMLExportHelper::tDataSequenceCont & aPassedSequences, bool bHasCategoryLabels, - bool bSwap, - bool bHasOwnData, + const SchXMLExportHelper::tDataSequenceCont & aSequencesToExport, + const Reference< chart::XComplexDescriptionAccess >& xComplexDescriptionAccess, + const OUString& rCategoriesRange, + bool bSeriesFromColumns, const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion ) { lcl_TableData aResult; - SchXMLExportHelper::tDataSequenceCont aSequencesToExport( aPassedSequences ); - if( bHasOwnData ) - lcl_PrepareInternalSequencesForTableExport( aSequencesToExport, bHasCategoryLabels ); + try + { + Sequence< OUString > aSimpleCategories; + if( xComplexDescriptionAccess.is() ) + { + if( bSeriesFromColumns ) + aSimpleCategories = xComplexDescriptionAccess->getRowDescriptions(); + else + aSimpleCategories = xComplexDescriptionAccess->getColumnDescriptions(); - SchXMLExportHelper::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size(); - SchXMLExportHelper::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin()); - SchXMLExportHelper::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end()); - SchXMLExportHelper::tDataSequenceCont::const_iterator aIt( aBegin ); + aResult.aComplexColumnDescriptions = xComplexDescriptionAccess->getComplexColumnDescriptions(); + aResult.aComplexRowDescriptions = xComplexDescriptionAccess->getComplexRowDescriptions(); + } - if( bHasCategoryLabels ) - { - if( nNumSequences>=1 ) //#i83537# - --nNumSequences; - else - bHasCategoryLabels=false; - } - size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport )); - size_t nNumColumns( bSwap ? nMaxSequenceLength : nNumSequences ); - size_t nNumRows( bSwap ? nNumSequences : nMaxSequenceLength ); + SchXMLExportHelper::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size(); + SchXMLExportHelper::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin()); + SchXMLExportHelper::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end()); + SchXMLExportHelper::tDataSequenceCont::const_iterator aIt( aBegin ); - // resize data - aResult.aDataInRows.resize( nNumRows ); - double fNan = 0.0; - ::rtl::math::setNan( &fNan ); - ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(), - lcl_resize< lcl_TableData::tTwoDimNumberContainer::value_type >( nNumColumns, fNan )); - aResult.aFirstRowStrings.resize( nNumColumns ); - aResult.aFirstColumnStrings.resize( nNumRows ); + size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport )); + nMaxSequenceLength = std::max( nMaxSequenceLength, size_t( aSimpleCategories.getLength() ) ); + size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength ); + size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences ); - lcl_TableData::tStringContainer & rCategories = - (bSwap ? aResult.aFirstRowStrings : aResult.aFirstColumnStrings ); - lcl_TableData::tStringContainer & rLabels = - (bSwap ? aResult.aFirstColumnStrings : aResult.aFirstRowStrings ); + // resize data + aResult.aDataInRows.resize( nNumRows ); + double fNan = 0.0; + ::rtl::math::setNan( &fNan ); + ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(), + lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan )); + aResult.aColumnDescriptions.resize( nNumColumns ); + aResult.aComplexColumnDescriptions.realloc( nNumColumns ); + aResult.aRowDescriptions.resize( nNumRows ); + aResult.aComplexRowDescriptions.realloc( nNumRows ); - if( aIt != aEnd ) - { - if( bHasCategoryLabels ) - { - lcl_fillCategoriesIntoStringVector( aIt->second, rCategories ); - if( aIt->second.is()) - { - OUString aRange( aIt->second->getSourceRangeRepresentation()); - if( xRangeConversion.is()) - aRange = xRangeConversion->convertRangeToXML( aRange ); - if( bSwap ) - aResult.aFirstRowRangeRepresentations.push_back( aRange ); - else - aResult.aFirstColumnRangeRepresentations.push_back( aRange ); - } - ++aIt; - } - else - { - // autogenerated categories - rCategories.clear(); - lcl_SequenceToVectorAppend( aIt->second->generateLabel( chart2::data::LabelOrigin_LONG_SIDE ), rCategories ); - } - } + tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions; + tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions; - // iterate over all sequences - size_t nSeqIdx = 0; - for( ; aIt != aEnd; ++aIt, ++nSeqIdx ) - { - OUString aRange; - if( aIt->first.is()) + //categories + lcl_SequenceToVector( aSimpleCategories, rCategories ); + if( rCategoriesRange.getLength() ) { - rLabels[nSeqIdx] = lcl_getLabelString( aIt->first ); - aRange = aIt->first->getSourceRangeRepresentation(); + OUString aRange(rCategoriesRange); if( xRangeConversion.is()) aRange = xRangeConversion->convertRangeToXML( aRange ); + if( bSeriesFromColumns ) + aResult.aRowDescriptions_Ranges.push_back( aRange ); + else + aResult.aColumnDescriptions_Ranges.push_back( aRange ); } - else if( aIt->second.is()) - rLabels[nSeqIdx] = lcl_flattenStringSequence( - aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE )); - if( bSwap ) - aResult.aFirstColumnRangeRepresentations.push_back( aRange ); - else - aResult.aFirstRowRangeRepresentations.push_back( aRange ); - ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second )); - if( bSwap ) - aResult.aDataInRows[nSeqIdx] = aNumbers; - else + // iterate over all sequences + size_t nSeqIdx = 0; + for( ; aIt != aEnd; ++aIt, ++nSeqIdx ) { - const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size())); - for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx ) - aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx]; - } + OUString aRange; + if( aIt->first.is()) + { + rLabels[nSeqIdx] = lcl_getLabelString( aIt->first ); + aRange = aIt->first->getSourceRangeRepresentation(); + if( xRangeConversion.is()) + aRange = xRangeConversion->convertRangeToXML( aRange ); + } + else if( aIt->second.is()) + rLabels[nSeqIdx] = lcl_flattenStringSequence( + aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE )); + if( bSeriesFromColumns ) + aResult.aColumnDescriptions_Ranges.push_back( aRange ); + else + aResult.aRowDescriptions_Ranges.push_back( aRange ); - if( aIt->second.is()) - { - aRange = aIt->second->getSourceRangeRepresentation(); - if( xRangeConversion.is()) - aRange = xRangeConversion->convertRangeToXML( aRange ); - } - aResult.aDataRangeRepresentations.push_back( aRange ); + ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second )); + if( bSeriesFromColumns ) + { + const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size())); + for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx ) + aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx]; + } + else + aResult.aDataInRows[nSeqIdx] = aNumbers; + + if( aIt->second.is()) + { + aRange = aIt->second->getSourceRangeRepresentation(); + if( xRangeConversion.is()) + aRange = xRangeConversion->convertRangeToXML( aRange ); + } + aResult.aDataRangeRepresentations.push_back( aRange ); - //is column hidden? - if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) ) - aResult.aHiddenColumns.push_back(nSeqIdx); + //is column hidden? + if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) ) + aResult.aHiddenColumns.push_back(nSeqIdx); + } + } + catch( uno::Exception & rEx ) + { + (void)rEx; // avoid warning for pro build + OSL_TRACE( OUStringToOString( OUString( RTL_CONSTASCII_USTRINGPARAM( + "something went wrong during table data collection: " )) + rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); } return aResult; @@ -1452,6 +1408,19 @@ void SchXMLExportHelper::parseDocument( Reference< chart::XChartDocument >& rCha delete pElChart; } +void lcl_exportComplexLabel( const Sequence< OUString >& rComplexLabel, SvXMLExport& rExport ) +{ + sal_Int32 nLength = rComplexLabel.getLength(); + if( nLength<=1 ) + return; + SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, sal_True, sal_True ); + for(sal_Int32 nN=0; nN<nLength; nN++) + { + SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, sal_True, sal_True ); + SchXMLTools::exportText( rExport, rComplexLabel[nN], false /*bConvertTabsLFs*/ ); + } +} + void SchXMLExportHelper::exportTable() { // table element @@ -1468,13 +1437,24 @@ void SchXMLExportHelper::exportTable() xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY ); } - lcl_TableData aData( lcl_getDataForLocalTable( - m_aDataSequencesToExport, mbHasCategoryLabels, !mbRowSourceColumns, bHasOwnData, xRangeConversion )); + Reference< chart::XComplexDescriptionAccess > xComplexDescriptionAccess; + { + Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY ); + if( xChartDoc.is() ) + xComplexDescriptionAccess = Reference< chart::XComplexDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY ); + } - lcl_TableData::tStringContainer::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin()); - const lcl_TableData::tStringContainer::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end()); - lcl_TableData::tStringContainer::const_iterator aFirstColumnRangeIter( aData.aFirstColumnRangeRepresentations.begin()); - const lcl_TableData::tStringContainer::const_iterator aFirstColumnRangeEndIter( aData.aFirstColumnRangeRepresentations.end()); + if( bHasOwnData ) + lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport ); + lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport + , xComplexDescriptionAccess, maCategoriesRange + , mbRowSourceColumns, xRangeConversion )); + + tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin()); + const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end()); + + tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin()); + const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end()); // declare columns { @@ -1502,7 +1482,7 @@ void SchXMLExportHelper::exportTable() nNextIndex = nHiddenIndex+1; } - sal_Int32 nEndIndex = aData.aFirstRowStrings.size()-1; + sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1; if( nEndIndex >= nNextIndex ) { sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 ); @@ -1514,59 +1494,78 @@ void SchXMLExportHelper::exportTable() } // export rows with content + //export header row { SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, sal_True, sal_True ); SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True ); + + //first one empty cell for the row descriptions { SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True ); } - lcl_TableData::tStringContainer::const_iterator aFirstRowRangeIter( aData.aFirstRowRangeRepresentations.begin()); - const lcl_TableData::tStringContainer::const_iterator aFirstRowRangeEndIter( aData.aFirstRowRangeRepresentations.end()); - for( lcl_TableData::tStringContainer::const_iterator aIt( aData.aFirstRowStrings.begin()); - aIt != aData.aFirstRowStrings.end(); ++aIt ) + //export column descriptions + tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin()); + const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end()); + const Sequence< Sequence< OUString > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions; + sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength(); + sal_Int32 nC = 0; + for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin()); + aIt != aData.aColumnDescriptions.end(); ++aIt ) { mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING ); SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); // write the original range name as id into the local table // to allow a correct re-association when copying via clipboard - if( !bHasOwnData && aFirstRowRangeIter != aFirstRowRangeEndIter ) + if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd ) { - if( (*aFirstRowRangeIter).getLength()) - mrExport.AddAttribute( XML_NAMESPACE_TEXT, XML_ID, *aFirstRowRangeIter ); - ++aFirstRowRangeIter; + if( (*aColumnDescriptions_RangeIter).getLength()) + mrExport.AddAttribute( XML_NAMESPACE_TEXT, XML_ID, *aColumnDescriptions_RangeIter ); + ++aColumnDescriptions_RangeIter; } exportText( *aIt ); + if( nC < nComplexCount ) + lcl_exportComplexLabel( rComplexColumnDescriptions[nC++], mrExport ); } - OSL_ASSERT( bHasOwnData || aFirstRowRangeIter == aFirstRowRangeEndIter ); + OSL_ASSERT( bHasOwnData || aColumnDescriptions_RangeIter == aColumnDescriptions_RangeEnd ); } // closing row and header-rows elements - // value rows + // export value rows { SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, sal_True, sal_True ); - lcl_TableData::tStringContainer::const_iterator aFirstColIt( aData.aFirstColumnStrings.begin()); - for( lcl_TableData::tTwoDimNumberContainer::const_iterator aColIt( aData.aDataInRows.begin()); - aColIt != aData.aDataInRows.end(); ++aColIt ) + tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin()); + const Sequence< Sequence< OUString > >& rComplexRowDescriptions = aData.aComplexRowDescriptions; + sal_Int32 nComplexCount = rComplexRowDescriptions.getLength(); + sal_Int32 nC = 0; + + for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin()); + aRowIt != aData.aDataInRows.end(); ++aRowIt ) { SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True ); + + //export row descriptions { mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING ); SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); - if( aFirstColIt != aData.aFirstColumnStrings.end()) + if( aRowDescriptionsIter != aData.aRowDescriptions.end()) { // write the original range name as id into the local table // to allow a correct re-association when copying via clipboard - if( !bHasOwnData && aFirstColumnRangeIter != aFirstColumnRangeEndIter ) - mrExport.AddAttribute( XML_NAMESPACE_TEXT, XML_ID, *aFirstColumnRangeIter++ ); - exportText( *aFirstColIt ); - ++aFirstColIt; + if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd ) + mrExport.AddAttribute( XML_NAMESPACE_TEXT, XML_ID, *aRowDescriptions_RangeIter++ ); + exportText( *aRowDescriptionsIter ); + ++aRowDescriptionsIter; + if( nC < nComplexCount ) + lcl_exportComplexLabel( rComplexRowDescriptions[nC++], mrExport ); } } - for( lcl_TableData::tTwoDimNumberContainer::value_type::const_iterator aInnerIt( aColIt->begin()); - aInnerIt != aColIt->end(); ++aInnerIt ) + + //export row values + for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin()); + aColIt != aRowIt->end(); ++aColIt ) { - SvXMLUnitConverter::convertDouble( msStringBuffer, *aInnerIt ); + SvXMLUnitConverter::convertDouble( msStringBuffer, *aColIt ); msString = msStringBuffer.makeStringAndClear(); mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT ); mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString ); @@ -1574,7 +1573,7 @@ void SchXMLExportHelper::exportTable() // write the original range name as id into the local table to // allow a correct re-association when copying via clipboard if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) && - ( mbRowSourceColumns || (aInnerIt == aColIt->begin())) ) + ( mbRowSourceColumns || (aColIt == aRowIt->begin())) ) { if( (*aDataRangeIter).getLength()) mrExport.AddAttribute( XML_NAMESPACE_TEXT, XML_ID, *aDataRangeIter ); @@ -1587,7 +1586,7 @@ void SchXMLExportHelper::exportTable() // if range iterator was used it should have reached its end OSL_ASSERT( bHasOwnData || (aDataRangeIter == aDataRangeEndIter) ); - OSL_ASSERT( bHasOwnData || (aFirstColumnRangeIter == aFirstColumnRangeEndIter) ); + OSL_ASSERT( bHasOwnData || (aRowDescriptions_RangeIter == aRowDescriptions_RangeEnd) ); } void SchXMLExportHelper::exportPlotArea( @@ -2112,8 +2111,8 @@ void SchXMLExportHelper::exportAxes( if( xValues.is()) { Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY ); - aCategoriesRange = lcl_ConvertRange( xValues->getSourceRangeRepresentation(), xNewDoc ); - m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xValues )); + maCategoriesRange = xValues->getSourceRangeRepresentation(); + aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc ); } } } @@ -3422,24 +3421,6 @@ awt::Size SchXMLExportHelper::getPageSize( const Reference< chart2::XChartDocume return aSize; } -void SchXMLExportHelper::swapDataArray( Sequence< Sequence< double > >& rSequence ) -{ - sal_Int32 nOuterSize = rSequence.getLength(); - sal_Int32 nInnerSize = rSequence[0].getLength(); // assume that all subsequences have same length - sal_Int32 i, o; - - Sequence< Sequence< double > > aResult( nInnerSize ); - Sequence< double >* pArray = aResult.getArray(); - for( i = 0; i < nInnerSize; i++ ) - { - pArray[ i ].realloc( nOuterSize ); - for( o = 0 ; o < nOuterSize ; o++ ) - aResult[ i ][ o ] = rSequence[ o ][ i ]; - } - - rSequence = aResult; -} - void SchXMLExportHelper::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates ) { if( !aStates.empty() ) diff --git a/xmloff/source/chart/SchXMLImport.cxx b/xmloff/source/chart/SchXMLImport.cxx index 4f32e90e861f..6afbaecb551c 100644 --- a/xmloff/source/chart/SchXMLImport.cxx +++ b/xmloff/source/chart/SchXMLImport.cxx @@ -47,7 +47,6 @@ #include <xmloff/xmlstyle.hxx> #include <com/sun/star/task/XStatusIndicatorSupplier.hpp> #include <com/sun/star/chart/XChartDocument.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> #include <com/sun/star/chart/ChartDataRowSource.hpp> #include <com/sun/star/container/XChild.hpp> #include <com/sun/star/uno/XComponentContext.hpp> @@ -507,113 +506,6 @@ const SvXMLTokenMap& SchXMLImportHelper::GetRegEquationAttrTokenMap() // ---------------------------------------- -sal_Int32 SchXMLImportHelper::GetNumberOfSeries() -{ - if( mxChartDoc.is()) - { - Reference< chart::XChartDataArray > xData( mxChartDoc->getData(), uno::UNO_QUERY ); - if( xData.is()) - { - Sequence< Sequence< double > > xArray = xData->getData(); - - if( xArray.getLength()) - return xArray[ 0 ].getLength(); - } - } - - return 0; -} - -sal_Int32 SchXMLImportHelper::GetLengthOfSeries() -{ - if( mxChartDoc.is()) - { - Reference< chart::XChartDataArray > xData( mxChartDoc->getData(), uno::UNO_QUERY ); - if( xData.is()) - { - Sequence< Sequence< double > > xArray = xData->getData(); - - return xArray.getLength(); - } - } - - return 0; -} - -// -1 means don't change -void SchXMLImportHelper::ResizeChartData( sal_Int32 nSeries, sal_Int32 nDataPoints ) -{ - if( mxChartDoc.is()) - { - sal_Bool bWasChanged = sal_False; - - sal_Bool bDataInColumns = sal_True; - Reference< beans::XPropertySet > xDiaProp( mxChartDoc->getDiagram(), uno::UNO_QUERY ); - if( xDiaProp.is()) - { - chart::ChartDataRowSource eRowSource; - xDiaProp->getPropertyValue( OUString::createFromAscii( "DataRowSource" )) >>= eRowSource; - bDataInColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS ); - - // the chart core treats donut chart with interchanged rows/columns - Reference< chart::XDiagram > xDiagram( xDiaProp, uno::UNO_QUERY ); - if( xDiagram.is()) - { - OUString sChartType = xDiagram->getDiagramType(); - if( 0 == sChartType.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.DonutDiagram" ))) - { - bDataInColumns = ! bDataInColumns; - } - } - } - sal_Int32 nColCount = bDataInColumns ? nSeries : nDataPoints; - sal_Int32 nRowCount = bDataInColumns ? nDataPoints : nSeries; - - Reference< chart::XChartDataArray > xData( mxChartDoc->getData(), uno::UNO_QUERY ); - if( xData.is()) - { - Sequence< Sequence< double > > xArray = xData->getData(); - - // increase number of rows - if( xArray.getLength() < nRowCount ) - { - sal_Int32 nOldLen = xArray.getLength(); - xArray.realloc( nRowCount ); - if( nColCount == -1 ) - { - sal_Int32 nSize = xArray[ 0 ].getLength(); - for( sal_Int32 i = nOldLen; i < nRowCount; i++ ) - xArray[ i ].realloc( nSize ); - } - bWasChanged = sal_True; - } - - if( nSeries == -1 && - nRowCount > 0 ) - nColCount = xArray[ 0 ].getLength(); - - // columns - if( nColCount > 0 && - xArray[ 0 ].getLength() < nColCount ) - { - if( nDataPoints == -1 ) - nRowCount = xArray.getLength(); - - for( sal_Int32 i = 0; i < nRowCount; i++ ) - xArray[ i ].realloc( nColCount ); - bWasChanged = sal_True; - } - - if( bWasChanged ) - { - xData->setData( xArray ); - mxChartDoc->attachData( - Reference< chart::XChartData >( xData, uno::UNO_QUERY )); - } - } - } -} - //static void SchXMLImportHelper::DeleteDataSeries( const Reference< chart2::XDataSeries > & xSeries, diff --git a/xmloff/source/chart/SchXMLTableContext.cxx b/xmloff/source/chart/SchXMLTableContext.cxx index 742d42cb5f15..6ba9a49e4502 100644 --- a/xmloff/source/chart/SchXMLTableContext.cxx +++ b/xmloff/source/chart/SchXMLTableContext.cxx @@ -30,6 +30,7 @@ #include "SchXMLTableContext.hxx" #include "SchXMLParagraphContext.hxx" +#include "SchXMLTextListContext.hxx" #include "SchXMLImport.hxx" #include "SchXMLTools.hxx" #include "transporttypes.hxx" @@ -44,7 +45,7 @@ #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/XChartTypeContainer.hpp> #include <com/sun/star/chart2/XInternalDataProvider.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> #include <com/sun/star/chart/ChartSeriesAddress.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/XPropertySetInfo.hpp> @@ -138,26 +139,10 @@ std::vector< Reference< chart2::XAxis > > lcl_getAxesHoldingCategoriesFromDiagra return aRet; } -void lcl_ApplyColumnLabels( - const ::std::vector< SchXMLCell > & rFirstRow, - Sequence< OUString > & rOutColumnLabels, - sal_Int32 nOffset ) -{ - const sal_Int32 nColumnLabelsSize = rOutColumnLabels.getLength(); - const sal_Int32 nMax = ::std::min< sal_Int32 >( nColumnLabelsSize, - static_cast< sal_Int32 >( rFirstRow.size()) - nOffset ); - OSL_ASSERT( nMax == nColumnLabelsSize ); - for( sal_Int32 i=0; i<nMax; ++i ) - if( rFirstRow[i+nOffset].eType == SCH_CELL_TYPE_STRING ) - rOutColumnLabels[i] = rFirstRow[i+nOffset].aString; -} - struct lcl_ApplyCellToData : public ::std::unary_function< SchXMLCell, void > { - lcl_ApplyCellToData( Sequence< double > & rOutData, - Sequence< OUString > & rOutRowLabels ) : + lcl_ApplyCellToData( Sequence< double > & rOutData ) : m_rData( rOutData ), - m_rRowLabels( rOutRowLabels ), m_nIndex( 0 ), m_nSize( rOutData.getLength()) { @@ -178,49 +163,11 @@ struct lcl_ApplyCellToData : public ::std::unary_function< SchXMLCell, void > private: Sequence< double > & m_rData; - Sequence< OUString > & m_rRowLabels; sal_Int32 m_nIndex; sal_Int32 m_nSize; double m_fNaN; }; -struct lcl_ApplyRowsToData : public ::std::unary_function< ::std::vector< SchXMLCell >, void > -{ - lcl_ApplyRowsToData( Sequence< Sequence< double > > & rOutData, - Sequence< OUString > & rOutRowLabels, - sal_Int32 nOffset, - bool bHasHeader ) : - m_rData( rOutData ), - m_rRowLabels( rOutRowLabels ), - m_nIndex( 0 ), - m_nOuterSize( rOutData.getLength()), - m_nOffset( nOffset ), - m_bHasHeader( bHasHeader ) - {} - void operator() ( const ::std::vector< SchXMLCell > & rRow ) - { - if( ! rRow.empty()) - { - // label - if( m_bHasHeader && m_nIndex < m_rRowLabels.getLength() && rRow.front().eType == SCH_CELL_TYPE_STRING ) - m_rRowLabels[m_nIndex] = rRow.front().aString; - - // values - if( m_nIndex < m_nOuterSize ) - ::std::for_each( rRow.begin() + m_nOffset, rRow.end(), lcl_ApplyCellToData( m_rData[m_nIndex], m_rRowLabels )); - } - ++m_nIndex; - } - -private: - Sequence< Sequence< double > > & m_rData; - Sequence< OUString > & m_rRowLabels; - sal_Int32 m_nIndex; - sal_Int32 m_nOuterSize; - sal_Int32 m_nOffset; - bool m_bHasHeader; -}; - Sequence< Sequence< double > > lcl_getSwappedArray( const Sequence< Sequence< double > > & rData ) { sal_Int32 nOldOuterSize = rData.getLength(); @@ -237,47 +184,6 @@ Sequence< Sequence< double > > lcl_getSwappedArray( const Sequence< Sequence< do return aResult; } -void lcl_applyXMLTableToInternalDataprovider( - const SchXMLTable & rTable, - const Reference< chart::XChartDataArray > & xDataArray ) -{ - sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size())); - sal_Int32 nRowOffset = 0; - if( rTable.bHasHeaderRow ) - { - --nNumRows; - nRowOffset = 1; - } - sal_Int32 nNumColumns( rTable.nMaxColumnIndex + 1 ); - sal_Int32 nColOffset = 0; - if( rTable.bHasHeaderColumn ) - { - --nNumColumns; - nColOffset = 1; - } - - Sequence< Sequence< double > > aData( nNumRows ); - Sequence< OUString > aRowLabels( nNumRows ); - Sequence< OUString > aColumnLabels( nNumColumns ); - for( sal_Int32 i=0; i<nNumRows; ++i ) - aData[i].realloc( nNumColumns ); - - if( rTable.aData.begin() != rTable.aData.end()) - { - if( rTable.bHasHeaderRow ) - lcl_ApplyColumnLabels( rTable.aData.front(), aColumnLabels, nColOffset ); - ::std::for_each( rTable.aData.begin() + nRowOffset, rTable.aData.end(), - lcl_ApplyRowsToData( aData, aRowLabels, nColOffset, rTable.bHasHeaderColumn )); - } - - xDataArray->setData( aData ); - - if( rTable.bHasHeaderColumn ) - xDataArray->setRowDescriptions( aRowLabels ); - if( rTable.bHasHeaderRow ) - xDataArray->setColumnDescriptions( aColumnLabels ); -} - void lcl_fillRangeMapping( const SchXMLTable & rTable, lcl_tOriginalRangeToInternalRangeMap & rOutRangeMap, @@ -830,7 +736,7 @@ void SchXMLTableCellContext::StartElement( const uno::Reference< xml::sax::XAttr } } - mbReadPara = sal_True; + mbReadText = sal_True; SchXMLCell aCell; aCell.eType = eValueType; @@ -841,8 +747,8 @@ void SchXMLTableCellContext::StartElement( const uno::Reference< xml::sax::XAttr SvXMLUnitConverter::convertDouble( fData, aCellContent ); aCell.fValue = fData; - // dont read following <text:p> element - mbReadPara = sal_False; + // dont read text from following <text:p> or <text:list> element + mbReadText = sal_False; } mrTable.aData[ mrTable.nRowIndex ].push_back( aCell ); @@ -858,9 +764,17 @@ SvXMLImportContext* SchXMLTableCellContext::CreateChildContext( { SvXMLImportContext* pContext = 0; - // <text:p> element - if( nPrefix == XML_NAMESPACE_TEXT && - IsXMLToken( rLocalName, XML_P ) ) + // <text:list> element + if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_LIST ) && mbReadText ) + { + SchXMLCell& rCell = mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ]; + rCell.pComplexString = new Sequence< OUString >(); + rCell.eType = SCH_CELL_TYPE_COMPLEX_STRING; + pContext = new SchXMLTextListContext( GetImport(), rLocalName, *rCell.pComplexString ); + mbReadText = sal_False;//don't apply text from <text:p> + } + // <text:p> element - read text and range-id + else if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_P ) ) { pContext = new SchXMLParagraphContext( GetImport(), rLocalName, maCellContent, &maRangeId ); } @@ -874,7 +788,7 @@ SvXMLImportContext* SchXMLTableCellContext::CreateChildContext( void SchXMLTableCellContext::EndElement() { - if( mbReadPara && maCellContent.getLength()) + if( mbReadText && maCellContent.getLength() ) //apply text from <text:p> element mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ].aString = maCellContent; if( maRangeId.getLength()) mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ].aRangeId = maRangeId; @@ -882,133 +796,90 @@ void SchXMLTableCellContext::EndElement() // ======================================== -// just interpret the table in a linear way with no references used -// (this is just a workaround for clipboard handling in EA2) -void SchXMLTableHelper::applyTableSimple( - const SchXMLTable& rTable, - const uno::Reference< chart::XChartDataArray > & xData ) +void lcl_ApplyCellToComplexLabel( const SchXMLCell& rCell, Sequence< OUString >& rComplexLabel ) { - // interpret table like this: - // - // series ----+---+ - // | | - // categories | | - // | | | - // V V V - // A B C ... - // 1 x x <--- labels - // 2 x 0 0 - // 3 x 0 0 - // ... - - // Standard Role-interpretation: - - // Column 1 contains the Categories - - // Chart Type/Class | Col 2 Col 3 Col 4 Col 5 Col 6 | Series | Domain - // -----------------+-----------------------------------+--------+------- - // Category Charts | Y 1 Y 2 Y 3 Y 4 ... | Y | - - // XY Chart | X all Y 1 Y 2 Y 3 ... | Y | X - // Stock Chart 1 | Min Max Close - - | Close | - - // Stock Chart 2 | Open Min Max Close - | Close | - - // Stock Chart 3 | Volume Min Max Close - | Close | - - // Stock Chart 4 | Volume Open Min Max Close | Close | - - - if( xData.is()) + if( rCell.eType == SCH_CELL_TYPE_STRING ) { - // get NaN - double fSolarNaN; - ::rtl::math::setNan( &fSolarNaN ); - double fNaN = fSolarNaN; - sal_Bool bConvertNaN = sal_False; - - uno::Reference< chart::XChartData > xChartData( xData, uno::UNO_QUERY ); - if( xChartData.is()) - { - fNaN = xChartData->getNotANumber(); - bConvertNaN = ( ! ::rtl::math::isNan( fNaN )); - } + rComplexLabel.realloc(1); + rComplexLabel[0] = rCell.aString; + } + else if( rCell.pComplexString && rCell.eType == SCH_CELL_TYPE_COMPLEX_STRING ) + rComplexLabel = *rCell.pComplexString; +} - sal_Int32 nRowCount = rTable.aData.size(); - sal_Int32 nColumnCount = 0; - sal_Int32 nCol = 0, nRow = 0; - if( nRowCount ) - { - nColumnCount = rTable.aData[ 0 ].size(); - ::std::vector< ::std::vector< SchXMLCell > >::const_iterator iRow = rTable.aData.begin(); - while( iRow != rTable.aData.end() ) - { - nColumnCount = ::std::max( nColumnCount, static_cast<sal_Int32>(iRow->size()) ); - iRow++; - } - } +void SchXMLTableHelper::applyTableToInternalDataProvider( + const SchXMLTable& rTable, + uno::Reference< chart2::XChartDocument > xChartDoc ) +{ + // apply all data read from the local table to the internal data provider + if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() ) + return; + Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider() ); + if( !xDataProv.is() ) + return; - // #i27909# avoid illegal index access for empty tables - if( nColumnCount == 0 || nRowCount == 0 ) - return; + //prepare the read local table data + sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size())); + sal_Int32 nRowOffset = 0; + if( rTable.bHasHeaderRow ) + { + --nNumRows; + nRowOffset = 1; + } + sal_Int32 nNumColumns( rTable.nMaxColumnIndex + 1 ); + sal_Int32 nColOffset = 0; + if( rTable.bHasHeaderColumn ) + { + --nNumColumns; + nColOffset = 1; + } - uno::Sequence< ::rtl::OUString > aCategories( nRowCount - 1 ); - uno::Sequence< ::rtl::OUString > aLabels( nColumnCount - 1 ); - uno::Sequence< uno::Sequence< double > > aData( nRowCount - 1 ); - for( nRow = 0; nRow < nRowCount - 1; nRow++ ) - aData[ nRow ].realloc( nColumnCount - 1 ); + Sequence< Sequence< double > > aDataInRows( nNumRows ); + Sequence< Sequence< OUString > > aComplexRowDescriptions( nNumRows ); + Sequence< Sequence< OUString > > aComplexColumnDescriptions( nNumColumns ); + for( sal_Int32 i=0; i<nNumRows; ++i ) + aDataInRows[i].realloc( nNumColumns ); - // set labels - ::std::vector< ::std::vector< SchXMLCell > >::const_iterator iRow = rTable.aData.begin(); - sal_Int32 nColumnCountOnFirstRow = iRow->size(); - for( nCol = 1; nCol < nColumnCountOnFirstRow; nCol++ ) + if( rTable.aData.begin() != rTable.aData.end()) + { + //apply column labels + if( rTable.bHasHeaderRow ) { - aLabels[ nCol - 1 ] = (*iRow)[ nCol ].aString; + const ::std::vector< SchXMLCell >& rFirstRow = rTable.aData.front(); + const sal_Int32 nColumnLabelsSize = aComplexColumnDescriptions.getLength(); + const sal_Int32 nMax = ::std::min< sal_Int32 >( nColumnLabelsSize, static_cast< sal_Int32 >( rFirstRow.size()) - nColOffset ); + OSL_ASSERT( nMax == nColumnLabelsSize ); + for( sal_Int32 i=0; i<nMax; ++i ) + lcl_ApplyCellToComplexLabel( rFirstRow[i+nColOffset], aComplexColumnDescriptions[i] ); } - xData->setColumnDescriptions( aLabels ); - double fVal; - const sal_Bool bConstConvertNan = bConvertNaN; - for( ++iRow, nRow = 0; iRow != rTable.aData.end(); iRow++, nRow++ ) + std::vector< ::std::vector< SchXMLCell > >::const_iterator aRowIter( rTable.aData.begin() + nRowOffset ); + std::vector< ::std::vector< SchXMLCell > >::const_iterator aEnd( rTable.aData.end() ); + for( sal_Int32 nRow = 0; aRowIter != aEnd && nRow < nNumRows; ++aRowIter, ++nRow ) { - aCategories[ nRow ] = (*iRow)[ 0 ].aString; - sal_Int32 nTableColCount( static_cast< sal_Int32 >((*iRow).size())); - for( nCol = 1; nCol < nTableColCount; nCol++ ) + const ::std::vector< SchXMLCell >& rRow = *aRowIter; + if( !rRow.empty() ) { - fVal = (*iRow)[ nCol ].fValue; - if( bConstConvertNan && - ::rtl::math::isNan( fVal )) - aData[ nRow ][ nCol - 1 ] = fNaN; - else - aData[ nRow ][ nCol - 1 ] = fVal; + // row label + if( rTable.bHasHeaderColumn ) + lcl_ApplyCellToComplexLabel( rRow.front(), aComplexRowDescriptions[nRow] ); + + // values + ::std::for_each( rRow.begin() + nColOffset, rRow.end(), lcl_ApplyCellToData( aDataInRows[nRow] )); } - // set remaining cells to NaN - for( ; nCol < nColumnCount; ++nCol ) - if( bConstConvertNan ) - aData[ nRow ][nCol - 1 ] = fNaN; - else - ::rtl::math::setNan( &(aData[ nRow ][nCol - 1 ])); } - xData->setRowDescriptions( aCategories ); - xData->setData( aData ); } -} -// ---------------------------------------- - -void SchXMLTableHelper::applyTableToInternalDataProvider( - const SchXMLTable& rTable, - uno::Reference< chart2::XChartDocument > xChartDoc ) -{ - if( ! (xChartDoc.is() && xChartDoc->hasInternalDataProvider())) - return; - Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider()); - Reference< chart::XChartDataArray > xDataArray( xDataProv, uno::UNO_QUERY ); - if( ! xDataArray.is()) + //apply the collected data to the chart + Reference< chart::XComplexDescriptionAccess > xDataAccess( xDataProv, uno::UNO_QUERY ); + if( !xDataAccess.is() ) return; - OSL_ASSERT( xDataProv.is()); - // prerequisite for this method: all objects (data series, domains, etc.) - // need their own range string. - - // apply all data read in the table to the chart data-array of the internal - // data provider - lcl_applyXMLTableToInternalDataprovider( rTable, xDataArray ); + xDataAccess->setData( aDataInRows ); + if( rTable.bHasHeaderColumn ) + xDataAccess->setComplexRowDescriptions( aComplexRowDescriptions ); + if( rTable.bHasHeaderRow ) + xDataAccess->setComplexColumnDescriptions( aComplexColumnDescriptions ); } void SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary( diff --git a/xmloff/source/chart/SchXMLTableContext.hxx b/xmloff/source/chart/SchXMLTableContext.hxx index e6c8ef61ac28..717628b18de0 100644 --- a/xmloff/source/chart/SchXMLTableContext.hxx +++ b/xmloff/source/chart/SchXMLTableContext.hxx @@ -45,7 +45,6 @@ namespace com { namespace sun { namespace star { }} namespace chart { class XChartDocument; - class XChartDataArray; struct ChartSeriesAddress; }}}} @@ -96,21 +95,11 @@ private: sal_Int32& nRows, sal_Int32& nColumns ); public: - /// The data for the ChartDocument is applied linearly - static void applyTableSimple( - const SchXMLTable& rTable, - const com::sun::star::uno::Reference< com::sun::star::chart::XChartDataArray > & xData ); - - /** The data for the ChartDocument is applied by reading the - table, the addresses of series, the addresses of labels, - the cell-range-address for the categories - */ static void applyTableToInternalDataProvider( const SchXMLTable& rTable, com::sun::star::uno::Reference< com::sun::star::chart2::XChartDocument > xChartDoc ); - /** Second part of applyTableToInternalDataProvider that has to be called after the data series - got their styles set. This function reorders local data to fit the - correct data structure. + /** This function reorders local data to fit the correct data structure. + Call it after the data series got their styles set. */ static void switchRangesFromOuterToInternalIfNecessary( const SchXMLTable& rTable, const tSchXMLLSequencesPerIndex & rLSequencesPerIndex, @@ -220,7 +209,7 @@ private: SchXMLTable& mrTable; rtl::OUString maCellContent; rtl::OUString maRangeId; - sal_Bool mbReadPara; + sal_Bool mbReadText; public: SchXMLTableCellContext( SchXMLImportHelper& rImpHelper, diff --git a/xmloff/source/chart/SchXMLTextListContext.cxx b/xmloff/source/chart/SchXMLTextListContext.cxx new file mode 100755 index 000000000000..884acb473108 --- /dev/null +++ b/xmloff/source/chart/SchXMLTextListContext.cxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#include "SchXMLImport.hxx" +#include "SchXMLTextListContext.hxx" +#include "SchXMLParagraphContext.hxx" + +#include "xmlnmspe.hxx" +#include <xmloff/xmltoken.hxx> +#include <xmloff/nmspmap.hxx> + +using ::rtl::OUString; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using namespace com::sun::star; +using namespace ::xmloff::token; + +//------------------------------------------------- +class SchXMLListItemContext : public SvXMLImportContext +{ +public: + SchXMLListItemContext( SvXMLImport& rImport, const OUString& rLocalName, OUString& rText ); + virtual ~SchXMLListItemContext(); + virtual void StartElement( const Reference< xml::sax::XAttributeList >& xAttrList ); + virtual void EndElement(); + + virtual SvXMLImportContext* CreateChildContext( + USHORT nPrefix, + const ::rtl::OUString& rLocalName, + const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList ); + +private: + ::rtl::OUString& m_rText; +}; + +SchXMLListItemContext::SchXMLListItemContext( + SvXMLImport& rImport + , const OUString& rLocalName + , OUString& rText ) + : SvXMLImportContext( rImport, XML_NAMESPACE_TEXT, rLocalName ) + , m_rText( rText ) +{ +} + +SchXMLListItemContext::~SchXMLListItemContext() +{} + +void SchXMLListItemContext::StartElement( const Reference< xml::sax::XAttributeList >& /*xAttrList*/ ) +{ +} + +void SchXMLListItemContext::EndElement() +{ +} + +SvXMLImportContext* SchXMLListItemContext::CreateChildContext( + USHORT nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList >& ) +{ + SvXMLImportContext* pContext = 0; + if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_P ) ) + pContext = new SchXMLParagraphContext( GetImport(), rLocalName, m_rText ); + else + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + return pContext; +} + +//------------------------------------------------- + +SchXMLTextListContext::SchXMLTextListContext( + SvXMLImport& rImport + , const OUString& rLocalName + , Sequence< OUString>& rTextList ) + : SvXMLImportContext( rImport, XML_NAMESPACE_TEXT, rLocalName ) + , m_rTextList( rTextList ) + , m_aTextVector() +{ +} + +SchXMLTextListContext::~SchXMLTextListContext() +{ +} + +void SchXMLTextListContext::StartElement( const Reference< xml::sax::XAttributeList >& /*xAttrList*/ ) +{ +} + +void SchXMLTextListContext::EndElement() +{ + sal_Int32 nCount = m_aTextVector.size(); + m_rTextList.realloc(nCount); + for( sal_Int32 nN=0; nN<nCount; nN++ ) + m_rTextList[nN]=m_aTextVector[nN]; +} + +SvXMLImportContext* SchXMLTextListContext::CreateChildContext( + USHORT nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList >& ) +{ + SvXMLImportContext* pContext = 0; + if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_LIST_ITEM ) ) + { + m_aTextVector.push_back( OUString() ); + pContext = new SchXMLListItemContext( GetImport(), rLocalName, m_aTextVector.back() ); + } + else + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + return pContext; +} diff --git a/xmloff/source/chart/SchXMLTextListContext.hxx b/xmloff/source/chart/SchXMLTextListContext.hxx new file mode 100755 index 000000000000..736331d10e71 --- /dev/null +++ b/xmloff/source/chart/SchXMLTextListContext.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SCH_XMLTEXTLISTCONTEXT_HXX_ +#define _SCH_XMLTEXTLISTCONTEXT_HXX_ + +#include <xmloff/xmlictxt.hxx> +#include "rtl/ustring.hxx" +#include <vector> + +namespace com { namespace sun { namespace star { namespace xml { namespace sax { + class XAttributeList; +}}}}} + +class SchXMLTextListContext : public SvXMLImportContext +{ +public: + SchXMLTextListContext( SvXMLImport& rImport, + const ::rtl::OUString& rLocalName, + ::com::sun::star::uno::Sequence< ::rtl::OUString>& rTextList ); + virtual ~SchXMLTextListContext(); + virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList ); + virtual void EndElement(); + + virtual SvXMLImportContext* CreateChildContext( + USHORT nPrefix, + const ::rtl::OUString& rLocalName, + const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList ); + +private: + ::com::sun::star::uno::Sequence< ::rtl::OUString>& m_rTextList; + std::vector< ::rtl::OUString> m_aTextVector; +}; + +#endif // _SCH_XMLTEXTLISTCONTEXT_HXX_ diff --git a/xmloff/source/chart/contexts.cxx b/xmloff/source/chart/contexts.cxx index 14928b697a1b..8d9ba3b7ff26 100644 --- a/xmloff/source/chart/contexts.cxx +++ b/xmloff/source/chart/contexts.cxx @@ -35,13 +35,6 @@ #include "SchXMLImport.hxx" #include "SchXMLCalculationSettingsContext.hxx" -// #ifndef _XMLOFF_XMLCHARTSTYLECONTEXT_HXX_ -// #include "XMLChartStyleContext.hxx" -// #endif -#include <com/sun/star/chart/XChartDocument.hpp> -#include <com/sun/star/chart/XChartDataArray.hpp> -#include <com/sun/star/chart/ChartDataRowSource.hpp> - #include "contexts.hxx" #include "SchXMLChartContext.hxx" diff --git a/xmloff/source/chart/makefile.mk b/xmloff/source/chart/makefile.mk index 33c217e51326..bfdc9aeb5e22 100644 --- a/xmloff/source/chart/makefile.mk +++ b/xmloff/source/chart/makefile.mk @@ -47,6 +47,7 @@ SLOFILES = $(SLO)$/ColorPropertySet.obj \ $(SLO)$/SchXMLChartContext.obj \ $(SLO)$/SchXMLPlotAreaContext.obj \ $(SLO)$/SchXMLParagraphContext.obj \ + $(SLO)$/SchXMLTextListContext.obj \ $(SLO)$/SchXMLSeriesHelper.obj \ $(SLO)$/SchXMLSeries2Context.obj \ $(SLO)$/PropertyMaps.obj \ diff --git a/xmloff/source/chart/transporttypes.hxx b/xmloff/source/chart/transporttypes.hxx index 213f97590c9d..27c8850e2b81 100644 --- a/xmloff/source/chart/transporttypes.hxx +++ b/xmloff/source/chart/transporttypes.hxx @@ -37,17 +37,37 @@ enum SchXMLCellType { SCH_CELL_TYPE_UNKNOWN, SCH_CELL_TYPE_FLOAT, - SCH_CELL_TYPE_STRING + SCH_CELL_TYPE_STRING, + SCH_CELL_TYPE_COMPLEX_STRING }; struct SchXMLCell { rtl::OUString aString; + ::com::sun::star::uno::Sequence< rtl::OUString >* pComplexString; double fValue; SchXMLCellType eType; rtl::OUString aRangeId; - SchXMLCell() : fValue( 0.0 ), eType( SCH_CELL_TYPE_UNKNOWN ) {} + SchXMLCell() : pComplexString(0), fValue( 0.0 ), eType( SCH_CELL_TYPE_UNKNOWN ) + {} + + SchXMLCell( const SchXMLCell& rOther ) + : aString( rOther.aString ) + , pComplexString( rOther.pComplexString ? new ::com::sun::star::uno::Sequence< rtl::OUString >( *rOther.pComplexString ) : 0 ) + , fValue( rOther.fValue ) + , eType( rOther.eType ) + , aRangeId( rOther.aRangeId ) + {} + + ~SchXMLCell() + { + if(pComplexString) + { + delete pComplexString; + pComplexString=0; + } + } }; struct SchXMLTable diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx index 980bceec97c3..af2ffc4352ed 100644 --- a/xmlsecurity/source/dialogs/certificateviewer.cxx +++ b/xmlsecurity/source/dialogs/certificateviewer.cxx @@ -125,16 +125,8 @@ CertificateViewerGeneralTP::CertificateViewerGeneralTP( Window* _pParent, Certif //Verify the certificate sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert, Sequence<Reference<css::security::XCertificate> >()); - //We currently have two status - //These errors are alloweds - sal_Int32 validCertErrors = css::security::CertificateValidity::VALID - | css::security::CertificateValidity::UNKNOWN_REVOKATION; - //Build a mask to filter out the allowed errors - sal_Int32 mask = ~validCertErrors; - // "subtract" the allowed error flags from the result - sal_Int32 certErrors = certStatus & mask; - bool bCertValid = certErrors > 0 ? false : true; + bool bCertValid = certStatus == css::security::CertificateValidity::VALID ? true : false; bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode(); if ( !bCertValid ) @@ -485,16 +477,7 @@ void CertificateViewerCertPathTP::ActivatePage() //Verify the certificate sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(rCert, Sequence<Reference<css::security::XCertificate> >()); - //We currently have two status - //These errors are alloweds - sal_Int32 validCertErrors = css::security::CertificateValidity::VALID - | css::security::CertificateValidity::UNKNOWN_REVOKATION; - - //Build a mask to filter out the allowed errors - sal_Int32 mask = ~validCertErrors; - // "subtract" the allowed error flags from the result - sal_Int32 certErrors = certStatus & mask; - bool bCertValid = certErrors > 0 ? false : true; + bool bCertValid = certStatus == css::security::CertificateValidity::VALID ? true : false; pParent = InsertCert( pParent, sName, rCert, bCertValid); } diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index cc62f883360c..5ea3fbb47a38 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -640,15 +640,7 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox() sal_Int32 certResult = xSecEnv->verifyCertificate(xCert, Sequence<css::uno::Reference<css::security::XCertificate> >()); - //These errors are alloweds - sal_Int32 validErrors = css::security::CertificateValidity::VALID - | css::security::CertificateValidity::UNKNOWN_REVOKATION; - - //Build a mask to filter out the allowed errors - sal_Int32 mask = ~validErrors; - // "subtract" the allowed error flags from the result - sal_Int32 errors = certResult & mask; - bCertValid = errors > 0 ? false : true; + bCertValid = certResult == css::security::CertificateValidity::VALID ? true : false; if ( bCertValid ) nValidCerts++; diff --git a/xmlsecurity/source/xmlsec/diagnose.cxx b/xmlsecurity/source/xmlsec/diagnose.cxx new file mode 100644 index 000000000000..1f17b12650b2 --- /dev/null +++ b/xmlsecurity/source/xmlsec/diagnose.cxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: xmlstreamio.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "diagnose.hxx" +#include <stdio.h> +#include <stdarg.h> +#include "rtl/instance.hxx" +#include "rtl/bootstrap.hxx" + +namespace xmlsecurity { + +struct UseDiagnose : public rtl::StaticWithInit< + const bool, UseDiagnose> +{ + const bool operator () () + { + ::rtl::OUString value; + sal_Bool res = rtl::Bootstrap::get( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("XMLSECURITY_TRACE")), value); + return res == sal_True ? true : false; + } +}; + +/* the function will print the string when + - build with debug + - the bootstrap variable XMLSECURITY_TRACE is set. + */ +void xmlsec_trace(const char* pszFormat, ...) +{ + bool bDebug = false; + +#if OSL_DEBUG_LEVEL > 1 + bDebug = true; +#endif + if (bDebug || UseDiagnose::get()) + { + va_list args; + fprintf(stderr, "[xmlsecurity] "); + va_start(args, pszFormat); + vfprintf(stderr, pszFormat, args); + va_end(args); + + fprintf(stderr,"\n"); + fflush(stderr); + } +} + + + +} diff --git a/xmlsecurity/source/xmlsec/diagnose.hxx b/xmlsecurity/source/xmlsec/diagnose.hxx new file mode 100644 index 000000000000..691d4e277c20 --- /dev/null +++ b/xmlsecurity/source/xmlsec/diagnose.hxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: xmlstreamio.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef XMLSECURITY_DIAGNOSE_HXX +#define XMLSECURITY_DIAGNOSE_HXX + + +namespace xmlsecurity +{ + + void xmlsec_trace(const char* pszFormat, ...); +} + + + +#endif //XMLSECURITY_DIAGNOSE_HXX diff --git a/xmlsecurity/source/xmlsec/makefile.mk b/xmlsecurity/source/xmlsec/makefile.mk index 1127419e12c8..44b668b84765 100644 --- a/xmlsecurity/source/xmlsec/makefile.mk +++ b/xmlsecurity/source/xmlsec/makefile.mk @@ -41,10 +41,12 @@ ENABLE_EXCEPTIONS = TRUE CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) .ENDIF -.IF "$(WITH_MOZILLA)" == "NO" +.IF "$(WITH_MOZILLA)" == "NO" || "$(ENABLE_NSS_MODULE)"!="YES" +.IF "$(SYSTEM_MOZILLA)" != "YES" @all: @echo "No mozilla -> no nss -> no libxmlsec -> no xmlsecurity.." .ENDIF +.ENDIF .IF "$(CRYPTO_ENGINE)" == "mscrypto" CDEFS += -DXMLSEC_CRYPTO_MSCRYPTO -DXMLSEC_NO_XSLT @@ -62,7 +64,8 @@ SLOFILES = \ $(SLO)$/certificateextension_xmlsecimpl.obj \ $(SLO)$/xmlstreamio.obj \ $(SLO)$/errorcallback.obj \ - $(SLO)$/xsec_xmlsec.obj + $(SLO)$/xsec_xmlsec.obj \ + $(SLO)$/diagnose.obj # --- Targets ------------------------------------------------------ diff --git a/xmlsecurity/source/xmlsec/mscrypt/makefile.mk b/xmlsecurity/source/xmlsec/mscrypt/makefile.mk index fd02aa7767fa..20153edf18e6 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/makefile.mk +++ b/xmlsecurity/source/xmlsec/mscrypt/makefile.mk @@ -43,10 +43,12 @@ LIBTARGET=NO .IF "$(CRYPTO_ENGINE)" == "mscrypto" -.IF "$(WITH_MOZILLA)" == "NO" +.IF "$(WITH_MOZILLA)" == "NO" || "$(ENABLE_NSS_MODULE)"!="YES" +.IF "$(SYSTEM_MOZILLA)" != "YES" @all: @echo "No mozilla -> no nss -> no libxmlsec -> no xmlsecurity/nss" .ENDIF +.ENDIF CDEFS += -DXMLSEC_CRYPTO_MSCRYPTO -DXMLSEC_NO_XSLT diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx index e84de0698016..71ff13fb3f82 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx @@ -37,6 +37,7 @@ #pragma warning(pop) #endif #include <sal/config.h> +#include <osl/thread.h> #include "securityenvironment_mscryptimpl.hxx" #ifndef _X509CERTIFICATE_NSSIMPL_HXX_ @@ -60,7 +61,11 @@ #include <osl/process.h> //CP : end +#include <rtl/memory.h> +#include "../diagnose.hxx" + +using namespace xmlsecurity; using namespace ::com::sun::star::uno ; using namespace ::com::sun::star::lang ; using ::com::sun::star::lang::XMultiServiceFactory ; @@ -69,9 +74,58 @@ using ::rtl::OUString ; using ::com::sun::star::xml::crypto::XSecurityEnvironment ; using ::com::sun::star::security::XCertificate ; +namespace css = ::com::sun::star; extern X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ; +struct CertErrorToString{ + DWORD error; + char * name; +}; + +CertErrorToString arErrStrings[] = +{ + { 0x00000000, "CERT_TRUST_NO_ERROR"}, + { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"}, + { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"}, + { 0x00000004, "CERT_TRUST_IS_REVOKED" }, + { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" }, + { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"}, + { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"}, + { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"}, + { 0x00000080, "CERT_TRUST_IS_CYCLIC"}, + { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"}, + { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"}, + { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"}, + { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"}, + { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"}, + { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"}, + { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"}, + { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"}, + { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"}, + { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"}, + { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"}, + { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"}, + //Chain errors + { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"}, + { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"}, + { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"}, + { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"} +}; + +void traceTrustStatus(DWORD err) +{ + int numErrors = sizeof(arErrStrings) / sizeof(CertErrorToString); + xmlsec_trace("The certificate error status is: "); + if (err == 0) + xmlsec_trace("%s", arErrStrings[0].name); + for (int i = 1; i < numErrors; i++) + { + if (arErrStrings[i].error & err) + xmlsec_trace("%s", arErrStrings[i].name); + } +} + SecurityEnvironment_MSCryptImpl :: SecurityEnvironment_MSCryptImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_hProv( NULL ) , m_pszContainer( NULL ) , m_hKeyStore( NULL ), m_hCertStore( NULL ), m_tSymKeyList() , m_tPubKeyList() , m_tPriKeyList(), m_xServiceManager( aFactory ), m_bEnableDefault( sal_False ) { } @@ -891,6 +945,11 @@ HCERTSTORE getCertStoreForIntermediatCerts( for (int i = 0; i < seqCerts.getLength(); i++) { + xmlsec_trace("Added temporary certificate: \n%s", + OUStringToOString(seqCerts[i]->getSubjectName(), + osl_getThreadTextEncoding()).getStr()); + + Sequence<sal_Int8> data = seqCerts[i]->getEncoded(); PCCERT_CONTEXT cert = CertCreateCertificateContext( X509_ASN_ENCODING, ( const BYTE* )&data[0], data.getLength()); @@ -901,6 +960,11 @@ HCERTSTORE getCertStoreForIntermediatCerts( } return store; } + +//We return only valid or invalid, as long as the API documentation expresses +//explicitly that all validation steps are carried out even if one or several +//errors occur. See also +//http://wiki.services.openoffice.org/wiki/Certificate_Path_Validation#Validation_status sal_Int32 SecurityEnvironment_MSCryptImpl :: verifyCertificate( const Reference< ::com::sun::star::security::XCertificate >& aCert, const Sequence< Reference< ::com::sun::star::security::XCertificate > >& seqCerts) @@ -910,17 +974,16 @@ sal_Int32 SecurityEnvironment_MSCryptImpl :: verifyCertificate( PCCERT_CHAIN_CONTEXT pChainContext = NULL; PCCERT_CONTEXT pCertContext = NULL; const X509Certificate_MSCryptImpl* xcert = NULL; - DWORD chainStatus ; - - CERT_ENHKEY_USAGE enhKeyUsage ; - CERT_USAGE_MATCH certUsage ; - CERT_CHAIN_PARA chainPara ; Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ; if( !xCertTunnel.is() ) { throw RuntimeException() ; } + xmlsec_trace("Start verification of certificate: \n %s", + OUStringToOString( + aCert->getSubjectName(), osl_getThreadTextEncoding()).getStr()); + xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ; if( xcert == NULL ) { throw RuntimeException() ; @@ -928,6 +991,11 @@ sal_Int32 SecurityEnvironment_MSCryptImpl :: verifyCertificate( pCertContext = xcert->getMswcryCert() ; + CERT_ENHKEY_USAGE enhKeyUsage ; + CERT_USAGE_MATCH certUsage ; + CERT_CHAIN_PARA chainPara ; + rtl_zeroMemory(&chainPara, sizeof(CERT_CHAIN_PARA)); + //Prepare parameter for CertGetCertificateChain enhKeyUsage.cUsageIdentifier = 0 ; enhKeyUsage.rgpszUsageIdentifier = NULL ; @@ -975,130 +1043,92 @@ sal_Int32 SecurityEnvironment_MSCryptImpl :: verifyCertificate( } //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST + //We do not check revocation of the root. In most cases there are none. + //Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN + xmlsec_trace("Verifying cert using revocation information."); bChain = CertGetCertificateChain( NULL , pCertContext , NULL , //use current system time hCollectionStore, &chainPara , - CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME , + CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, NULL , &pChainContext); - if (!bChain) - pChainContext = NULL; - - } - - if(bChain && pChainContext != NULL ) - { - chainStatus = pChainContext->TrustStatus.dwErrorStatus ; - - // JL & TKR: Until we have a test suite to test all error types we just say that the cert is - // valid or invalid with no further separation. - // Error CERT_TRUST_IS_OFFLINE_REVOCATION and CERT_TRUST_REVOCATION_STATUS_UNKNOWN are treated separate - // because they are ignored ( Bad! ) in the currently situation - - if( chainStatus == CERT_TRUST_NO_ERROR ) - { - validity = ::com::sun::star::security::CertificateValidity::VALID ; - } - - if ( ( chainStatus & CERT_TRUST_IS_OFFLINE_REVOCATION ) == CERT_TRUST_IS_OFFLINE_REVOCATION ) { - validity |= ::com::sun::star::security::CertificateValidity::UNKNOWN_REVOKATION ; - } - - if ( ( chainStatus & CERT_TRUST_REVOCATION_STATUS_UNKNOWN ) == CERT_TRUST_REVOCATION_STATUS_UNKNOWN ) { - validity |= ::com::sun::star::security::CertificateValidity::UNKNOWN_REVOKATION ; - } - - if (chainStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE - || chainStatus & CERT_TRUST_IS_CYCLIC - || chainStatus & CERT_TRUST_INVALID_POLICY_CONSTRAINTS - || chainStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS - || chainStatus & CERT_TRUST_INVALID_NAME_CONSTRAINTS - || chainStatus & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY - || chainStatus & CERT_TRUST_CTL_IS_NOT_TIME_VALID - || chainStatus & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID - || chainStatus & CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE - || chainStatus & CERT_TRUST_IS_NOT_TIME_VALID - || chainStatus & CERT_TRUST_IS_NOT_TIME_NESTED - || chainStatus & CERT_TRUST_IS_REVOKED - || chainStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID - || chainStatus & CERT_TRUST_IS_UNTRUSTED_ROOT - || chainStatus & CERT_TRUST_INVALID_EXTENSION - || chainStatus & CERT_TRUST_IS_PARTIAL_CHAIN ) + if (bChain && pChainContext->cChain > 0) { - validity = ::com::sun::star::security::CertificateValidity::INVALID; - } -/* + xmlsec_trace("Overall error status (all chains):"); + traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus); + //highest quality chains come first + PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0]; + xmlsec_trace("Error status of first chain: "); + traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus); + + //CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate + //has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed. + DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN | + CERT_TRUST_IS_OFFLINE_REVOCATION; + DWORD otherErrorsMask = ~revocationFlags; + if( !(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask)) - if( ( chainStatus & CERT_TRUST_IS_NOT_TIME_VALID ) == CERT_TRUST_IS_NOT_TIME_VALID ) { - validity |= ::com::sun::star::security::CertificateValidity::TIME_INVALID ; - } - - if( ( chainStatus & CERT_TRUST_IS_NOT_TIME_NESTED ) == CERT_TRUST_IS_NOT_TIME_NESTED ) { - validity |= ::com::sun::star::security::CertificateValidity::NOT_TIME_NESTED; - } - - if( ( chainStatus & CERT_TRUST_IS_REVOKED ) == CERT_TRUST_IS_REVOKED ) { - validity |= ::com::sun::star::security::CertificateValidity::REVOKED ; - } - - //JL My interpretation is that CERT_TRUST_IS_OFFLINE_REVOCATION does not mean that the certificate was revoked. - //Instead the CRL cannot be retrieved from the net, or an available CRL is stale (too old). - //This error may also occurs if the certificate does not contain the CDP (Certificate Distribution Point)extension - if( ( chainStatus & CERT_TRUST_IS_OFFLINE_REVOCATION ) == CERT_TRUST_IS_OFFLINE_REVOCATION ) { - validity |= ::com::sun::star::security::CertificateValidity::UNKNOWN_REVOKATION ; - } - - if( ( chainStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID ) == CERT_TRUST_IS_NOT_SIGNATURE_VALID ) { - validity |= ::com::sun::star::security::CertificateValidity::SIGNATURE_INVALID ; - } - - if( ( chainStatus & CERT_TRUST_IS_UNTRUSTED_ROOT ) == CERT_TRUST_IS_UNTRUSTED_ROOT ) { - validity |= ::com::sun::star::security::CertificateValidity::ROOT_UNTRUSTED ; - } - - if( ( chainStatus & CERT_TRUST_REVOCATION_STATUS_UNKNOWN ) == CERT_TRUST_REVOCATION_STATUS_UNKNOWN ) { - validity |= ::com::sun::star::security::CertificateValidity::UNKNOWN_REVOKATION ; - } - - if( ( chainStatus & CERT_TRUST_INVALID_EXTENSION ) == CERT_TRUST_INVALID_EXTENSION ) { - validity |= ::com::sun::star::security::CertificateValidity::EXTENSION_INVALID ; - } - - if( ( chainStatus & CERT_TRUST_IS_PARTIAL_CHAIN ) == CERT_TRUST_IS_PARTIAL_CHAIN ) { - validity |= ::com::sun::star::security::CertificateValidity::CHAIN_INCOMPLETE ; + { + //No errors except maybe those caused by missing revocation information + //Check if there are errors + if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags) + { + //No revocation information. Because MSDN documentation is not + //clear about if all other tests are performed if an error occurrs, + //we test again, without requiring revocation checking. + CertFreeCertificateChain(pChainContext); + pChainContext = NULL; + xmlsec_trace("Checking again but without requiring revocation information."); + bChain = CertGetCertificateChain( + NULL , + pCertContext , + NULL , //use current system time + hCollectionStore, + &chainPara , + 0, + NULL , + &pChainContext); + if (bChain + && pChainContext->cChain > 0 + && pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR) + { + xmlsec_trace("Certificate is valid.\n"); + validity = ::com::sun::star::security::CertificateValidity::VALID; + } + else + { + xmlsec_trace("Certificate is invalid.\n"); + } + } + else + { + //valid and revocation information available + xmlsec_trace("Certificate is valid.\n"); + validity = ::com::sun::star::security::CertificateValidity::VALID; + } + } + else + { + //invalid + xmlsec_trace("Certificate is invalid.\n"); + validity = ::com::sun::star::security::CertificateValidity::INVALID ; + } } - //todo - if (chainStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE - || chainStatus & CERT_TRUST_IS_CYCLIC - || chainStatus & CERT_TRUST_INVALID_POLICY_CONSTRAINTS - || chainStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS - || chainStatus & CERT_TRUST_INVALID_NAME_CONSTRAINTS - || chainStatus & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT - || chainStatus & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY - || chainStatus & CERT_TRUST_CTL_IS_NOT_TIME_VALID - || chainStatus & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID - || chainStatus & CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) + else { - validity = ::com::sun::star::security::CertificateValidity::INVALID; + xmlsec_trace("CertGetCertificateChaine failed.\n"); } -*/ - } else { - validity = ::com::sun::star::security::CertificateValidity::INVALID ; } if (pChainContext) + { CertFreeCertificateChain(pChainContext); + pChainContext = NULL; + } //Close the additional store, do not destroy the contained certs CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); diff --git a/xmlsecurity/source/xmlsec/nss/certerrors.h b/xmlsecurity/source/xmlsec/nss/certerrors.h new file mode 100644 index 000000000000..9b9801f21f59 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/certerrors.h @@ -0,0 +1,384 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: securityenvironment_nssimpl.cxx,v $ + * $Revision: 1.23 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +{SEC_ERROR_IO, "An I/O error occurred during security authorization."}, + +{SEC_ERROR_LIBRARY_FAILURE, "security library failure."}, + +{SEC_ERROR_BAD_DATA, "security library: received bad data."}, + +{SEC_ERROR_OUTPUT_LEN, "security library: output length error."}, + +{SEC_ERROR_INPUT_LEN, "security library has experienced an input length error."}, + +{SEC_ERROR_INVALID_ARGS, "security library: invalid arguments."}, + +{SEC_ERROR_INVALID_ALGORITHM, "security library: invalid algorithm."}, + +{SEC_ERROR_INVALID_AVA, "security library: invalid AVA."}, + +{SEC_ERROR_INVALID_TIME, "Improperly formatted time string."}, + +{SEC_ERROR_BAD_DER, "security library: improperly formatted DER-encoded message."}, + +{SEC_ERROR_BAD_SIGNATURE, "Peer's certificate has an invalid signature."}, + +{SEC_ERROR_EXPIRED_CERTIFICATE, "Peer's Certificate has expired."}, + +{SEC_ERROR_REVOKED_CERTIFICATE, "Peer's Certificate has been revoked."}, + +{SEC_ERROR_UNKNOWN_ISSUER, "Peer's Certificate issuer is not recognized."}, + +{SEC_ERROR_BAD_KEY, "Peer's public key is invalid."}, + +{SEC_ERROR_BAD_PASSWORD, "The security password entered is incorrect."}, + +{SEC_ERROR_RETRY_PASSWORD, "New password entered incorrectly. Please try again."}, + +{SEC_ERROR_NO_NODELOCK, "security library: no nodelock."}, + +{SEC_ERROR_BAD_DATABASE, "security library: bad database."}, + +{SEC_ERROR_NO_MEMORY, "security library: memory allocation failure."}, + +{SEC_ERROR_UNTRUSTED_ISSUER, "Peer's certificate issuer has been marked as not trusted by the user."}, + +{SEC_ERROR_UNTRUSTED_CERT, "Peer's certificate has been marked as not trusted by the user."}, + +{SEC_ERROR_DUPLICATE_CERT, "Certificate already exists in your database."}, + +{SEC_ERROR_DUPLICATE_CERT_NAME, "Downloaded certificate's name duplicates one already in your database."}, + +{SEC_ERROR_ADDING_CERT, "Error adding certificate to database."}, + +{SEC_ERROR_FILING_KEY, "Error refiling the key for this certificate."}, + +{SEC_ERROR_NO_KEY, "The private key for this certificate cannot be found in key database"}, + +{SEC_ERROR_CERT_VALID, "This certificate is valid."}, + +{SEC_ERROR_CERT_NOT_VALID, "This certificate is not valid."}, + +{SEC_ERROR_CERT_NO_RESPONSE, "Cert Library: No Response"}, + +{SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, "The certificate issuer's certificate has expired. Check your system date and time."}, + +{SEC_ERROR_CRL_EXPIRED, "The CRL for the certificate's issuer has expired. Update it or check your system date and time."}, + +{SEC_ERROR_CRL_BAD_SIGNATURE, "The CRL for the certificate's issuer has an invalid signature."}, + +{SEC_ERROR_CRL_INVALID, "New CRL has an invalid format."}, + +{SEC_ERROR_EXTENSION_VALUE_INVALID, "Certificate extension value is invalid."}, + +{SEC_ERROR_EXTENSION_NOT_FOUND, "Certificate extension not found."}, + +{SEC_ERROR_CA_CERT_INVALID, "Issuer certificate is invalid."}, + +{SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, "Certificate path length constraint is invalid."}, + +{SEC_ERROR_CERT_USAGES_INVALID, "Certificate usages field is invalid."}, + +{SEC_INTERNAL_ONLY, "**Internal ONLY module**"}, + +{SEC_ERROR_INVALID_KEY, "The key does not support the requested operation."}, + +{SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, "Certificate contains unknown critical extension."}, + +{SEC_ERROR_OLD_CRL, "New CRL is not later than the current one."}, + +{SEC_ERROR_NO_EMAIL_CERT, "Not encrypted or signed: you do not yet have an email certificate."}, + +{SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, "Not encrypted: you do not have certificates for each of the recipients."}, + +{SEC_ERROR_NOT_A_RECIPIENT, "Cannot decrypt: you are not a recipient, or matching certificate and \ +private key not found."}, + +{SEC_ERROR_PKCS7_KEYALG_MISMATCH, "Cannot decrypt: key encryption algorithm does not match your certificate."}, + +{SEC_ERROR_PKCS7_BAD_SIGNATURE, "Signature verification failed: no signer found, too many signers found, \ +or improper or corrupted data."}, + +{SEC_ERROR_UNSUPPORTED_KEYALG, "Unsupported or unknown key algorithm."}, + +{SEC_ERROR_DECRYPTION_DISALLOWED, "Cannot decrypt: encrypted using a disallowed algorithm or key size."}, + + +/* Fortezza Alerts */ +{XP_SEC_FORTEZZA_BAD_CARD, "Fortezza card has not been properly initialized. \ +Please remove it and return it to your issuer."}, + +{XP_SEC_FORTEZZA_NO_CARD, "No Fortezza cards Found"}, + +{XP_SEC_FORTEZZA_NONE_SELECTED, "No Fortezza card selected"}, + +{XP_SEC_FORTEZZA_MORE_INFO, "Please select a personality to get more info on"}, + +{XP_SEC_FORTEZZA_PERSON_NOT_FOUND, "Personality not found"}, + +{XP_SEC_FORTEZZA_NO_MORE_INFO, "No more information on that Personality"}, + +{XP_SEC_FORTEZZA_BAD_PIN, "Invalid Pin"}, + +{XP_SEC_FORTEZZA_PERSON_ERROR, "Couldn't initialize Fortezza personalities."}, +/* end fortezza alerts. */ + +{SEC_ERROR_NO_KRL, "No KRL for this site's certificate has been found."}, + +{SEC_ERROR_KRL_EXPIRED, "The KRL for this site's certificate has expired."}, + +{SEC_ERROR_KRL_BAD_SIGNATURE, "The KRL for this site's certificate has an invalid signature."}, + +{SEC_ERROR_REVOKED_KEY, "The key for this site's certificate has been revoked."}, + +{SEC_ERROR_KRL_INVALID, "New KRL has an invalid format."}, + +{SEC_ERROR_NEED_RANDOM, "security library: need random data."}, + +{SEC_ERROR_NO_MODULE, "security library: no security module can perform the requested operation."}, + +{SEC_ERROR_NO_TOKEN, "The security card or token does not exist, needs to be initialized, or has been removed."}, + +{SEC_ERROR_READ_ONLY, "security library: read-only database."}, + +{SEC_ERROR_NO_SLOT_SELECTED, "No slot or token was selected."}, + +{SEC_ERROR_CERT_NICKNAME_COLLISION, "A certificate with the same nickname already exists."}, + +{SEC_ERROR_KEY_NICKNAME_COLLISION, "A key with the same nickname already exists."}, + +{SEC_ERROR_SAFE_NOT_CREATED, "error while creating safe object"}, + +{SEC_ERROR_BAGGAGE_NOT_CREATED, "error while creating baggage object"}, + +{XP_JAVA_REMOVE_PRINCIPAL_ERROR, "Couldn't remove the principal"}, + +{XP_JAVA_DELETE_PRIVILEGE_ERROR, "Couldn't delete the privilege"}, + +{XP_JAVA_CERT_NOT_EXISTS_ERROR, "This principal doesn't have a certificate"}, + +{SEC_ERROR_BAD_EXPORT_ALGORITHM, "Required algorithm is not allowed."}, + +{SEC_ERROR_EXPORTING_CERTIFICATES, "Error attempting to export certificates."}, + +{SEC_ERROR_IMPORTING_CERTIFICATES, "Error attempting to import certificates."}, + +{SEC_ERROR_PKCS12_DECODING_PFX, "Unable to import. Decoding error. File not valid."}, + +{SEC_ERROR_PKCS12_INVALID_MAC, "Unable to import. Invalid MAC. Incorrect password or corrupt file."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, "Unable to import. MAC algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, "Unable to import. Only password integrity and privacy modes supported."}, + +{SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, "Unable to import. File structure is corrupt."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, "Unable to import. Encryption algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, "Unable to import. File version not supported."}, + +{SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, "Unable to import. Incorrect privacy password."}, + +{SEC_ERROR_PKCS12_CERT_COLLISION, "Unable to import. Same nickname already exists in database."}, + +{SEC_ERROR_USER_CANCELLED, "The user pressed cancel."}, + +{SEC_ERROR_PKCS12_DUPLICATE_DATA, "Not imported, already in database."}, + +{SEC_ERROR_MESSAGE_SEND_ABORTED, "Message not sent."}, + +{SEC_ERROR_INADEQUATE_KEY_USAGE, "Certificate key usage inadequate for attempted operation."}, + +{SEC_ERROR_INADEQUATE_CERT_TYPE, "Certificate type not approved for application."}, + +{SEC_ERROR_CERT_ADDR_MISMATCH, "Address in signing certificate does not match address in message headers."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, "Unable to import. Error attempting to import private key."}, + +{SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, "Unable to import. Error attempting to import certificate chain."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, "Unable to export. Unable to locate certificate or key by nickname."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, "Unable to export. Private Key could not be located and exported."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_WRITE, "Unable to export. Unable to write the export file."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_READ, "Unable to import. Unable to read the import file."}, + +{SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, "Unable to export. Key database corrupt or deleted."}, + +{SEC_ERROR_KEYGEN_FAIL, "Unable to generate public/private key pair."}, + +{SEC_ERROR_INVALID_PASSWORD, "Password entered is invalid. Please pick a different one."}, + +{SEC_ERROR_RETRY_OLD_PASSWORD, "Old password entered incorrectly. Please try again."}, + +{SEC_ERROR_BAD_NICKNAME, "Certificate nickname already in use."}, + +{SEC_ERROR_NOT_FORTEZZA_ISSUER, "Peer FORTEZZA chain has a non-FORTEZZA Certificate."}, + +{SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, "A sensitive key cannot be moved to the slot where it is needed."}, + +{SEC_ERROR_JS_INVALID_MODULE_NAME, "Invalid module name."}, + +{SEC_ERROR_JS_INVALID_DLL, "Invalid module path/filename"}, + +{SEC_ERROR_JS_ADD_MOD_FAILURE, "Unable to add module"}, + +{SEC_ERROR_JS_DEL_MOD_FAILURE, "Unable to delete module"}, + +{SEC_ERROR_OLD_KRL, "New KRL is not later than the current one."}, + +{SEC_ERROR_CKL_CONFLICT, "New CKL has different issuer than current CKL. Delete current CKL."}, + +{SEC_ERROR_CERT_NOT_IN_NAME_SPACE, "The Certifying Authority for this certificate is not permitted to issue a \ +certificate with this name."}, + +{SEC_ERROR_KRL_NOT_YET_VALID, "The key revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_CRL_NOT_YET_VALID, "The certificate revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_UNKNOWN_CERT, "The requested certificate could not be found."}, + +{SEC_ERROR_UNKNOWN_SIGNER, "The signer's certificate could not be found."}, + +{SEC_ERROR_CERT_BAD_ACCESS_LOCATION, "The location for the certificate status server has invalid format."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, "The OCSP response cannot be fully decoded; it is of an unknown type."}, + +{SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, "The OCSP server returned unexpected/invalid HTTP data."}, + +{SEC_ERROR_OCSP_MALFORMED_REQUEST, "The OCSP server found the request to be corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_SERVER_ERROR, "The OCSP server experienced an internal error."}, + +{SEC_ERROR_OCSP_TRY_SERVER_LATER, "The OCSP server suggests trying again later."}, + +{SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, "The OCSP server requires a signature on this request."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, "The OCSP server has refused this request as unauthorized."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, "The OCSP server returned an unrecognizable status."}, + +{SEC_ERROR_OCSP_UNKNOWN_CERT, "The OCSP server has no status for the certificate."}, + +{SEC_ERROR_OCSP_NOT_ENABLED, "You must enable OCSP before performing this operation."}, + +{SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, "You must set the OCSP default responder before performing this operation."}, + +{SEC_ERROR_OCSP_MALFORMED_RESPONSE, "The response from the OCSP server was corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, "The signer of the OCSP response is not authorized to give status for \ +this certificate."}, + +{SEC_ERROR_OCSP_FUTURE_RESPONSE, "The OCSP response is not yet valid (contains a date in the future},."}, + +{SEC_ERROR_OCSP_OLD_RESPONSE, "The OCSP response contains out-of-date information."}, + +{SEC_ERROR_DIGEST_NOT_FOUND, "The CMS or PKCS #7 Digest was not found in signed message."}, + +{SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, "The CMS or PKCS #7 Message type is unsupported."}, + +{SEC_ERROR_MODULE_STUCK, "PKCS #11 module could not be removed because it is still in use."}, + +{SEC_ERROR_BAD_TEMPLATE, "Could not decode ASN.1 data. Specified template was invalid."}, + +{SEC_ERROR_CRL_NOT_FOUND, "No matching CRL was found."}, + +{SEC_ERROR_REUSED_ISSUER_AND_SERIAL, "You are attempting to import a cert with the same issuer/serial as \ +an existing cert, but that is not the same cert."}, + +{SEC_ERROR_BUSY, "NSS could not shutdown. Objects are still in use."}, + +{SEC_ERROR_EXTRA_INPUT, "DER-encoded message contained extra unused data."}, + +{SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, "Unsupported elliptic curve."}, + +{SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, "Unsupported elliptic curve point form."}, + +{SEC_ERROR_UNRECOGNIZED_OID, "Unrecognized Object Identifier."}, + +{SEC_ERROR_OCSP_INVALID_SIGNING_CERT, "Invalid OCSP signing certificate in OCSP response."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_CRL, "Certificate is revoked in issuer's certificate revocation list."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_OCSP, "Issuer's OCSP responder reports certificate is revoked."}, + +{SEC_ERROR_CRL_INVALID_VERSION, "Issuer's Certificate Revocation List has an unknown version number."}, + +{SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, "Issuer's V1 Certificate Revocation List has a critical extension."}, + +{SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, "Issuer's V2 Certificate Revocation List has an unknown critical extension."}, + +{SEC_ERROR_UNKNOWN_OBJECT_TYPE, "Unknown object type specified."}, + +{SEC_ERROR_INCOMPATIBLE_PKCS11, "PKCS #11 driver violates the spec in an incompatible way."}, + +{SEC_ERROR_NO_EVENT, "No new slot event is available at this time."}, + +{SEC_ERROR_CRL_ALREADY_EXISTS, "CRL already exists."}, + +{SEC_ERROR_NOT_INITIALIZED, "NSS is not initialized."}, + +{SEC_ERROR_TOKEN_NOT_LOGGED_IN, "The operation failed because the PKCS#11 token is not logged in."}, + +{SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, "Configured OCSP responder's certificate is invalid."}, + +{SEC_ERROR_OCSP_BAD_SIGNATURE, "OCSP response has an invalid signature."}, + +{SEC_ERROR_OUT_OF_SEARCH_LIMITS, "Cert validation search is out of search limits"}, + +{SEC_ERROR_INVALID_POLICY_MAPPING, "Policy mapping contains anypolicy"}, + +{SEC_ERROR_POLICY_VALIDATION_FAILED, "Cert chain fails policy validation"}, + +{SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, "Unknown location type in cert AIA extension"}, + +{SEC_ERROR_BAD_HTTP_RESPONSE, "Server returned bad HTTP response"}, + +{SEC_ERROR_BAD_LDAP_RESPONSE, "Server returned bad LDAP response"}, + +{SEC_ERROR_FAILED_TO_ENCODE_DATA, "Failed to encode data with ASN1 encoder"}, + +{SEC_ERROR_BAD_INFO_ACCESS_LOCATION, "Bad information access location in cert extension"}, + +{SEC_ERROR_LIBPKIX_INTERNAL, "Libpkix internal error occured during cert validation."}, + +{SEC_ERROR_PKCS11_GENERAL_ERROR, "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred."}, + +{SEC_ERROR_PKCS11_FUNCTION_FAILED, "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed."}, + +{SEC_ERROR_PKCS11_DEVICE_ERROR, "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot."}, + +{SEC_ERROR_BAD_INFO_ACCESS_METHOD, "Unknown information access method in certificate extension."}, + +{SEC_ERROR_CRL_IMPORT_FAILED, "Error attempting to import a CRL."}, + diff --git a/xmlsecurity/source/xmlsec/nss/makefile.mk b/xmlsecurity/source/xmlsec/nss/makefile.mk index df5bb7131a55..227b6de88477 100644 --- a/xmlsecurity/source/xmlsec/nss/makefile.mk +++ b/xmlsecurity/source/xmlsec/nss/makefile.mk @@ -47,10 +47,12 @@ LIBTARGET=NO .IF "$(CRYPTO_ENGINE)" == "nss" -.IF "$(WITH_MOZILLA)" == "NO" +.IF "$(WITH_MOZILLA)" == "NO" || "$(ENABLE_NSS_MODULE)"!="YES" +.IF "$(SYSTEM_MOZILLA)" != "YES" @all: @echo "No mozilla -> no nss -> no libxmlsec -> no xmlsecurity/nss" .ENDIF +.ENDIF .IF "$(SYSTEM_MOZILLA)" != "YES" MOZ_INC = $(SOLARVERSION)$/$(INPATH)$/inc$(UPDMINOREXT)$/mozilla @@ -128,7 +130,9 @@ SLOFILES = \ $(SLO)$/xmlsignature_nssimpl.obj \ $(SLO)$/x509certificate_nssimpl.obj \ $(SLO)$/seinitializer_nssimpl.obj \ - $(SLO)$/xsec_nss.obj + $(SLO)$/xsec_nss.obj \ + $(SLO)$/secerror.obj + .ENDIF diff --git a/xmlsecurity/source/xmlsec/nss/secerror.cxx b/xmlsecurity/source/xmlsec/nss/secerror.cxx new file mode 100644 index 000000000000..4a9ee3622bc4 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.cxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: securityenvironment_nssimpl.cxx,v $ + * $Revision: 1.23 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "secerr.h" +#include "sslerr.h" +#include "nspr.h" +#include "certt.h" + +#include "../diagnose.hxx" + +using namespace xmlsecurity; + +struct ErrDesc { + PRErrorCode errNum; + const char * errString; +}; + + + +const ErrDesc allDesc[] = { + +#include "certerrors.h" + +}; + + + +/* Returns a UTF-8 encoded constant error string for "errNum". + * Returns NULL of errNum is unknown. + */ +const char * +getCertError(PRErrorCode errNum) +{ + static char sEmpty[] = ""; + const int numDesc = sizeof(allDesc) / sizeof(ErrDesc); + for (int i = 0; i < numDesc; i++) + { + if (allDesc[i].errNum == errNum) + return allDesc[i].errString; + } + + return sEmpty; +} + +void +printChainFailure(CERTVerifyLog *log) +{ + unsigned long errorFlags = 0; + unsigned int depth = (unsigned int)-1; + const char * specificError = NULL; + const char * issuer = NULL; + CERTVerifyLogNode *node = NULL; + + if (log->count > 0) + { + xmlsec_trace("Bad certifcation path:"); + for (node = log->head; node; node = node->next) + { + if (depth != node->depth) + { + depth = node->depth; + xmlsec_trace("Certificate: %d. %s %s:", depth, + node->cert->subjectName, + depth ? "[Certificate Authority]": ""); + } + xmlsec_trace(" ERROR %ld: %s", node->error, + getCertError(node->error)); + specificError = NULL; + issuer = NULL; + switch (node->error) + { + case SEC_ERROR_INADEQUATE_KEY_USAGE: + errorFlags = (unsigned long)node->arg; + switch (errorFlags) + { + case KU_DIGITAL_SIGNATURE: + specificError = "Certificate cannot sign."; + break; + case KU_KEY_ENCIPHERMENT: + specificError = "Certificate cannot encrypt."; + break; + case KU_KEY_CERT_SIGN: + specificError = "Certificate cannot sign other certs."; + break; + default: + specificError = "[unknown usage]."; + break; + } + case SEC_ERROR_INADEQUATE_CERT_TYPE: + errorFlags = (unsigned long)node->arg; + switch (errorFlags) + { + case NS_CERT_TYPE_SSL_CLIENT: + case NS_CERT_TYPE_SSL_SERVER: + specificError = "Certificate cannot be used for SSL."; + break; + case NS_CERT_TYPE_SSL_CA: + specificError = "Certificate cannot be used as an SSL CA."; + break; + case NS_CERT_TYPE_EMAIL: + specificError = "Certificate cannot be used for SMIME."; + break; + case NS_CERT_TYPE_EMAIL_CA: + specificError = "Certificate cannot be used as an SMIME CA."; + break; + case NS_CERT_TYPE_OBJECT_SIGNING: + specificError = "Certificate cannot be used for object signing."; + break; + case NS_CERT_TYPE_OBJECT_SIGNING_CA: + specificError = "Certificate cannot be used as an object signing CA."; + break; + default: + specificError = "[unknown usage]."; + break; + } + case SEC_ERROR_UNKNOWN_ISSUER: + specificError = "Unknown issuer:"; + issuer = node->cert->issuerName; + break; + case SEC_ERROR_UNTRUSTED_ISSUER: + specificError = "Untrusted issuer:"; + issuer = node->cert->issuerName; + break; + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + specificError = "Expired issuer certificate:"; + issuer = node->cert->issuerName; + break; + default: + break; + } + if (specificError) + xmlsec_trace("%s", specificError); + if (issuer) + xmlsec_trace("%s", issuer); + } + } +} diff --git a/xmlsecurity/source/xmlsec/nss/secerror.hxx b/xmlsecurity/source/xmlsec/nss/secerror.hxx new file mode 100644 index 000000000000..732fef5fd03e --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.hxx @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: securityenvironment_nssimpl.hxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XSECERROR_HXX_ +#define _XSECERROR_HXX_ + +const char * +getCertError(PRErrorCode errNum); + +void +printChainFailure(CERTVerifyLog *log); +#endif // _XSECERROR_HXX_ + diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx index 0f8cfb744e5d..9458424afa7c 100644 --- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -33,12 +33,13 @@ #include "nssrenam.h" #include "cert.h" #include "secerr.h" +#include "ocsp.h" #include <sal/config.h> #include "securityenvironment_nssimpl.hxx" #include "x509certificate_nssimpl.hxx" #include <rtl/uuid.h> - +#include "../diagnose.hxx" #include <sal/types.h> //For reasons that escape me, this is what xmlsec does when size_t is not 4 @@ -62,9 +63,12 @@ #include <vector> #include "boost/scoped_array.hpp" +#include "secerror.hxx" + // MM : added for password exception #include <com/sun/star/security/NoPasswordException.hpp> namespace csss = ::com::sun::star::security; +using namespace xmlsecurity; using namespace ::com::sun::star::security; using namespace com::sun::star; using namespace ::com::sun::star::uno ; @@ -80,6 +84,14 @@ extern X509Certificate_NssImpl* NssCertToXCert( CERTCertificate* cert ) ; extern X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* ) ; +struct UsageDescription +{ + SECCertificateUsage usage; + char const * const description; +}; + + + char* GetPasswordFunction( PK11SlotInfo* pSlot, PRBool bRetry, void* /*arg*/ ) { uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() ); @@ -750,7 +762,7 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert, const Sequence< Reference< csss::XCertificate > >& intermediateCerts ) throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException ) { - sal_Int32 validity = 0; + sal_Int32 validity = csss::CertificateValidity::INVALID; const X509Certificate_NssImpl* xcert ; const CERTCertificate* cert ; ::std::vector<CERTCertificate*> vecTmpNSSCertificates; @@ -759,10 +771,9 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert, throw RuntimeException() ; } - OSL_TRACE("[xmlsecurity] Start verification of certificate: %s", + xmlsec_trace("Start verification of certificate: \n %s \n", OUStringToOString( - aCert->getIssuerName(), osl_getThreadTextEncoding()).getStr()); - + aCert->getSubjectName(), osl_getThreadTextEncoding()).getStr()); xcert = reinterpret_cast<X509Certificate_NssImpl*>( sal::static_int_cast<sal_uIntPtr>(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ; @@ -770,12 +781,16 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert, throw RuntimeException() ; } + //CERT_PKIXVerifyCert does not take a db as argument. It will therefore + //internally use CERT_GetDefaultCertDB + //Make sure m_pHandler is the default DB + OSL_ASSERT(m_pHandler == CERT_GetDefaultCertDB()); + CERTCertDBHandle * certDb = m_pHandler != NULL ? m_pHandler : CERT_GetDefaultCertDB(); cert = xcert->getNssCert() ; if( cert != NULL ) { //prepare the intermediate certificates - CERTCertDBHandle * certDb = m_pHandler != NULL ? m_pHandler : CERT_GetDefaultCertDB(); for (sal_Int32 i = 0; i < intermediateCerts.getLength(); i++) { Sequence<sal_Int8> der = intermediateCerts[i]->getEncoded(); @@ -790,140 +805,172 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert, PR_TRUE /* copyDER */); if (!certTmp) { - OSL_TRACE("[xmlsecurity] Failed to add a temporary certificate: %s", + xmlsec_trace("Failed to add a temporary certificate: %s", OUStringToOString(intermediateCerts[i]->getIssuerName(), osl_getThreadTextEncoding()).getStr()); } else { - OSL_TRACE("[xmlsecurity] Added temporary certificate: %s", + xmlsec_trace("Added temporary certificate: %s", certTmp->subjectName ? certTmp->subjectName : ""); vecTmpNSSCertificates.push_back(certTmp); } } - int64 timeboundary ; SECStatus status ; - //Get the system clock time - timeboundary = PR_Now() ; - SECCertificateUsage usage = 0; - - // create log - - CERTVerifyLog realLog; - CERTVerifyLog *log; - - log = &realLog; - - - log->count = 0; - log->head = NULL; - log->tail = NULL; - log->arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); - - //CERTVerifyLog *log; - //PRArenaPool *arena; - - //arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); - //log = PORT_ArenaZNew( arena, CERTVerifyLog ); - //log->arena = arena; - validity = csss::CertificateValidity::INVALID; - - if( m_pHandler != NULL ) + CERTVerifyLog log; + log.arena = PORT_NewArena(512); + log.head = log.tail = NULL; + log.count = 0; + + CERT_EnableOCSPChecking(certDb); + CERT_DisableOCSPDefaultResponder(certDb); + CERTValOutParam cvout[5]; + CERTValInParam cvin[3]; + + cvin[0].type = cert_pi_useAIACertFetch; + cvin[0].value.scalar.b = PR_TRUE; + + PRUint64 revFlagsLeaf[2]; + PRUint64 revFlagsChain[2]; + CERTRevocationFlags rev; + rev.leafTests.number_of_defined_methods = 2; + rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf; + //the flags are defined in cert.h + //We check both leaf and chain. + //It is enough if one revocation method has fresh info, + //but at least one must have some. Otherwise validation fails. + //!!! using leaf test and CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE + // when validating a root certificate will result in "revoked". Usually + //there is no revocation information available for the root cert because + //it must be trusted anyway and it does itself issue revocation information. + //When we use the flag here and OOo shows the certification path then the root + //cert is invalid while all other can be valid. It would probably best if + //this interface method returned the whole chain. + //Otherwise we need to check if the certificate is self-signed and if it is + //then not use the flag when doing the leaf-test. + rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.leafTests.number_of_preferred_methods = 0; + rev.leafTests.preferred_methods = NULL; + rev.leafTests.cert_rev_method_independent_flags = + CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; +// | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; + + rev.chainTests.number_of_defined_methods = 2; + rev.chainTests.cert_rev_flags_per_method = revFlagsChain; + rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.chainTests.number_of_preferred_methods = 0; + rev.chainTests.preferred_methods = NULL; + rev.chainTests.cert_rev_method_independent_flags = + CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; +// | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; + + + cvin[1].type = cert_pi_revocationFlags; + cvin[1].value.pointer.revocation = &rev; + // does not work, not implemented yet in 3.12.4 +// cvin[2].type = cert_pi_keyusage; +// cvin[2].value.scalar.ui = KU_DIGITAL_SIGNATURE; + cvin[2].type = cert_pi_end; + + cvout[0].type = cert_po_trustAnchor; + cvout[0].value.pointer.cert = NULL; + cvout[1].type = cert_po_errorLog; + cvout[1].value.pointer.log = &log; + cvout[2].type = cert_po_end; + + // We check SSL server certificates, CA certificates and signing sertificates. + // + // ToDo check keyusage, looking at CERT_KeyUsageAndTypeForCertUsage ( + // mozilla/security/nss/lib/certdb/certdb.c indicates that + // certificateUsageSSLClient, certificateUsageSSLServer and certificateUsageSSLCA + // are sufficient. They cover the key usages for digital signature, key agreement + // and encipherment and certificate signature + + //never use the following usages because they are not checked properly + // certificateUsageUserCertImport + // certificateUsageVerifyCA + // certificateUsageAnyCA + // certificateUsageProtectedObjectSigner + + UsageDescription arUsages[] = { - //JL: We must not pass a particular usage in the requiredUsages argument (the 4th) because, - //then ONLY these are verified. For example, we pass - //certificateUsageSSLClient | certificateUsageSSLServer. Then checking a certificate which - // is a valid certificateUsageEmailSigner but no certificateUsageSSLClient | certificateUsageSSLServer - //will result in CertificateValidity::INVALID. - //Only if the argument "requiredUsages" has a value (other than zero) - //then the function will return SECFailure in case - //the certificate is not suitable for the provided usage. That is, in the previous - //example the function returns SECFailure. - status = CERT_VerifyCertificate( - m_pHandler, ( CERTCertificate* )cert, PR_TRUE, - (SECCertificateUsage)0, timeboundary , NULL, log, &usage); - } - else + {certificateUsageSSLClient, "certificateUsageSSLClient" }, + {certificateUsageSSLServer, "certificateUsageSSLServer" }, + {certificateUsageSSLCA, "certificateUsageSSLCA" }, + {certificateUsageEmailSigner, "certificateUsageEmailSigner"}, //only usable for end certs + {certificateUsageEmailRecipient, "certificateUsageEmailRecipient"} + }; + + int numUsages = sizeof(arUsages) / sizeof(UsageDescription); + for (int i = 0; i < numUsages; i++) { - status = CERT_VerifyCertificate( - CERT_GetDefaultCertDB(), ( CERTCertificate* )cert, - PR_TRUE, (SECCertificateUsage)0, timeboundary ,NULL, log, &usage); - } + xmlsec_trace("Testing usage %d of %d: %s (0x%x)", i + 1, + numUsages, arUsages[i].description, (int) arUsages[i].usage); + + status = CERT_PKIXVerifyCert(const_cast<CERTCertificate *>(cert), arUsages[i].usage, + cvin, cvout, NULL); + if( status == SECSuccess ) + { + xmlsec_trace("CERT_PKIXVerifyCert returned SECSuccess."); + //When an intermediate or root certificate is checked then we expect the usage + //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog + //the button "This certificate can identify websites" is checked. If for example only + //"This certificate can identify mail users" is set then the end certificate can + //be validated and the returned usage will conain certificateUsageEmailRecipient. + //But checking directly the root or intermediate certificate will fail. In the + //certificate path view the end certificate will be shown as valid but the others + //will be displayed as invalid. - if( status == SECSuccess ) - { - // JL & TKR : certificateUsageUserCertImport, - // certificateUsageVerifyCA and certificateUsageAnyCA dont check the chain - - //When an intermediate or root certificate is checked then we expect the usage - //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog - //the button "This certificate can identify websites" is checked. If for example only - //"This certificate can identify mail users" is set then the end certificate can - //be validated and the returned usage will conain certificateUsageEmailRecipient. - //But checking directly the root or intermediate certificate will fail. In the - //certificate path view the end certificate will be shown as valid but the others - //will be displayed as invalid. - - if (usage & certificateUsageEmailSigner - || usage & certificateUsageEmailRecipient - || usage & certificateUsageSSLCA - || usage & certificateUsageSSLServer - || usage & certificateUsageSSLClient - // || usage & certificateUsageUserCertImport - // || usage & certificateUsageVerifyCA - || usage & certificateUsageStatusResponder ) - // || usage & certificateUsageAnyCA ) validity = csss::CertificateValidity::VALID; + xmlsec_trace("Certificate is valid.\n"); + CERTCertificate * issuerCert = cvout[0].value.pointer.cert; + if (issuerCert) + { + xmlsec_trace("Root certificate: %s", issuerCert->subjectName); + CERT_DestroyCertificate(issuerCert); + }; + + break; + } else - validity = csss::CertificateValidity::INVALID; + { + PRIntn err = PR_GetError(); + xmlsec_trace("Error: , %d = %s", err, getCertError(err)); + /* Display validation results */ + if ( log.count > 0) + { + CERTVerifyLogNode *node = NULL; + printChainFailure(&log); + + for (node = log.head; node; node = node->next) { + if (node->cert) + CERT_DestroyCertificate(node->cert); + } + log.head = log.tail = NULL; + log.count = 0; + } + xmlsec_trace("Certificate is invalid.\n"); + } } - // always check what kind of error occured, even SECStatus says Success - //JL: When we call CERT_VerifyCertificate whit the parameter requiredUsages == 0 then all - //possible usages are checked. Then there are certainly usages for which the certificate - //is not intended. For these usages there will be NO flag set in the argument returnedUsages - // (the last arg) and there will be error codes set in the log. Therefore we cannot - //set the CertificateValidity to INVALID because there is a log entry. -// CERTVerifyLogNode *logNode = 0; - -// logNode = log->head; -// while ( logNode != NULL ) -// { -// sal_Int32 errorCode = 0; -// errorCode = logNode->error; - -// switch ( errorCode ) -// { -// // JL & TKR: Any error are treated as invalid because we cannot say that we get all occurred errors from NSS -// /* -// case ( SEC_ERROR_REVOKED_CERTIFICATE ): -// validity |= csss::CertificateValidity::REVOKED; -// break; -// case ( SEC_ERROR_EXPIRED_CERTIFICATE ): -// validity |= csss::CertificateValidity::TIME_INVALID; -// break; -// case ( SEC_ERROR_CERT_USAGES_INVALID): -// validity |= csss::CertificateValidity::INVALID; -// break; -// case ( SEC_ERROR_UNTRUSTED_ISSUER ): -// case ( SEC_ERROR_UNTRUSTED_CERT ): -// validity |= csss::CertificateValidity::UNTRUSTED; -// break; -// */ -// default: -// validity |= csss::CertificateValidity::INVALID; -// break; -// } -// logNode = logNode->next; -// } + } else { - validity = ::com::sun::star::security::CertificateValidity::INVALID ; } @@ -931,15 +978,9 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert, std::vector<CERTCertificate*>::const_iterator cert_i; for (cert_i = vecTmpNSSCertificates.begin(); cert_i != vecTmpNSSCertificates.end(); cert_i++) { - OSL_TRACE("[xmlsecurity] Destroying temporary certificate"); + xmlsec_trace("Destroying temporary certificate"); CERT_DestroyCertificate(*cert_i); } -#if OSL_DEBUG_LEVEL > 1 - if (validity == ::com::sun::star::security::CertificateValidity::VALID) - OSL_TRACE("[xmlsecurity] Certificate is valid."); - else - OSL_TRACE("[xmlsecurity] Certificate is invalid."); -#endif return validity ; } diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx index 4aad18fa2c10..127d7fa43fe6 100644 --- a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx @@ -61,6 +61,7 @@ #include <rtl/logfile.hxx> #include "seinitializer_nssimpl.hxx" +#include "../diagnose.hxx" #include "securityenvironment_nssimpl.hxx" #include <com/sun/star/mozilla/XMozillaBootstrap.hpp> @@ -76,6 +77,7 @@ namespace cssu = com::sun::star::uno; namespace cssl = com::sun::star::lang; namespace cssxc = com::sun::star::xml::crypto; +using namespace xmlsecurity; using namespace com::sun::star; using ::rtl::OUString; using ::rtl::OString; @@ -109,7 +111,7 @@ struct InitNSSInitialize bInitialized = nsscrypto_initialize(m_sProfile.getStr(), bNSSInit); if (bNSSInit) atexit(nsscrypto_finalize ); - return & bInitialized; + return & bInitialized; } }; @@ -139,7 +141,7 @@ void deleteRootsModule() { if (PK11_HasRootCerts(slot)) { - OSL_TRACE("[xmlsecurity] The root certifificates module \"%s" + xmlsec_trace("The root certifificates module \"%s" "\" is already loaded: \n%s", module->commonName, module->dllName); @@ -157,11 +159,11 @@ void deleteRootsModule() PRInt32 modType; if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType)) { - OSL_TRACE("[xmlsecurity] Deleted module \"%s\".", RootsModule->commonName); + xmlsec_trace("Deleted module \"%s\".", RootsModule->commonName); } else { - OSL_TRACE("[xmlsecurity] Failed to delete \"%s\" : \n%s", + xmlsec_trace("Failed to delete \"%s\" : \n%s", RootsModule->commonName, RootsModule->dllName); } SECMOD_DestroyModule(RootsModule); @@ -194,18 +196,36 @@ bool nsscrypto_initialize( const char* token, bool & out_nss_init ) { bool return_value = true; - OSL_TRACE("[xmlsecurity] Using profile: %s", token); + xmlsec_trace("Using profile: %s", token); PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ; - if( NSS_InitReadWrite( token ) != SECSuccess ) + //token may be an empty string + if (token != NULL && strlen(token) > 0) { - char * error = NULL; + if( NSS_InitReadWrite( token ) != SECSuccess ) + { + xmlsec_trace("Initializing NSS with profile failed."); + char * error = NULL; - PR_GetErrorText(error); - if (error) - printf("%s",error); - return false ; + PR_GetErrorText(error); + if (error) + xmlsec_trace("%s",error); + return false ; + } + } + else + { + xmlsec_trace("Initializing NSS without profile."); + if ( NSS_NoDB_Init(NULL) != SECSuccess ) + { + xmlsec_trace("Initializing NSS without profile failed."); + char * error = NULL; + PR_GetErrorText(error); + if (error) + xmlsec_trace("%s",error); + return false ; + } } out_nss_init = true; @@ -247,18 +267,18 @@ bool nsscrypto_initialize( const char* token, bool & out_nss_init ) SECMOD_DestroyModule(RootsModule); RootsModule = 0; if (found) - OSL_TRACE("[xmlsecurity] Added new root certificate module " + xmlsec_trace("Added new root certificate module " "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); else { - OSL_TRACE("[xmlsecurity] FAILED to load the new root certificate module " + xmlsec_trace("FAILED to load the new root certificate module " "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); return_value = false; } } else { - OSL_TRACE("[xmlsecurity] FAILED to add new root certifice module: " + xmlsec_trace("FAILED to add new root certifice module: " "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); return_value = false; @@ -266,7 +286,7 @@ bool nsscrypto_initialize( const char* token, bool & out_nss_init ) } else { - OSL_TRACE("[xmlsecurity] Adding new root certificate module failed."); + xmlsec_trace("Adding new root certificate module failed."); return_value = false; } #if SYSTEM_MOZILLA @@ -287,17 +307,17 @@ extern "C" void nsscrypto_finalize() if (SECSuccess == SECMOD_UnloadUserModule(RootsModule)) { - OSL_TRACE("[xmlsecurity] Unloaded module \""ROOT_CERTS"\"."); + xmlsec_trace("Unloaded module \""ROOT_CERTS"\"."); } else { - OSL_TRACE("[xmlsecurity] Failed unloadeding module \""ROOT_CERTS"\"."); + xmlsec_trace("Failed unloadeding module \""ROOT_CERTS"\"."); } SECMOD_DestroyModule(RootsModule); } else { - OSL_TRACE("[xmlsecurity] Unloading module \""ROOT_CERTS + xmlsec_trace("Unloading module \""ROOT_CERTS "\" failed because it was not found."); } PK11_LogoutAll(); @@ -312,17 +332,16 @@ bool getMozillaCurrentProfile( /* * first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER" */ - char * env = getenv("MOZILLA_CERTIFICATE_FOLDER"); - if (env) - { - profilePath = rtl::OUString::createFromAscii( env ); - RTL_LOGFILE_PRODUCT_TRACE1( "XMLSEC: Using env MOZILLA_CERTIFICATE_FOLDER: %s", rtl::OUStringToOString( profilePath, RTL_TEXTENCODING_ASCII_US ).getStr() ); - return true; - } - else - { - RTL_LOGFILE_TRACE( "getMozillaCurrentProfile: Using MozillaBootstrap..." ); - mozilla::MozillaProductType productTypes[4] = { + char * env = getenv("MOZILLA_CERTIFICATE_FOLDER"); + if (env) + { + profilePath = rtl::OUString::createFromAscii( env ); + RTL_LOGFILE_PRODUCT_TRACE1( "XMLSEC: Using env MOZILLA_CERTIFICATE_FOLDER: %s", rtl::OUStringToOString( profilePath, RTL_TEXTENCODING_ASCII_US ).getStr() ); + return true; + } + else + { + mozilla::MozillaProductType productTypes[4] = { mozilla::MozillaProductType_Thunderbird, mozilla::MozillaProductType_Mozilla, mozilla::MozillaProductType_Firefox, @@ -343,8 +362,6 @@ bool getMozillaCurrentProfile( { ::rtl::OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]); - RTL_LOGFILE_TRACE2( "getMozillaCurrentProfile: getDefaultProfile [%i] returns %s", i, rtl::OUStringToOString( profile, RTL_TEXTENCODING_ASCII_US ).getStr() ); - if (profile != NULL && profile.getLength()>0) { profilePath = xMozillaBootstrap->getProfilePath(productTypes[i],profile); @@ -401,36 +418,9 @@ cssu::Reference< cssxc::XXMLSecurityContext > SAL_CALL } - if( !sCertDir.getLength() ) - { - RTL_LOGFILE_TRACE( "XMLSEC: Error - No certificate directory!" ); - // return NULL; - } - - - /* Initialize NSPR and NSS */ - /* Replaced with new methods by AF. ---- - //PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1 ) ; - PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ; - - if (NSS_Init(sCertDir.getStr()) != SECSuccess ) - { - PK11_LogoutAll(); - return NULL; - } - ----*/ if( ! *initNSS( sCertDir.getStr() ) ) { - RTL_LOGFILE_TRACE( "XMLSEC: Error - nsscrypto_initialize() failed." ); - if ( NSS_NoDB_Init(NULL) != SECSuccess ) - { - RTL_LOGFILE_TRACE( "XMLSEC: NSS_NoDB_Init also failed, NSS Security not available!" ); - return NULL; - } - else - { - RTL_LOGFILE_TRACE( "XMLSEC: NSS_NoDB_Init works, enough for verifying signatures..." ); - } + return NULL; } pCertHandle = CERT_GetDefaultCertDB() ; diff --git a/xmlsecurity/util/makefile.mk b/xmlsecurity/util/makefile.mk index bcbf7ac5e43d..1030fbbd10c3 100644 --- a/xmlsecurity/util/makefile.mk +++ b/xmlsecurity/util/makefile.mk @@ -70,8 +70,13 @@ DEF1EXPORTFILE = xsec_fw.dxp # # The 2nd shared library # + SHL2NAME=xsec_xmlsec SHL2TARGET= $(SHL2NAME) + + +.IF "$(ENABLE_NSS_MODULE)"=="YES" || "$(SYSTEM_MOZILLA)" == "YES" + SHL2LIBS= \ $(SLB)$/xs_comm.lib @@ -83,6 +88,9 @@ SHL2LIBS += \ $(SLB)$/xs_nss.lib .ENDIF +.ENDIF + + SHL2STDLIBS += \ $(SALLIB) \ $(CPPULIB) \ |