diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /chart2/source/model | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/source/model')
82 files changed, 19340 insertions, 0 deletions
diff --git a/chart2/source/model/filter/XMLFilter.cxx b/chart2/source/model/filter/XMLFilter.cxx new file mode 100644 index 000000000..a31f1d9f6 --- /dev/null +++ b/chart2/source/model/filter/XMLFilter.cxx @@ -0,0 +1,773 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <XMLFilter.hxx> +#include <MediaDescriptorHelper.hxx> + +#include <officecfg/Office/Common.hxx> +#include <svtools/sfxecode.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/documentconstants.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/sequence.hxx> + +#include <osl/diagnose.h> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/StorageFactory.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XFastParser.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/document/GraphicStorageHandler.hpp> +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::osl::MutexGuard; + +namespace +{ +constexpr OUStringLiteral sXML_metaStreamName = u"meta.xml"; +constexpr OUStringLiteral sXML_styleStreamName = u"styles.xml"; +constexpr OUStringLiteral sXML_contentStreamName = u"content.xml"; + + +uno::Reference< embed::XStorage > lcl_getWriteStorage( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const uno::Reference< uno::XComponentContext >& xContext,const OUString& _sMediaType) +{ + uno::Reference< embed::XStorage > xStorage; + try + { + apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor ); + if( aMDHelper.ISSET_Storage ) + { + xStorage = aMDHelper.Storage; + } + else + { + Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) ); + + std::vector< beans::PropertyValue > aPropertiesForStorage; + + for( sal_Int32 i=rMediaDescriptor.getLength(); i--; ) + { + // properties understood by storage factory + // (see package/source/xstor/xfactory.cxx for details) + if ( rMediaDescriptor[i].Name == "InteractionHandler" || rMediaDescriptor[i].Name == "Password" || rMediaDescriptor[i].Name == "RepairPackage" ) + { + aPropertiesForStorage.push_back( rMediaDescriptor[i] ); + } + } + + if( aMDHelper.ISSET_Storage ) + xStorage.set( aMDHelper.Storage ); + else + { + Sequence< uno::Any > aStorageArgs{ + aMDHelper.ISSET_OutputStream ? uno::Any(aMDHelper.OutputStream) + : uno::Any(aMDHelper.URL), + uno::Any(embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE), + uno::Any(comphelper::containerToSequence( aPropertiesForStorage )) + }; + + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + } + + // set correct media type at storage + uno::Reference<beans::XPropertySet> xProp(xStorage,uno::UNO_QUERY); + OUString aMediaType; + if ( ! xProp.is() || + ! ( xProp->getPropertyValue( "MediaType") >>= aMediaType ) || + ( aMediaType.isEmpty() )) + { + xProp->setPropertyValue( "MediaType", uno::Any( _sMediaType )); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xStorage; +} + +uno::Reference< embed::XStorage > lcl_getReadStorage( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const uno::Reference< uno::XComponentContext >& xContext) +{ + uno::Reference< embed::XStorage > xStorage; + + try + { + apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor ); + if( aMDHelper.ISSET_Storage ) + { + xStorage = aMDHelper.Storage; + } + else + { + // get XStream from MediaDescriptor + uno::Reference< io::XInputStream > xStream; + std::vector< beans::PropertyValue > aPropertiesForStorage; + for( sal_Int32 i=rMediaDescriptor.getLength(); i--; ) + { + if( rMediaDescriptor[i].Name == "InputStream" ) + xStream.set( rMediaDescriptor[i].Value, uno::UNO_QUERY ); + + // properties understood by storage factory + // (see package/source/xstor/xfactory.cxx for details) + if ( rMediaDescriptor[i].Name == "InteractionHandler" || rMediaDescriptor[i].Name == "Password" || rMediaDescriptor[i].Name == "RepairPackage" ) + { + aPropertiesForStorage.push_back( rMediaDescriptor[i] ); + } + } + OSL_ENSURE( xStream.is(), "No Stream" ); + if( ! xStream.is()) + return xStorage; + + // convert XInputStream to XStorage via the storage factory + Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) ); + Sequence< uno::Any > aStorageArgs{ + uno::Any(xStream), + uno::Any(embed::ElementModes::READ | embed::ElementModes::NOCREATE), + uno::Any(comphelper::containerToSequence( aPropertiesForStorage )) + }; + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW ); + } + + OSL_ENSURE( xStorage.is(), "No Storage" ); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xStorage; +} + +} // anonymous namespace + +namespace chart +{ + +XMLFilter::XMLFilter( Reference< uno::XComponentContext > const & xContext ) : + m_xContext( xContext ), + m_bCancelOperation( false ) +{} + +XMLFilter::~XMLFilter() +{} + +// ____ XFilter ____ +sal_Bool SAL_CALL XMLFilter::filter( + const Sequence< beans::PropertyValue >& aDescriptor ) +{ + bool bResult = false; + + MutexGuard aGuard( m_aMutex ); + + // ignore cancel flag at start of function + // note: is currently ignored during import/export + if( m_bCancelOperation ) + m_bCancelOperation = false; + + if( m_xSourceDoc.is()) + { + OSL_ENSURE( ! m_xTargetDoc.is(), "source doc is set -> target document should not be set" ); + if( impl_Export( m_xSourceDoc, + aDescriptor ) == ERRCODE_NONE ) + { + m_xSourceDoc = nullptr; + bResult = true; + } + } + else if( m_xTargetDoc.is()) + { + if( impl_Import( m_xTargetDoc, + aDescriptor ) == ERRCODE_NONE ) + { + m_xTargetDoc = nullptr; + bResult = true; + } + } + else + { + OSL_FAIL( "filter() called with no document set" ); + } + + return bResult; +} + +void SAL_CALL XMLFilter::cancel() +{ + // if mutex is locked set "cancel state" + // note: is currently ignored in filter-method + if( ! m_aMutex.tryToAcquire()) + { + m_bCancelOperation = true; + } +} + +// ____ XImporter ____ +void SAL_CALL XMLFilter::setTargetDocument( + const Reference< lang::XComponent >& Document ) +{ + MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( ! m_xSourceDoc.is(), "Setting target doc while source doc is set" ); + + m_xTargetDoc = Document; +} + +// ____ XExporter ____ +void SAL_CALL XMLFilter::setSourceDocument( + const Reference< lang::XComponent >& Document ) +{ + MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( ! m_xTargetDoc.is(), "Setting source doc while target doc is set" ); + + m_xSourceDoc = Document; +} + +ErrCode XMLFilter::impl_Import( + const Reference< lang::XComponent > & xDocumentComp, + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + ErrCode nWarning = ERRCODE_NONE; + + OSL_ENSURE( xDocumentComp.is(), "Import: No Model" ); + OSL_ENSURE( m_xContext.is(), "Import: No ComponentContext" ); + + if( ! (xDocumentComp.is() && + m_xContext.is())) + return nWarning; + + try + { + Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW ); + if( ! xServInfo->supportsService( "com.sun.star.chart2.ChartDocument")) + { + OSL_FAIL( "Import: No ChartDocument" ); + return ERRCODE_SFX_GENERAL; + } + + Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager()); + OSL_ENSURE( xFactory.is(), "Import: No Factory" ); + if( ! xFactory.is()) + return ERRCODE_SFX_GENERAL; + + bool bOasis = true; + isOasisFormat( rMediaDescriptor, bOasis ); + Reference< embed::XStorage > xStorage( lcl_getReadStorage( rMediaDescriptor, m_xContext)); + if( ! xStorage.is()) + return ERRCODE_SFX_GENERAL; + + uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler; + uno::Reference<lang::XMultiServiceFactory> xServiceFactory(xFactory, uno::UNO_QUERY); + if (xServiceFactory.is()) + { + uno::Sequence<uno::Any> aArgs{ uno::Any(xStorage) }; + xGraphicStorageHandler.set( + xServiceFactory->createInstanceWithArguments( + "com.sun.star.comp.Svx.GraphicImportHelper", aArgs), uno::UNO_QUERY); + } + + // create XPropertySet with extra information for the filter + /** property map for import info set */ + static comphelper::PropertyMapEntry const aImportInfoMap[] = + { + // necessary properties for XML progress bar at load time + { OUString("ProgressRange"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("ProgressMax"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("ProgressCurrent"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BaseURI"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BuildId"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + }; + uno::Reference< beans::XPropertySet > xImportInfo( + comphelper::GenericPropertySet_CreateInstance( + new comphelper::PropertySetInfo( aImportInfoMap ) ) ); + + // Set base URI and Hierarchical Name + OUString aHierarchName, aBaseUri; + // why retrieve this from the model when it's available as rMediaDescriptor? + uno::Reference<frame::XModel> const xModel(m_xTargetDoc, uno::UNO_QUERY); + if( xModel.is() ) + { + const uno::Sequence< beans::PropertyValue > aModProps = xModel->getArgs(); + for( beans::PropertyValue const & prop : aModProps ) + { + if( prop.Name == "HierarchicalDocumentName" ) + { + // Actually this argument only has meaning for embedded documents + prop.Value >>= aHierarchName; + } + else if( prop.Name == "DocumentBaseURL" ) + { + prop.Value >>= aBaseUri; + } + } + } + + // needed for relative URLs, but in clipboard copy/paste there may be none + SAL_INFO_IF(aBaseUri.isEmpty(), "chart2", "chart::XMLFilter: no base URL"); + if( !aBaseUri.isEmpty() ) + xImportInfo->setPropertyValue( "BaseURI", uno::Any( aBaseUri ) ); + + if( !aHierarchName.isEmpty() ) + xImportInfo->setPropertyValue( "StreamRelPath", uno::Any( aHierarchName ) ); + + // import meta information + if( bOasis ) + nWarning = impl_ImportStream( + sXML_metaStreamName, + "com.sun.star.comp.Chart.XMLOasisMetaImporter", + xStorage, xFactory, xGraphicStorageHandler, xImportInfo ); + + // import styles + ErrCode nTmpErr = impl_ImportStream( + sXML_styleStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisStylesImporter") + : OUString("com.sun.star.comp.Chart.XMLStylesImporter"), + xStorage, xFactory, xGraphicStorageHandler, xImportInfo ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nTmpErr; + + // import content + ErrCode nContentWarning = impl_ImportStream( + sXML_contentStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisContentImporter") + : OUString("com.sun.star.comp.Chart.XMLContentImporter"), + xStorage, xFactory, xGraphicStorageHandler, xImportInfo ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nContentWarning; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + + // something went awry + nWarning = ERRCODE_SFX_GENERAL; + } + + return nWarning; +} + +ErrCode XMLFilter::impl_ImportStream( + const OUString & rStreamName, + const OUString & rServiceName, + const Reference< embed::XStorage > & xStorage, + const Reference< lang::XMultiComponentFactory > & xFactory, + const Reference< document::XGraphicStorageHandler > & xGraphicStorageHandler, + uno::Reference< beans::XPropertySet > const & xImportInfo ) +{ + ErrCode nWarning = ERRCODE_SFX_GENERAL; + + if( ! (xStorage.is() && + xStorage->hasByName( rStreamName ))) + return ERRCODE_NONE; + + if( xImportInfo.is() ) + xImportInfo->setPropertyValue( "StreamName", uno::Any( rStreamName ) ); + + if( xStorage.is() && + xStorage->isStreamElement( rStreamName ) ) + { + try + { + auto xInputStream = + xStorage->openStreamElement( + rStreamName, + embed::ElementModes::READ | embed::ElementModes::NOCREATE ); + + // todo: encryption + + if( xInputStream.is()) + { + sal_Int32 nArgs = 0; + if( xGraphicStorageHandler.is()) + nArgs++; + if( xImportInfo.is()) + nArgs++; + + uno::Sequence< uno::Any > aFilterCompArgs( nArgs ); + auto aFilterCompArgsRange = asNonConstRange(aFilterCompArgs); + + nArgs = 0; + if( xGraphicStorageHandler.is()) + aFilterCompArgsRange[nArgs++] <<= xGraphicStorageHandler; + if( xImportInfo.is()) + aFilterCompArgsRange[ nArgs++ ] <<= xImportInfo; + + // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler + Reference< XInterface > xFilter = + xFactory->createInstanceWithArgumentsAndContext( rServiceName, aFilterCompArgs, m_xContext ); + assert(xFilter); + Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY ); + assert(xImporter); + xImporter->setTargetDocument( Reference< lang::XComponent >( m_xTargetDoc, uno::UNO_SET_THROW )); + + if ( !m_sDocumentHandler.isEmpty() ) + { + try + { + uno::Sequence< uno::Any > aArgs{ + uno::Any(beans::NamedValue("DocumentHandler", uno::Any(xFilter))), + uno::Any(beans::NamedValue("Model", uno::Any(m_xTargetDoc))) + }; + + xFilter = xFactory->createInstanceWithArgumentsAndContext(m_sDocumentHandler,aArgs,m_xContext); + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", "failed to instantiate " << m_sDocumentHandler); + } + } + xml::sax::InputSource aParserInput; + aParserInput.aInputStream.set(xInputStream, uno::UNO_QUERY_THROW); + + // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler + Reference< xml::sax::XFastParser > xFastParser(xFilter, uno::UNO_QUERY); + if (xFastParser.is()) + xFastParser->parseStream(aParserInput); + else + { + Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(m_xContext); + xParser->setDocumentHandler( uno::Reference<xml::sax::XDocumentHandler>(xFilter, uno::UNO_QUERY_THROW) ); + xParser->parseStream(aParserInput); + } + } + + // load was successful + nWarning = ERRCODE_NONE; + } + catch (const xml::sax::SAXParseException&) + { + // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD + } + catch (const xml::sax::SAXException&) + { + // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD + } + catch (const packages::zip::ZipIOException&) + { + nWarning = ERRCODE_IO_BROKENPACKAGE; + } + catch (const io::IOException&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return nWarning; +} + +ErrCode XMLFilter::impl_Export( + const Reference< lang::XComponent > & xDocumentComp, + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + m_aMediaDescriptor = rMediaDescriptor; + //save + + ErrCode nWarning = ERRCODE_NONE; + + OSL_ENSURE( xDocumentComp.is(), "Export: No Model" ); + OSL_ENSURE( m_xContext.is(), "Export: No ComponentContext" ); + + if( !xDocumentComp.is() || !m_xContext.is() ) + return nWarning; + + try + { + Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW ); + if( ! xServInfo->supportsService( "com.sun.star.chart2.ChartDocument")) + { + OSL_FAIL( "Export: No ChartDocument" ); + return ERRCODE_SFX_GENERAL; + } + + Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager()); + OSL_ENSURE( xFactory.is(), "Export: No Factory" ); + if( ! xFactory.is()) + return ERRCODE_SFX_GENERAL; + uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_xContext->getServiceManager(), uno::UNO_QUERY); + if( ! xServiceFactory.is()) + return ERRCODE_SFX_GENERAL; + + uno::Reference< xml::sax::XWriter > xSaxWriter = xml::sax::Writer::create(m_xContext); + + bool bOasis = true; + isOasisFormat( rMediaDescriptor, bOasis ); + + uno::Reference< embed::XStorage > xStorage( lcl_getWriteStorage( rMediaDescriptor, m_xContext, getMediaType(bOasis) ) ); + OSL_ENSURE( xStorage.is(), "No Storage" ); + if( ! xStorage.is()) + return ERRCODE_SFX_GENERAL; + + uno::Reference< xml::sax::XDocumentHandler> xDocHandler = xSaxWriter; + + if ( !m_sDocumentHandler.isEmpty() ) + { + try + { + uno::Sequence< uno::Any > aArgs{ + uno::Any(beans::NamedValue("DocumentHandler", uno::Any(xDocHandler))), + uno::Any(beans::NamedValue("Model", uno::Any(xDocumentComp))) + }; + + xDocHandler.set(xServiceFactory->createInstanceWithArguments(m_sDocumentHandler,aArgs), uno::UNO_QUERY ); + xSaxWriter.set(xDocHandler,uno::UNO_QUERY); + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "chart2", "Exception caught!"); + } + } + + Reference<document::XGraphicStorageHandler> xGraphicStorageHandler; + xGraphicStorageHandler.set(document::GraphicStorageHandler::createWithStorage(m_xContext, xStorage)); + + // property map for export info set + static comphelper::PropertyMapEntry const aExportInfoMap[] = + { + { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("ExportTableNumberList"), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + }; + + uno::Reference< beans::XPropertySet > xInfoSet = + comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ); + + bool bUsePrettyPrinting( officecfg::Office::Common::Save::Document::PrettyPrinting::get() ); + xInfoSet->setPropertyValue( "UsePrettyPrinting", uno::Any( bUsePrettyPrinting ) ); + if( ! bOasis ) + xInfoSet->setPropertyValue( "ExportTableNumberList", uno::Any( true )); + + sal_Int32 nArgs = 2; + if( xGraphicStorageHandler.is()) + nArgs++; + + uno::Sequence< uno::Any > aFilterProperties( nArgs ); + { + auto pFilterProperties = aFilterProperties.getArray(); + nArgs = 0; + pFilterProperties[ nArgs++ ] <<= xInfoSet; + pFilterProperties[ nArgs++ ] <<= xDocHandler; + if( xGraphicStorageHandler.is()) + pFilterProperties[ nArgs++ ] <<= xGraphicStorageHandler; + } + + // export meta information + if( bOasis ) + nWarning = impl_ExportStream( + sXML_metaStreamName, + "com.sun.star.comp.Chart.XMLOasisMetaExporter", + xStorage, xSaxWriter, xServiceFactory, aFilterProperties ); + + // export styles + ErrCode nTmp = impl_ExportStream( + sXML_styleStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisStylesExporter") + : OUString("com.sun.star.comp.Chart.XMLStylesExporter"), // soffice 6/7 + xStorage, xSaxWriter, xServiceFactory, aFilterProperties ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nTmp; + + // export content + ErrCode nContentWarning = impl_ExportStream( + sXML_contentStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisContentExporter") + : OUString("com.sun.star.comp.Chart.XMLContentExporter"), + xStorage, xSaxWriter, xServiceFactory, aFilterProperties ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nContentWarning; + + Reference< lang::XComponent > xComp(xGraphicStorageHandler, uno::UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + + uno::Reference<embed::XTransactedObject> xTransact( xStorage ,uno::UNO_QUERY); + if ( xTransact.is() ) + xTransact->commit(); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + + // something went awry + nWarning = ERRCODE_SFX_GENERAL; + } + + return nWarning; +} + +ErrCode XMLFilter::impl_ExportStream( + const OUString & rStreamName, + const OUString & rServiceName, + const Reference< embed::XStorage > & xStorage, + const uno::Reference< xml::sax::XWriter >& xActiveDataSource, + const Reference< lang::XMultiServiceFactory >& xServiceFactory, + const Sequence< uno::Any > & rFilterProperties ) +{ + try + { + if( !xServiceFactory.is() ) + return ERRCODE_SFX_GENERAL; + if( !xStorage.is() ) + return ERRCODE_SFX_GENERAL; + if ( !xActiveDataSource.is() ) + return ERRCODE_SFX_GENERAL; + + uno::Reference< io::XStream > xStream( xStorage->openStreamElement( + rStreamName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ) ); + if ( !xStream.is() ) + return ERRCODE_SFX_GENERAL; + uno::Reference< io::XOutputStream > xOutputStream( xStream->getOutputStream() ); + if ( !xOutputStream.is() ) + return ERRCODE_SFX_GENERAL; + + uno::Reference< beans::XPropertySet > xStreamProp( xOutputStream, uno::UNO_QUERY ); + if(xStreamProp.is()) try + { + xStreamProp->setPropertyValue( "MediaType", uno::Any( OUString("text/xml") ) ); + xStreamProp->setPropertyValue( "Compressed", uno::Any( true ) );//@todo? + xStreamProp->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::Any( true ) ); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + xActiveDataSource->setOutputStream(xOutputStream); + + // set Base URL + { + uno::Reference< beans::XPropertySet > xInfoSet; + if( rFilterProperties.hasElements() ) + rFilterProperties.getConstArray()[0] >>= xInfoSet; + OSL_ENSURE( xInfoSet.is(), "missing infoset for export" ); + if( xInfoSet.is() ) + xInfoSet->setPropertyValue( "StreamName", uno::Any( rStreamName ) ); + } + + Reference< XExporter > xExporter( xServiceFactory->createInstanceWithArguments( + rServiceName, rFilterProperties ), uno::UNO_QUERY); + if ( !xExporter.is() ) + return ERRCODE_SFX_GENERAL; + + xExporter->setSourceDocument( m_xSourceDoc ); + + uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY ); + if ( !xFilter.is() ) + return ERRCODE_SFX_GENERAL; + + xFilter->filter(m_aMediaDescriptor); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return ERRCODE_NONE; +} + +void XMLFilter::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS ) +{ + apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor ); + if( aMDHelper.ISSET_FilterName ) + rOutOASIS = aMDHelper.FilterName == "chart8"; +} +OUString XMLFilter::getMediaType(bool _bOasis) +{ + return _bOasis ? OUString(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII) : OUString(MIMETYPE_VND_SUN_XML_CHART_ASCII); +} + +OUString SAL_CALL XMLFilter::getImplementationName() +{ + return "com.sun.star.comp.chart2.XMLFilter"; +} + +sal_Bool SAL_CALL XMLFilter::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL XMLFilter::getSupportedServiceNames() +{ + return { + "com.sun.star.document.ImportFilter", + "com.sun.star.document.ExportFilter" + }; + // todo: services are incomplete. Missing: + // XInitialization, XNamed +} + +void XMLReportFilterHelper::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS ) +{ + apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor ); + if( aMDHelper.ISSET_FilterName ) + rOutOASIS = aMDHelper.FilterName == "StarOffice XML (Base) Report Chart"; +} +OUString XMLReportFilterHelper::getMediaType(bool ) +{ + return MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_XMLFilter_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::XMLFilter(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_report_XMLFilter_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::XMLReportFilterHelper(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/CartesianCoordinateSystem.hxx b/chart2/source/model/inc/CartesianCoordinateSystem.hxx new file mode 100644 index 000000000..d84f53bf5 --- /dev/null +++ b/chart2/source/model/inc/CartesianCoordinateSystem.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <BaseCoordinateSystem.hxx> + +namespace chart +{ +class CartesianCoordinateSystem : public BaseCoordinateSystem +{ +public: + explicit CartesianCoordinateSystem(sal_Int32 nDimensionCount); + explicit CartesianCoordinateSystem(const CartesianCoordinateSystem& rSource); + virtual ~CartesianCoordinateSystem() override; + + // ____ XCoordinateSystem ____ + virtual OUString SAL_CALL getCoordinateSystemType() override; + virtual OUString SAL_CALL getViewServiceName() override; + + // ____ XCloneable ____ + virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override; + + // ____ XServiceInfo ____ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +class CartesianCoordinateSystem2d final : public CartesianCoordinateSystem +{ +public: + explicit CartesianCoordinateSystem2d(); + virtual ~CartesianCoordinateSystem2d() override; + + // ____ XServiceInfo ____ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +class CartesianCoordinateSystem3d final : public CartesianCoordinateSystem +{ +public: + explicit CartesianCoordinateSystem3d(); + virtual ~CartesianCoordinateSystem3d() override; + + // ____ XServiceInfo ____ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/PolarCoordinateSystem.hxx b/chart2/source/model/inc/PolarCoordinateSystem.hxx new file mode 100644 index 000000000..43eaefa5b --- /dev/null +++ b/chart2/source/model/inc/PolarCoordinateSystem.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <BaseCoordinateSystem.hxx> + +namespace chart +{ +class PolarCoordinateSystem : public BaseCoordinateSystem +{ +public: + explicit PolarCoordinateSystem(sal_Int32 nDimensionCount); + explicit PolarCoordinateSystem(const PolarCoordinateSystem& rSource); + virtual ~PolarCoordinateSystem() override; + + // ____ XCoordinateSystem ____ + virtual OUString SAL_CALL getCoordinateSystemType() override; + virtual OUString SAL_CALL getViewServiceName() override; + + // ____ XCloneable ____ + virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override; + + // ____ XServiceInfo ____ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +class PolarCoordinateSystem2d final : public PolarCoordinateSystem +{ +public: + explicit PolarCoordinateSystem2d(); + virtual ~PolarCoordinateSystem2d() override; + + // ____ XServiceInfo ____ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +class PolarCoordinateSystem3d final : public PolarCoordinateSystem +{ +public: + explicit PolarCoordinateSystem3d(); + virtual ~PolarCoordinateSystem3d() override; + + // ____ XServiceInfo ____ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/StockBar.hxx b/chart2/source/model/inc/StockBar.hxx new file mode 100644 index 000000000..dbc357ea4 --- /dev/null +++ b/chart2/source/model/inc/StockBar.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <com/sun/star/util/XCloneable.hpp> +#include <OPropertySet.hxx> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/uno3.hxx> +#include <ModifyListenerHelper.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + StockBar_Base; +} + +class StockBar final : + public cppu::BaseMutex, + public impl::StockBar_Base, + public ::property::OPropertySet +{ +public: + explicit StockBar( bool bRisingCourse ); + virtual ~StockBar() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + +private: + explicit StockBar( const StockBar & rOther ); + + // ____ XTypeProvider ____ + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const css::lang::EventObject& aEvent ) override; + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const css::lang::EventObject& Source ) override; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/XMLFilter.hxx b/chart2/source/model/inc/XMLFilter.hxx new file mode 100644 index 000000000..332bf62ca --- /dev/null +++ b/chart2/source/model/inc/XMLFilter.hxx @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <osl/mutex.hxx> +#include <vcl/errcode.hxx> + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::xml::sax { class XWriter; } +namespace com::sun::star::lang { class XMultiComponentFactory; } + +namespace com::sun::star { + namespace embed { + class XStorage; + } + namespace xml::sax { + class XFastParser; + } + namespace document { + class XGraphicStorageHandler; + } +} + +namespace chart +{ + +class XMLFilter : public + ::cppu::WeakImplHelper< + css::document::XFilter, + css::document::XExporter, + css::document::XImporter, + css::lang::XServiceInfo > +{ +public: + explicit XMLFilter( css::uno::Reference< css::uno::XComponentContext > const & xContext ); + virtual ~XMLFilter() override; + + /// XServiceInfo declarations + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +protected: + // ____ XFilter ____ + virtual sal_Bool SAL_CALL filter( + const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor ) override; + virtual void SAL_CALL cancel() override; + + // ____ XImporter ____ + virtual void SAL_CALL setTargetDocument( + const css::uno::Reference< css::lang::XComponent >& Document ) override; + + // ____ XExporter ____ + virtual void SAL_CALL setSourceDocument( + const css::uno::Reference< css::lang::XComponent >& Document ) override; + + void setDocumentHandler(const OUString& _sDocumentHandler) { m_sDocumentHandler = _sDocumentHandler; } + + virtual OUString getMediaType(bool _bOasis); + + /** fills the oasis flag only when a filtername was set + * + * \param _rMediaDescriptor + * \param _rOutOASIS + */ + virtual void isOasisFormat(const css::uno::Sequence< css::beans::PropertyValue >& _rMediaDescriptor, bool & _rOutOASIS ); + +private: + // methods + + /// @return a warning code, or 0 for successful operation + ErrCode impl_Import( const css::uno::Reference< css::lang::XComponent > & xDocumentComp, + const css::uno::Sequence< css::beans::PropertyValue > & aMediaDescriptor ); + /// @return a warning code, or 0 for successful operation + ErrCode impl_ImportStream( + const OUString & rStreamName, + const OUString & rServiceName, + const css::uno::Reference< css::embed::XStorage > & xStorage, + const css::uno::Reference< css::lang::XMultiComponentFactory > & xFactory, + const css::uno::Reference<css::document::XGraphicStorageHandler> & xGraphicStorageHandler, + css::uno::Reference< css::beans::XPropertySet > const & xPropSet ); + + /// @return a warning code, or 0 for successful operation + ErrCode impl_Export( const css::uno::Reference< css::lang::XComponent > & xDocumentComp, + const css::uno::Sequence< css::beans::PropertyValue > & aMediaDescriptor ); + /// @return a warning code, or 0 for successful operation + ErrCode impl_ExportStream( + const OUString & rStreamName, + const OUString & rServiceName, + const css::uno::Reference< css::embed::XStorage > & xStorage, + const css::uno::Reference< css::xml::sax::XWriter >& xActiveDataSource, + const css::uno::Reference< css::lang::XMultiServiceFactory > & xFactory, + const css::uno::Sequence< css::uno::Any > & rFilterProperties ); + + // members + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::lang::XComponent > m_xTargetDoc; + css::uno::Reference< css::lang::XComponent > m_xSourceDoc; + + css::uno::Sequence<css::beans::PropertyValue> m_aMediaDescriptor; + + OUString m_sDocumentHandler; // when set it will be set as doc handler + + volatile bool m_bCancelOperation; + ::osl::Mutex m_aMutex; +}; + +class XMLReportFilterHelper final : public XMLFilter +{ + virtual void isOasisFormat(const css::uno::Sequence< css::beans::PropertyValue >& _rMediaDescriptor, + bool & _rOutOASIS ) override; +public: + explicit XMLReportFilterHelper( css::uno::Reference< css::uno::XComponentContext > const & _xContext ) + :XMLFilter(_xContext) + {} +protected: + virtual OUString SAL_CALL + getImplementationName() override + { + return "com.sun.star.comp.chart2.report.XMLFilter"; + } + // ____ XImporter ____ + virtual void SAL_CALL setTargetDocument( + const css::uno::Reference< css::lang::XComponent >& Document ) override + { + setDocumentHandler( "com.sun.star.comp.report.ImportDocumentHandler" ); + XMLFilter::setTargetDocument(Document); + } + + // ____ XExporter ____ + virtual void SAL_CALL setSourceDocument( + const css::uno::Reference< css::lang::XComponent >& Document ) override + { + setDocumentHandler( "com.sun.star.comp.report.ExportDocumentHandler" ); + XMLFilter::setSourceDocument(Document); + } + + virtual OUString getMediaType(bool _bOasis) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Axis.cxx b/chart2/source/model/main/Axis.cxx new file mode 100644 index 000000000..9507f3719 --- /dev/null +++ b/chart2/source/model/main/Axis.cxx @@ -0,0 +1,615 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <Axis.hxx> +#include "GridProperties.hxx" +#include <CharacterProperties.hxx> +#include <LinePropertiesHelper.hxx> +#include <UserDefinedProperties.hxx> +#include <PropertyHelper.hxx> +#include <CloneHelper.hxx> +#include <AxisHelper.hxx> +#include <EventListenerHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <unonames.hxx> + +#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp> +#include <com/sun/star/chart/ChartAxisLabelPosition.hpp> +#include <com/sun/star/chart/ChartAxisMarkPosition.hpp> +#include <com/sun/star/chart/ChartAxisPosition.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/ref.hxx> + +#include <vector> +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans::PropertyAttribute; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; + +namespace +{ + +enum +{ + PROP_AXIS_SHOW, + PROP_AXIS_CROSSOVER_POSITION, + PROP_AXIS_CROSSOVER_VALUE, + PROP_AXIS_DISPLAY_LABELS, + PROP_AXIS_NUMBERFORMAT, + PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, + PROP_AXIS_LABEL_POSITION, + PROP_AXIS_TEXT_ROTATION, + PROP_AXIS_TEXT_BREAK, + PROP_AXIS_TEXT_OVERLAP, + PROP_AXIS_TEXT_STACKED, + PROP_AXIS_TEXT_ARRANGE_ORDER, + PROP_AXIS_REFERENCE_DIAGRAM_SIZE, + + PROP_AXIS_MAJOR_TICKMARKS, + PROP_AXIS_MINOR_TICKMARKS, + PROP_AXIS_MARK_POSITION, + + PROP_AXIS_DISPLAY_UNITS, + PROP_AXIS_BUILTINUNIT, + + PROP_AXIS_TRY_STAGGERING_FIRST, + PROP_AXIS_MAJOR_ORIGIN +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "Show", + PROP_AXIS_SHOW, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CrossoverPosition", + PROP_AXIS_CROSSOVER_POSITION, + cppu::UnoType<css::chart::ChartAxisPosition>::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CrossoverValue", + PROP_AXIS_CROSSOVER_VALUE, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "DisplayLabels", + PROP_AXIS_DISPLAY_LABELS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_AXIS_NUMBERFORMAT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT, + PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LabelPosition", + PROP_AXIS_LABEL_POSITION, + cppu::UnoType<css::chart::ChartAxisLabelPosition>::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextRotation", + PROP_AXIS_TEXT_ROTATION, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextBreak", + PROP_AXIS_TEXT_BREAK, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextOverlap", + PROP_AXIS_TEXT_OVERLAP, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "StackCharacters", + PROP_AXIS_TEXT_STACKED, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ArrangeOrder", + PROP_AXIS_TEXT_ARRANGE_ORDER, + cppu::UnoType<css::chart::ChartAxisArrangeOrderType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_AXIS_REFERENCE_DIAGRAM_SIZE, + cppu::UnoType<awt::Size>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "MajorTickmarks", + PROP_AXIS_MAJOR_TICKMARKS, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MinorTickmarks", + PROP_AXIS_MINOR_TICKMARKS, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MarkPosition", + PROP_AXIS_MARK_POSITION, + cppu::UnoType<css::chart::ChartAxisMarkPosition>::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + //Properties for display units: + rOutProperties.emplace_back( "DisplayUnits", + PROP_AXIS_DISPLAY_UNITS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //Properties for labels: + rOutProperties.emplace_back( "BuiltInUnit", + PROP_AXIS_BUILTINUNIT, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // Compatibility option: starting from LibreOffice 5.1 the rotated + // layout is preferred to staggering for axis labels. + rOutProperties.emplace_back( "TryStaggeringFirst", + PROP_AXIS_TRY_STAGGERING_FIRST, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MajorOrigin", + PROP_AXIS_MAJOR_ORIGIN, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + +} + +struct StaticAxisDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::CharacterProperties::AddDefaultsToMap( rOutMap ); + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_SHOW, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_CROSSOVER_POSITION, css::chart::ChartAxisPosition_ZERO ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_DISPLAY_LABELS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_LABEL_POSITION, css::chart::ChartAxisLabelPosition_NEAR_AXIS ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_AXIS_TEXT_ROTATION, 0.0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_BREAK, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_OVERLAP, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_STACKED, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_ARRANGE_ORDER, css::chart::ChartAxisArrangeOrderType_AUTO ); + + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_AXIS_MAJOR_TICKMARKS, 2 /* CHAXIS_MARK_OUTER */ ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_AXIS_MINOR_TICKMARKS, 0 /* CHAXIS_MARK_NONE */ ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_MARK_POSITION, css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_DISPLAY_UNITS, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TRY_STAGGERING_FIRST, false ); + } +}; + +struct StaticAxisDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticAxisDefaults_Initializer > +{ +}; + +struct StaticAxisInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticAxisInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticAxisInfoHelper_Initializer > +{ +}; + +struct StaticAxisInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticAxisInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticAxisInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticAxisInfo_Initializer > +{ +}; + +typedef uno::Reference< beans::XPropertySet > lcl_tSubGridType; + +void lcl_CloneSubGrids( + const uno::Sequence< lcl_tSubGridType > & rSource, uno::Sequence< lcl_tSubGridType > & rDestination ) +{ + rDestination.realloc( rSource.getLength()); + lcl_tSubGridType * pDestBegin = rDestination.getArray(); + lcl_tSubGridType * pDestEnd = pDestBegin + rDestination.getLength(); + lcl_tSubGridType * pDestIt = pDestBegin; + + for( Reference< beans::XPropertySet > const & i : rSource ) + { + Reference< beans::XPropertySet > xSubGrid( i ); + if( xSubGrid.is()) + { + Reference< util::XCloneable > xCloneable( xSubGrid, uno::UNO_QUERY ); + if( xCloneable.is()) + xSubGrid.set( xCloneable->createClone(), uno::UNO_QUERY ); + } + + (*pDestIt) = xSubGrid; + OSL_ASSERT( pDestIt != pDestEnd ); + ++pDestIt; + } + OSL_ASSERT( pDestIt == pDestEnd ); +} + +} // anonymous namespace + +namespace chart +{ + +Axis::Axis() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_aScaleData( AxisHelper::createDefaultScale() ), + m_xGrid( new GridProperties() ) +{ + osl_atomic_increment(&m_refCount); + setFastPropertyValue_NoBroadcast( + ::chart::LinePropertiesHelper::PROP_LINE_COLOR, uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + + if( m_xGrid.is()) + ModifyListenerHelper::addListener( m_xGrid, m_xModifyEventForwarder ); + if( m_aScaleData.Categories.is()) + ModifyListenerHelper::addListener( m_aScaleData.Categories, m_xModifyEventForwarder ); + + AllocateSubGrids(); + osl_atomic_decrement(&m_refCount); +} + +Axis::Axis( const Axis & rOther ) : + impl::Axis_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_aScaleData( rOther.m_aScaleData ) +{ + m_xGrid.set( CloneHelper::CreateRefClone< beans::XPropertySet >()( rOther.m_xGrid )); + if( m_xGrid.is()) + ModifyListenerHelper::addListener( m_xGrid, m_xModifyEventForwarder ); + + if( m_aScaleData.Categories.is()) + ModifyListenerHelper::addListener( m_aScaleData.Categories, m_xModifyEventForwarder ); + + if( rOther.m_aSubGridProperties.hasElements() ) + lcl_CloneSubGrids( rOther.m_aSubGridProperties, m_aSubGridProperties ); + ModifyListenerHelper::addListenerToAllSequenceElements( m_aSubGridProperties, m_xModifyEventForwarder ); + + m_xTitle.set( CloneHelper::CreateRefClone< chart2::XTitle >()( rOther.m_xTitle )); + if( m_xTitle.is()) + ModifyListenerHelper::addListener( m_xTitle, m_xModifyEventForwarder ); +} + +// late initialization to call after copy-constructing +void Axis::Init() +{ + if( m_aScaleData.Categories.is()) + EventListenerHelper::addListener( m_aScaleData.Categories, this ); +} + +Axis::~Axis() +{ + try + { + ModifyListenerHelper::removeListener( m_xGrid, m_xModifyEventForwarder ); + ModifyListenerHelper::removeListenerFromAllSequenceElements( m_aSubGridProperties, m_xModifyEventForwarder ); + ModifyListenerHelper::removeListener( m_xTitle, m_xModifyEventForwarder ); + if( m_aScaleData.Categories.is()) + { + ModifyListenerHelper::removeListener( m_aScaleData.Categories, m_xModifyEventForwarder ); + m_aScaleData.Categories.set(nullptr); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + m_aSubGridProperties.realloc(0); + m_xGrid = nullptr; + m_xTitle = nullptr; +} + +void Axis::AllocateSubGrids() +{ + Reference< util::XModifyListener > xModifyEventForwarder; + Reference< lang::XEventListener > xEventListener; + std::vector< Reference< beans::XPropertySet > > aOldBroadcasters; + std::vector< Reference< beans::XPropertySet > > aNewBroadcasters; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + xEventListener = this; + + sal_Int32 nNewSubIncCount = m_aScaleData.IncrementData.SubIncrements.getLength(); + sal_Int32 nOldSubIncCount = m_aSubGridProperties.getLength(); + + if( nOldSubIncCount > nNewSubIncCount ) + { + // remove superfluous entries + for( sal_Int32 i = nNewSubIncCount; i < nOldSubIncCount; ++i ) + aOldBroadcasters.push_back( m_aSubGridProperties[ i ] ); + m_aSubGridProperties.realloc( nNewSubIncCount ); + } + else if( nOldSubIncCount < nNewSubIncCount ) + { + m_aSubGridProperties.realloc( nNewSubIncCount ); + auto pSubGridProperties = m_aSubGridProperties.getArray(); + + // allocate new entries + for( sal_Int32 i = nOldSubIncCount; i < nNewSubIncCount; ++i ) + { + pSubGridProperties[ i ] = new GridProperties(); + LinePropertiesHelper::SetLineInvisible( m_aSubGridProperties[ i ] ); + LinePropertiesHelper::SetLineColor( m_aSubGridProperties[ i ], static_cast<sal_Int32>(0xdddddd) ); //gray2 + aNewBroadcasters.push_back( m_aSubGridProperties[ i ] ); + } + } + } + //don't keep the mutex locked while calling out + for (auto const& oldBroadcaster : aOldBroadcasters) + ModifyListenerHelper::removeListener(oldBroadcaster, xModifyEventForwarder ); + for (auto const& newBroadcaster : aNewBroadcasters) + ModifyListenerHelper::addListener( newBroadcaster, xModifyEventForwarder ); +} + +// ____ XAxis ____ +void SAL_CALL Axis::setScaleData( const chart2::ScaleData& rScaleData ) +{ + Reference< util::XModifyListener > xModifyEventForwarder; + Reference< lang::XEventListener > xEventListener; + Reference< chart2::data::XLabeledDataSequence > xOldCategories; + Reference< chart2::data::XLabeledDataSequence > xNewCategories = rScaleData.Categories; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + xEventListener = this; + xOldCategories = m_aScaleData.Categories; + m_aScaleData = rScaleData; + } + AllocateSubGrids(); + + //don't keep the mutex locked while calling out + if( xOldCategories.is() && xOldCategories != xNewCategories ) + { + ModifyListenerHelper::removeListener( xOldCategories, xModifyEventForwarder ); + EventListenerHelper::removeListener( xOldCategories, xEventListener ); + } + if( xNewCategories.is() && xOldCategories != xNewCategories ) + { + ModifyListenerHelper::addListener( xNewCategories, m_xModifyEventForwarder ); + EventListenerHelper::addListener( xNewCategories, xEventListener ); + } + fireModifyEvent(); +} + +chart2::ScaleData SAL_CALL Axis::getScaleData() +{ + MutexGuard aGuard( m_aMutex ); + return m_aScaleData; +} + +Reference< beans::XPropertySet > SAL_CALL Axis::getGridProperties() +{ + MutexGuard aGuard( m_aMutex ); + return m_xGrid; +} +Sequence< Reference< beans::XPropertySet > > SAL_CALL Axis::getSubGridProperties() +{ + MutexGuard aGuard( m_aMutex ); + return m_aSubGridProperties; +} + +Sequence< Reference< beans::XPropertySet > > SAL_CALL Axis::getSubTickProperties() +{ + OSL_FAIL( "Not implemented yet" ); + return Sequence< Reference< beans::XPropertySet > >(); +} + +// ____ XTitled ____ +Reference< chart2::XTitle > SAL_CALL Axis::getTitleObject() +{ + MutexGuard aGuard( m_aMutex ); + return m_xTitle; +} + +void SAL_CALL Axis::setTitleObject( const Reference< chart2::XTitle >& xNewTitle ) +{ + Reference< util::XModifyListener > xModifyEventForwarder; + Reference< chart2::XTitle > xOldTitle; + { + MutexGuard aGuard( m_aMutex ); + xOldTitle = m_xTitle; + xModifyEventForwarder = m_xModifyEventForwarder; + m_xTitle = xNewTitle; + } + + //don't keep the mutex locked while calling out + if( xOldTitle.is() && xOldTitle != xNewTitle ) + ModifyListenerHelper::removeListener( xOldTitle, xModifyEventForwarder ); + if( xNewTitle.is() && xOldTitle != xNewTitle ) + ModifyListenerHelper::addListener( xNewTitle, xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ XCloneable ____ +Reference< util::XCloneable > SAL_CALL Axis::createClone() +{ + rtl::Reference<Axis> pNewAxis( new Axis( *this )); + // do initialization that uses uno references to the clone + pNewAxis->Init(); + return pNewAxis; +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Axis::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL Axis::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL Axis::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL Axis::disposing( const lang::EventObject& Source ) +{ + if( Source.Source == m_aScaleData.Categories ) + m_aScaleData.Categories = nullptr; +} + +// ____ OPropertySet ____ +void Axis::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void Axis::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ____ OPropertySet ____ +void Axis::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticAxisDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Axis::getInfoHelper() +{ + return *StaticAxisInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL Axis::getPropertySetInfo() +{ + return *StaticAxisInfo::get(); +} + +using impl::Axis_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( Axis, Axis_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( Axis, Axis_Base, ::property::OPropertySet ) + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL Axis::getImplementationName() +{ + return "com.sun.star.comp.chart2.Axis"; +} + +sal_Bool SAL_CALL Axis::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL Axis::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.Axis", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_Axis_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::Axis); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/BaseCoordinateSystem.cxx b/chart2/source/model/main/BaseCoordinateSystem.cxx new file mode 100644 index 000000000..98dc9b4e8 --- /dev/null +++ b/chart2/source/model/main/BaseCoordinateSystem.cxx @@ -0,0 +1,413 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <BaseCoordinateSystem.hxx> +#include <PropertyHelper.hxx> +#include <UserDefinedProperties.hxx> +#include <CloneHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <Axis.hxx> +#include <ChartType.hxx> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <o3tl/safeint.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +#include <com/sun/star/beans/PropertyAttribute.hpp> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ +enum +{ + PROP_COORDINATESYSTEM_SWAPXANDYAXIS +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "SwapXAndYAxis", + PROP_COORDINATESYSTEM_SWAPXANDYAXIS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticCooSysDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::PropertyHelper::setPropertyValueDefault( aStaticDefaults, PROP_COORDINATESYSTEM_SWAPXANDYAXIS, false ); + return &aStaticDefaults; + } +}; + +struct StaticCooSysDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticCooSysDefaults_Initializer > +{ +}; + +struct StaticCooSysInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticCooSysInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticCooSysInfoHelper_Initializer > +{ +}; + +struct StaticCooSysInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticCooSysInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticCooSysInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticCooSysInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +BaseCoordinateSystem::BaseCoordinateSystem( + sal_Int32 nDimensionCount /* = 2 */ ) : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_nDimensionCount( nDimensionCount ) + { + m_aAllAxis.resize( m_nDimensionCount ); + for( sal_Int32 nN=0; nN<m_nDimensionCount; nN++ ) + { + m_aAllAxis[nN].resize( 1 ); + rtl::Reference< Axis > xAxis( new Axis ); + m_aAllAxis[nN][0] = xAxis; + + ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder ); + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + if(nN==0) + { + aScaleData.AxisType = chart2::AxisType::CATEGORY; + } + else if( nN==1) + { + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + } + else if( nN==2) + { + aScaleData.AxisType = chart2::AxisType::SERIES; + } + xAxis->setScaleData( aScaleData ); + } + + setFastPropertyValue_NoBroadcast( PROP_COORDINATESYSTEM_SWAPXANDYAXIS, uno::Any( false )); +} + +// explicit +BaseCoordinateSystem::BaseCoordinateSystem( + const BaseCoordinateSystem & rSource ) : + impl::BaseCoordinateSystem_Base(rSource), + ::property::OPropertySet( rSource, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_nDimensionCount( rSource.m_nDimensionCount ) +{ + m_aAllAxis.resize(rSource.m_aAllAxis.size()); + tAxisVecVecType::size_type nN=0; + for( nN=0; nN<m_aAllAxis.size(); nN++ ) + CloneHelper::CloneRefVector( rSource.m_aAllAxis[nN], m_aAllAxis[nN] ); + for (const auto & rxChartType : rSource.m_aChartTypes) + m_aChartTypes.push_back(rxChartType->cloneChartType()); + + for( nN=0; nN<m_aAllAxis.size(); nN++ ) + ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder ); + for (const auto & rxChartType : m_aChartTypes) + rxChartType->addModifyListener( m_xModifyEventForwarder ); +} + +BaseCoordinateSystem::~BaseCoordinateSystem() +{ + try + { + for(const tAxisVecVecType::value_type & i : m_aAllAxis) + ModifyListenerHelper::removeListenerFromAllElements( i, m_xModifyEventForwarder ); + for (const auto & rxChartType : m_aChartTypes) + rxChartType->removeModifyListener( m_xModifyEventForwarder ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } +} + +// ____ XCoordinateSystem ____ +sal_Int32 SAL_CALL BaseCoordinateSystem::getDimension() +{ + return m_nDimensionCount; +} + +void SAL_CALL BaseCoordinateSystem::setAxisByDimension( + sal_Int32 nDimensionIndex, + const Reference< chart2::XAxis >& xAxis, + sal_Int32 nIndex ) +{ + if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() ) + throw lang::IndexOutOfBoundsException(); + + if( nIndex < 0 ) + throw lang::IndexOutOfBoundsException(); + + assert(!xAxis || dynamic_cast<Axis*>(xAxis.get())); + + if( m_aAllAxis[ nDimensionIndex ].size() < o3tl::make_unsigned( nIndex+1 )) + { + m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 ); + m_aAllAxis[ nDimensionIndex ][nIndex] = nullptr; + } + + rtl::Reference< Axis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] ); + if( xOldAxis.is()) + ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder ); + m_aAllAxis[ nDimensionIndex ][nIndex] = dynamic_cast<Axis*>(xAxis.get()); + if( xAxis.is()) + ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +void BaseCoordinateSystem::setAxisByDimension( + sal_Int32 nDimensionIndex, + const rtl::Reference< Axis >& xAxis, + sal_Int32 nIndex ) +{ + if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() ) + throw lang::IndexOutOfBoundsException(); + + if( nIndex < 0 ) + throw lang::IndexOutOfBoundsException(); + + if( m_aAllAxis[ nDimensionIndex ].size() < o3tl::make_unsigned( nIndex+1 )) + { + m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 ); + m_aAllAxis[ nDimensionIndex ][nIndex] = nullptr; + } + + rtl::Reference< Axis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] ); + if( xOldAxis.is()) + ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder ); + m_aAllAxis[ nDimensionIndex ][nIndex] = xAxis; + if( xAxis.is()) + ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +Reference< chart2::XAxis > SAL_CALL BaseCoordinateSystem::getAxisByDimension( + sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) +{ + if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() ) + throw lang::IndexOutOfBoundsException(); + + OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension())); + + if( nAxisIndex < 0 || nAxisIndex > getMaximumAxisIndexByDimension(nDimensionIndex) ) + throw lang::IndexOutOfBoundsException(); + + return m_aAllAxis[ nDimensionIndex ][nAxisIndex]; +} + +const rtl::Reference< Axis > & BaseCoordinateSystem::getAxisByDimension2( + sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const +{ + if( nDimensionIndex < 0 || nDimensionIndex >= m_nDimensionCount ) + throw lang::IndexOutOfBoundsException(); + + OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( m_nDimensionCount)); + + if( nAxisIndex < 0 || o3tl::make_unsigned(nAxisIndex) > m_aAllAxis[ nDimensionIndex ].size() ) + throw lang::IndexOutOfBoundsException(); + + return m_aAllAxis[ nDimensionIndex ][nAxisIndex]; +} + +sal_Int32 SAL_CALL BaseCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) +{ + if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() ) + throw lang::IndexOutOfBoundsException(); + + OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension())); + + sal_Int32 nRet = m_aAllAxis[ nDimensionIndex ].size(); + if(nRet) + nRet-=1; + + return nRet; +} + +// ____ XChartTypeContainer ____ +void SAL_CALL BaseCoordinateSystem::addChartType( const Reference< chart2::XChartType >& aChartType ) +{ + auto pChartType = dynamic_cast<ChartType*>(aChartType.get()); + assert(pChartType); + + if( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), pChartType ) + != m_aChartTypes.end()) + throw lang::IllegalArgumentException("type not found", static_cast<cppu::OWeakObject*>(this), 1); + + m_aChartTypes.push_back( pChartType ); + ModifyListenerHelper::addListener( aChartType, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +void SAL_CALL BaseCoordinateSystem::removeChartType( const Reference< chart2::XChartType >& aChartType ) +{ + auto pChartType = dynamic_cast<ChartType*>(aChartType.get()); + assert(pChartType); + auto aIt( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), pChartType )); + if( aIt == m_aChartTypes.end()) + throw container::NoSuchElementException( + "The given chart type is no element of the container", + static_cast< uno::XWeak * >( this )); + + m_aChartTypes.erase( aIt ); + ModifyListenerHelper::removeListener( aChartType, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +Sequence< Reference< chart2::XChartType > > SAL_CALL BaseCoordinateSystem::getChartTypes() +{ + return comphelper::containerToSequence< Reference< chart2::XChartType > >( m_aChartTypes ); +} + +void SAL_CALL BaseCoordinateSystem::setChartTypes( const Sequence< Reference< chart2::XChartType > >& aChartTypes ) +{ + for (auto const & aChartType : m_aChartTypes) + aChartType->removeModifyListener( m_xModifyEventForwarder ); + m_aChartTypes.clear(); + for (auto const & aChartType : aChartTypes) + { + auto pChartType = dynamic_cast<ChartType*>(aChartType.get()); + assert(pChartType); + m_aChartTypes.push_back(pChartType); + pChartType->addModifyListener( m_xModifyEventForwarder ); + } + fireModifyEvent(); +} + +void BaseCoordinateSystem::setChartTypes( const std::vector< rtl::Reference< ChartType > >& aChartTypes ) +{ + for (auto const & aChartType : m_aChartTypes) + aChartType->removeModifyListener( m_xModifyEventForwarder ); + m_aChartTypes = aChartTypes; + for (auto const & aChartType : m_aChartTypes) + aChartType->addModifyListener( m_xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL BaseCoordinateSystem::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL BaseCoordinateSystem::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL BaseCoordinateSystem::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL BaseCoordinateSystem::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void BaseCoordinateSystem::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void BaseCoordinateSystem::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ____ OPropertySet ____ +void BaseCoordinateSystem::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticCooSysDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL BaseCoordinateSystem::getInfoHelper() +{ + return *StaticCooSysInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL BaseCoordinateSystem::getPropertySetInfo() +{ + return *StaticCooSysInfo::get(); +} + +using impl::BaseCoordinateSystem_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/CartesianCoordinateSystem.cxx b/chart2/source/model/main/CartesianCoordinateSystem.cxx new file mode 100644 index 000000000..c65adee25 --- /dev/null +++ b/chart2/source/model/main/CartesianCoordinateSystem.cxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <CartesianCoordinateSystem.hxx> +#include <servicenames_coosystems.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace com::sun::star::uno { class XComponentContext; } + +namespace +{ + +constexpr OUStringLiteral CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME = u"com.sun.star.chart2.CoordinateSystems.Cartesian"; + +} + +namespace chart +{ + +// explicit +CartesianCoordinateSystem::CartesianCoordinateSystem( + sal_Int32 nDimensionCount /* = 2 */ ) : + BaseCoordinateSystem( nDimensionCount ) +{} + +CartesianCoordinateSystem::CartesianCoordinateSystem( + const CartesianCoordinateSystem & rSource ) : + BaseCoordinateSystem( rSource ) +{} + +CartesianCoordinateSystem::~CartesianCoordinateSystem() +{} + +// ____ XCoordinateSystem ____ +OUString SAL_CALL CartesianCoordinateSystem::getCoordinateSystemType() +{ + return CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME; +} + +OUString SAL_CALL CartesianCoordinateSystem::getViewServiceName() +{ + return CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME; +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL CartesianCoordinateSystem::createClone() +{ + return Reference< util::XCloneable >( new CartesianCoordinateSystem( *this )); +} + +// ____ XServiceInfo ____ +OUString SAL_CALL CartesianCoordinateSystem::getImplementationName() +{ + return "com.sun.star.comp.chart.CartesianCoordinateSystem"; +} + +sal_Bool SAL_CALL CartesianCoordinateSystem::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL CartesianCoordinateSystem::getSupportedServiceNames() +{ + return { CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME }; +} + +// ==== CartesianCoordinateSystem2d ==== + +CartesianCoordinateSystem2d::CartesianCoordinateSystem2d() : + CartesianCoordinateSystem( 2 ) +{} + +CartesianCoordinateSystem2d::~CartesianCoordinateSystem2d() +{} + +// ____ XServiceInfo ____ +OUString SAL_CALL CartesianCoordinateSystem2d::getImplementationName() +{ + return "com.sun.star.comp.chart2.CartesianCoordinateSystem2d"; +} + +sal_Bool SAL_CALL CartesianCoordinateSystem2d::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL CartesianCoordinateSystem2d::getSupportedServiceNames() +{ + return { + CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME, + "com.sun.star.chart2.CartesianCoordinateSystem2d" + }; +} + +// ==== CartesianCoordinateSystem3d ==== + +CartesianCoordinateSystem3d::CartesianCoordinateSystem3d() : + CartesianCoordinateSystem( 3 ) +{} + +CartesianCoordinateSystem3d::~CartesianCoordinateSystem3d() +{} + +// ____ XServiceInfo ____ +OUString SAL_CALL CartesianCoordinateSystem3d::getImplementationName() +{ + return "com.sun.star.comp.chart2.CartesianCoordinateSystem3d"; +} + +sal_Bool SAL_CALL CartesianCoordinateSystem3d::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL CartesianCoordinateSystem3d::getSupportedServiceNames() +{ + return { + CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME, + "com.sun.star.chart2.CartesianCoordinateSystem3d" + }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_CartesianCoordinateSystem2d_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::CartesianCoordinateSystem2d); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_CartesianCoordinateSystem3d_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::CartesianCoordinateSystem3d); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/ChartModel.cxx b/chart2/source/model/main/ChartModel.cxx new file mode 100644 index 000000000..712be3fdf --- /dev/null +++ b/chart2/source/model/main/ChartModel.cxx @@ -0,0 +1,1306 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartModel.hxx> +#include <ChartTypeManager.hxx> +#include <ChartTypeTemplate.hxx> +#include <servicenames.hxx> +#include <DataSource.hxx> +#include <DataSourceHelper.hxx> +#include <ChartModelHelper.hxx> +#include <DisposeHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <InternalDataProvider.hxx> +#include <ObjectIdentifier.hxx> +#include "PageBackground.hxx" +#include <CloneHelper.hxx> +#include <NameContainer.hxx> +#include "UndoManager.hxx" +#include <ChartView.hxx> +#include <PopupRequest.hxx> +#include <ModifyListenerHelper.hxx> +#include <Diagram.hxx> + +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <svl/numformat.hxx> +#include <svl/numuno.hxx> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/embed/EmbedMapUnits.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/document/DocumentProperties.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> + +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> +#include <libxml/xmlwriter.h> + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::osl::MutexGuard; + +using namespace ::com::sun::star; +using namespace ::apphelper; +using namespace ::chart::CloneHelper; + +namespace +{ +constexpr OUStringLiteral lcl_aGDIMetaFileMIMEType( + u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""); +constexpr OUStringLiteral lcl_aGDIMetaFileMIMETypeHighContrast( + u"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""); + +} // anonymous namespace + +// ChartModel Constructor and Destructor + +namespace chart +{ + +ChartModel::ChartModel(uno::Reference<uno::XComponentContext > const & xContext) + : m_aLifeTimeManager( this, this ) + , m_bReadOnly( false ) + , m_bModified( false ) + , m_nInLoad(0) + , m_bUpdateNotificationsPending(false) + , mbTimeBased(false) + , m_aControllers( m_aModelMutex ) + , m_nControllerLockCount(0) + , m_xContext( xContext ) + , m_aVisualAreaSize( ChartModelHelper::getDefaultPageSize() ) + , m_xPageBackground( new PageBackground ) + , m_xXMLNamespaceMap( new NameContainer() ) + , mnStart(0) + , mnEnd(0) +{ + osl_atomic_increment(&m_refCount); + { + m_xOldModelAgg.set( + m_xContext->getServiceManager()->createInstanceWithContext( + CHART_CHARTAPIWRAPPER_SERVICE_NAME, + m_xContext ), uno::UNO_QUERY_THROW ); + m_xOldModelAgg->setDelegator( *this ); + } + + { + m_xPageBackground->addModifyListener( this ); + m_xChartTypeManager = new ::chart::ChartTypeManager( m_xContext ); + } + osl_atomic_decrement(&m_refCount); +} + +ChartModel::ChartModel( const ChartModel & rOther ) + : impl::ChartModel_Base(rOther) + , m_aLifeTimeManager( this, this ) + , m_bReadOnly( rOther.m_bReadOnly ) + , m_bModified( rOther.m_bModified ) + , m_nInLoad(0) + , m_bUpdateNotificationsPending(false) + , mbTimeBased(rOther.mbTimeBased) + , m_aResource( rOther.m_aResource ) + , m_aMediaDescriptor( rOther.m_aMediaDescriptor ) + , m_aControllers( m_aModelMutex ) + , m_nControllerLockCount(0) + , m_xContext( rOther.m_xContext ) + // @note: the old model aggregate must not be shared with other models if it + // is, you get mutex deadlocks + //, m_xOldModelAgg( nullptr ) //rOther.m_xOldModelAgg ) + // m_xStorage( nullptr ) //rOther.m_xStorage ) + , m_aVisualAreaSize( rOther.m_aVisualAreaSize ) + , m_aGraphicObjectVector( rOther.m_aGraphicObjectVector ) + , m_xDataProvider( rOther.m_xDataProvider ) + , m_xInternalDataProvider( rOther.m_xInternalDataProvider ) + , mnStart(rOther.mnStart) + , mnEnd(rOther.mnEnd) +{ + osl_atomic_increment(&m_refCount); + { + m_xOldModelAgg.set( + m_xContext->getServiceManager()->createInstanceWithContext( + CHART_CHARTAPIWRAPPER_SERVICE_NAME, + m_xContext ), uno::UNO_QUERY_THROW ); + m_xOldModelAgg->setDelegator( *this ); + + Reference< util::XModifyListener > xListener; + Reference< chart2::XTitle > xNewTitle = CreateRefClone< chart2::XTitle >()( rOther.m_xTitle ); + rtl::Reference< ::chart::Diagram > xNewDiagram; + if (rOther.m_xDiagram.is()) + xNewDiagram = new ::chart::Diagram( *rOther.m_xDiagram ); + rtl::Reference< ::chart::PageBackground > xNewPageBackground = new PageBackground( *rOther.m_xPageBackground ); + rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager; // does not implement XCloneable + rtl::Reference< ::chart::NameContainer > xXMLNamespaceMap = new NameContainer( *rOther.m_xXMLNamespaceMap ); + + { + MutexGuard aGuard( m_aModelMutex ); + xListener = this; + m_xTitle = xNewTitle; + m_xDiagram = xNewDiagram; + m_xPageBackground = xNewPageBackground; + m_xChartTypeManager = xChartTypeManager; + m_xXMLNamespaceMap = xXMLNamespaceMap; + } + + ModifyListenerHelper::addListener( xNewTitle, xListener ); + if( xNewDiagram && xListener) + xNewDiagram->addModifyListener( xListener ); + if( xNewPageBackground && xListener) + xNewPageBackground->addModifyListener( xListener ); + xListener.clear(); + } + osl_atomic_decrement(&m_refCount); +} + +ChartModel::~ChartModel() +{ + if( m_xOldModelAgg.is()) + m_xOldModelAgg->setDelegator( nullptr ); +} + +void SAL_CALL ChartModel::initialize( const Sequence< Any >& /*rArguments*/ ) +{ + //#i113722# avoid duplicate creation + + //maybe additional todo?: + //support argument "EmbeddedObject"? + //support argument "EmbeddedScriptSupport"? + //support argument "DocumentRecoverySupport"? +} + +ChartView* ChartModel::getChartView() const +{ + return mxChartView.get(); +} + +// private methods + +OUString ChartModel::impl_g_getLocation() +{ + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return OUString(); //behave passive if already disposed or closed or throw exception @todo? + //mutex is acquired + return m_aResource; +} + +bool ChartModel::impl_isControllerConnected( const uno::Reference< frame::XController >& xController ) +{ + try + { + std::vector< uno::Reference<uno::XInterface> > aSeq = m_aControllers.getElements(); + for( const auto & r : aSeq ) + { + if( r == xController ) + return true; + } + } + catch (const uno::Exception&) + { + } + return false; +} + +uno::Reference< frame::XController > ChartModel::impl_getCurrentController() +{ + //@todo? hold only weak references to controllers + + // get the last active controller of this model + if( m_xCurrentController.is() ) + return m_xCurrentController; + + // get the first controller of this model + if( m_aControllers.getLength() ) + { + uno::Reference<uno::XInterface> xI = m_aControllers.getInterface(0); + return uno::Reference<frame::XController>( xI, uno::UNO_QUERY ); + } + + //return nothing if no controllers are connected at all + return uno::Reference< frame::XController > (); +} + +void ChartModel::impl_notifyCloseListeners() +{ + ::comphelper::OInterfaceContainerHelper2* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType<util::XCloseListener>::get()); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent*>(this) ); + ::comphelper::OInterfaceIteratorHelper2 aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + static_cast< util::XCloseListener* >( aIt.next() )->notifyClosing( aEvent ); + } + } +} + +void ChartModel::impl_adjustAdditionalShapesPositionAndSize( const awt::Size& aVisualAreaSize ) +{ + uno::Reference< beans::XPropertySet > xProperties( static_cast< ::cppu::OWeakObject* >( this ), uno::UNO_QUERY ); + if ( !xProperties.is() ) + return; + + uno::Reference< drawing::XShapes > xShapes; + xProperties->getPropertyValue( "AdditionalShapes" ) >>= xShapes; + if ( !xShapes.is() ) + return; + + sal_Int32 nCount = xShapes->getCount(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< drawing::XShape > xShape; + if ( xShapes->getByIndex( i ) >>= xShape ) + { + if ( xShape.is() ) + { + awt::Point aPos( xShape->getPosition() ); + awt::Size aSize( xShape->getSize() ); + + double fWidth = static_cast< double >( aVisualAreaSize.Width ) / m_aVisualAreaSize.Width; + double fHeight = static_cast< double >( aVisualAreaSize.Height ) / m_aVisualAreaSize.Height; + + aPos.X = static_cast< tools::Long >( aPos.X * fWidth ); + aPos.Y = static_cast< tools::Long >( aPos.Y * fHeight ); + aSize.Width = static_cast< tools::Long >( aSize.Width * fWidth ); + aSize.Height = static_cast< tools::Long >( aSize.Height * fHeight ); + + xShape->setPosition( aPos ); + xShape->setSize( aSize ); + } + } + } +} + +// lang::XServiceInfo + +OUString SAL_CALL ChartModel::getImplementationName() +{ + return CHART_MODEL_SERVICE_IMPLEMENTATION_NAME; +} + +sal_Bool SAL_CALL ChartModel::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL ChartModel::getSupportedServiceNames() +{ + return { + CHART_MODEL_SERVICE_NAME, + "com.sun.star.document.OfficeDocument", + "com.sun.star.chart.ChartDocument" + }; +} + +// frame::XModel (required interface) + +sal_Bool SAL_CALL ChartModel::attachResource( const OUString& rURL + , const uno::Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + /* + The method attachResource() is used by the frame loader implementations + to inform the model about its URL and MediaDescriptor. + */ + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return false; //behave passive if already disposed or closed or throw exception @todo? + //mutex is acquired + + if(!m_aResource.isEmpty())//we have a resource already //@todo? or is setting a new resource allowed? + return false; + m_aResource = rURL; + m_aMediaDescriptor = rMediaDescriptor; + + //@todo ? check rURL ?? + //@todo ? evaluate m_aMediaDescriptor; + //@todo ? ... ??? --> nothing, this method is only for setting information + + return true; +} + +OUString SAL_CALL ChartModel::getURL() +{ + return impl_g_getLocation(); +} + +uno::Sequence< beans::PropertyValue > SAL_CALL ChartModel::getArgs() +{ + /* + The method getArgs() returns a sequence of property values + that report the resource description according to com.sun.star.document.MediaDescriptor, + specified on loading or saving with storeAsURL. + */ + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return uno::Sequence< beans::PropertyValue >(); //behave passive if already disposed or closed or throw exception @todo? + //mutex is acquired + + return m_aMediaDescriptor; +} + +void SAL_CALL ChartModel::connectController( const uno::Reference< frame::XController >& xController ) +{ + //@todo? this method is declared as oneway -> ...? + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return ; //behave passive if already disposed or closed + //mutex is acquired + + //--add controller + m_aControllers.addInterface(xController); +} + +void SAL_CALL ChartModel::disconnectController( const uno::Reference< frame::XController >& xController ) +{ + //@todo? this method is declared as oneway -> ...? + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return; //behave passive if already disposed or closed + + //--remove controller + m_aControllers.removeInterface(xController); + + //case: current controller is disconnected: + if( m_xCurrentController == xController ) + m_xCurrentController.clear(); + + DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); + DisposeHelper::DisposeAndClear(m_xPopupRequest); +} + +void SAL_CALL ChartModel::lockControllers() +{ + /* + suspends some notifications to the controllers which are used for display updates. + + The calls to lockControllers() and unlockControllers() may be nested + and even overlapping, but they must be in pairs. While there is at least one lock + remaining, some notifications for display updates are not broadcasted. + */ + + //@todo? this method is declared as oneway -> ...? + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return; //behave passive if already disposed or closed or throw exception @todo? + ++m_nControllerLockCount; +} + +void SAL_CALL ChartModel::unlockControllers() +{ + /* + resumes the notifications which were suspended by lockControllers() . + + The calls to lockControllers() and unlockControllers() may be nested + and even overlapping, but they must be in pairs. While there is at least one lock + remaining, some notifications for display updates are not broadcasted. + */ + + //@todo? this method is declared as oneway -> ...? + + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return; //behave passive if already disposed or closed or throw exception @todo? + if( m_nControllerLockCount == 0 ) + { + SAL_WARN("chart2", "ChartModel: unlockControllers called with m_nControllerLockCount == 0" ); + return; + } + --m_nControllerLockCount; + if( m_nControllerLockCount == 0 && m_bUpdateNotificationsPending ) + { + aGuard.clear(); + impl_notifyModifiedListeners(); + } +} + +sal_Bool SAL_CALL ChartModel::hasControllersLocked() +{ + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + return false; //behave passive if already disposed or closed or throw exception @todo? + return ( m_nControllerLockCount != 0 ) ; +} + +uno::Reference< frame::XController > SAL_CALL ChartModel::getCurrentController() +{ + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + throw lang::DisposedException( + "getCurrentController was called on an already disposed or closed model", + static_cast< ::cppu::OWeakObject* >(this) ); + + return impl_getCurrentController(); +} + +void SAL_CALL ChartModel::setCurrentController( const uno::Reference< frame::XController >& xController ) +{ + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + throw lang::DisposedException( + "setCurrentController was called on an already disposed or closed model", + static_cast< ::cppu::OWeakObject* >(this) ); + + //OSL_ENSURE( impl_isControllerConnected(xController), "setCurrentController is called with a Controller which is not connected" ); + if(!impl_isControllerConnected(xController)) + throw container::NoSuchElementException( + "setCurrentController is called with a Controller which is not connected", + static_cast< ::cppu::OWeakObject* >(this) ); + + m_xCurrentController = xController; + + DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); + DisposeHelper::DisposeAndClear(m_xPopupRequest); +} + +uno::Reference< uno::XInterface > SAL_CALL ChartModel::getCurrentSelection() +{ + LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall()) + throw lang::DisposedException( + "getCurrentSelection was called on an already disposed or closed model", + static_cast< ::cppu::OWeakObject* >(this) ); + + uno::Reference< uno::XInterface > xReturn; + uno::Reference< frame::XController > xController = impl_getCurrentController(); + + aGuard.clear(); + if( xController.is() ) + { + uno::Reference< view::XSelectionSupplier > xSelectionSupl( xController, uno::UNO_QUERY ); + if ( xSelectionSupl.is() ) + { + uno::Any aSel = xSelectionSupl->getSelection(); + OUString aObjectCID; + if( aSel >>= aObjectCID ) + xReturn.set( ObjectIdentifier::getObjectPropertySet( aObjectCID, this)); + } + } + return xReturn; +} + +// lang::XComponent (base of XModel) +void SAL_CALL ChartModel::dispose() +{ + Reference< XInterface > xKeepAlive( *this ); + + //This object should release all resources and references in the + //easiest possible manner + //This object must notify all registered listeners using the method + //<member>XEventListener::disposing</member> + + //hold no mutex + if( !m_aLifeTimeManager.dispose() ) + return; + + //--release all resources and references + //// @todo + + if ( m_xDiagram.is() ) + m_xDiagram->removeModifyListener( this ); + + if ( m_xDataProvider.is() ) + { + Reference<util::XModifyBroadcaster> xModifyBroadcaster( m_xDataProvider, uno::UNO_QUERY ); + if ( xModifyBroadcaster.is() ) + xModifyBroadcaster->removeModifyListener( this ); + } + + m_xDataProvider.clear(); + m_xInternalDataProvider.clear(); + m_xNumberFormatsSupplier.clear(); + m_xOwnNumberFormatsSupplier.clear(); + m_xChartTypeManager.clear(); + m_xDiagram.clear(); + DisposeHelper::DisposeAndClear( m_xTitle ); + m_xPageBackground.clear(); + m_xXMLNamespaceMap.clear(); + + m_xStorage.clear(); + // just clear, don't dispose - we're not the owner + + if ( m_pUndoManager.is() ) + m_pUndoManager->disposing(); + m_pUndoManager.clear(); + // that's important, since the UndoManager implementation delegates its ref counting to ourself. + + if( m_xOldModelAgg.is()) // #i120828#, to release cyclic reference to ChartModel object + m_xOldModelAgg->setDelegator( nullptr ); + + m_aControllers.disposeAndClear( lang::EventObject( static_cast< cppu::OWeakObject * >( this ))); + m_xCurrentController.clear(); + + DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); + DisposeHelper::DisposeAndClear(m_xPopupRequest); + + if( m_xOldModelAgg.is()) + m_xOldModelAgg->setDelegator( nullptr ); +} + +void SAL_CALL ChartModel::addEventListener( const uno::Reference< lang::XEventListener > & xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType<lang::XEventListener>::get(), xListener ); +} + +void SAL_CALL ChartModel::removeEventListener( const uno::Reference< lang::XEventListener > & xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), xListener ); +} + +// util::XCloseBroadcaster (base of XCloseable) +void SAL_CALL ChartModel::addCloseListener( const uno::Reference< util::XCloseListener > & xListener ) +{ + m_aLifeTimeManager.g_addCloseListener( xListener ); +} + +void SAL_CALL ChartModel::removeCloseListener( const uno::Reference< util::XCloseListener > & xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType<util::XCloseListener>::get(), xListener ); +} + +// util::XCloseable +void SAL_CALL ChartModel::close( sal_Bool bDeliverOwnership ) +{ + //hold no mutex + + if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) ) + return; + //no mutex is acquired + + // At the end of this method may we must dispose ourself ... + // and may nobody from outside hold a reference to us ... + // then it's a good idea to do that by ourself. + uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) ); + + //the listeners have had no veto + //check whether we self can close + { + util::CloseVetoException aVetoException( + "the model itself could not be closed", + static_cast< ::cppu::OWeakObject* >(this) ); + + m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException ); + } + m_aLifeTimeManager.g_close_endTryClose_doClose(); + + // BM @todo: is it ok to call the listeners here? + impl_notifyCloseListeners(); +} + +// lang::XTypeProvider +uno::Sequence< uno::Type > SAL_CALL ChartModel::getTypes() +{ + uno::Reference< lang::XTypeProvider > xAggTypeProvider; + if( (m_xOldModelAgg->queryAggregation( cppu::UnoType<decltype(xAggTypeProvider)>::get()) >>= xAggTypeProvider) + && xAggTypeProvider.is()) + { + return comphelper::concatSequences( + impl::ChartModel_Base::getTypes(), + xAggTypeProvider->getTypes()); + } + + return impl::ChartModel_Base::getTypes(); +} + +// document::XDocumentPropertiesSupplier +uno::Reference< document::XDocumentProperties > SAL_CALL + ChartModel::getDocumentProperties() +{ + ::osl::MutexGuard aGuard( m_aModelMutex ); + if ( !m_xDocumentProperties.is() ) + { + m_xDocumentProperties.set( document::DocumentProperties::create( ::comphelper::getProcessComponentContext() ) ); + } + return m_xDocumentProperties; +} + +// document::XDocumentPropertiesSupplier +Reference< document::XUndoManager > SAL_CALL ChartModel::getUndoManager( ) +{ + ::osl::MutexGuard aGuard( m_aModelMutex ); + if ( !m_pUndoManager.is() ) + m_pUndoManager.set( new UndoManager( *this, m_aModelMutex ) ); + return m_pUndoManager; +} + +// chart2::XChartDocument + +uno::Reference< chart2::XDiagram > SAL_CALL ChartModel::getFirstDiagram() +{ + MutexGuard aGuard( m_aModelMutex ); + return m_xDiagram; +} + +void SAL_CALL ChartModel::setFirstDiagram( const uno::Reference< chart2::XDiagram >& xDiagram ) +{ + rtl::Reference< ::chart::Diagram > xOldDiagram; + Reference< util::XModifyListener > xListener; + { + MutexGuard aGuard( m_aModelMutex ); + if( xDiagram.get() == m_xDiagram.get() ) + return; + xOldDiagram = m_xDiagram; + assert(!xDiagram || dynamic_cast<::chart::Diagram*>(xDiagram.get())); + m_xDiagram = dynamic_cast<::chart::Diagram*>(xDiagram.get()); + xListener = this; + } + //don't keep the mutex locked while calling out + if( xOldDiagram && xListener ) + xOldDiagram->removeModifyListener( xListener ); + ModifyListenerHelper::addListener( xDiagram, xListener ); + setModified( true ); +} + +Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData() +{ + Reference< chart2::data::XDataSource > xDataSource; + if( hasInternalDataProvider() ) + { + //init internal dataprovider + { + beans::NamedValue aParam( "CreateDefaultData" ,uno::Any(true) ); + uno::Sequence< uno::Any > aArgs{ uno::Any(aParam) }; + m_xInternalDataProvider->initialize(aArgs); + } + //create data + uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({ + { "CellRangeRepresentation", uno::Any( OUString("all") ) }, + { "HasCategories", uno::Any( true ) }, + { "FirstCellAsLabel", uno::Any( true ) }, + { "DataRowSource", uno::Any( css::chart::ChartDataRowSource_COLUMNS ) } + })); + xDataSource = m_xInternalDataProvider->createDataSource( aArgs ); + } + return xDataSource; +} + +void SAL_CALL ChartModel::createInternalDataProvider( sal_Bool bCloneExistingData ) +{ + // 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 + if( !hasInternalDataProvider() ) + { + if( bCloneExistingData ) + m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( this, true ); + else + m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( nullptr, true ); + m_xDataProvider.set( m_xInternalDataProvider ); + } + setModified( true ); +} + +void ChartModel::removeDataProviders() +{ + if (m_xInternalDataProvider.is()) + m_xInternalDataProvider.clear(); + if (m_xDataProvider.is()) + m_xDataProvider.clear(); +} + +void ChartModel::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ChartModel")); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + + if (mxChartView.is()) + { + mxChartView->dumpAsXml(pWriter); + } + + (void)xmlTextWriterEndElement(pWriter); +} + +sal_Bool SAL_CALL ChartModel::hasInternalDataProvider() +{ + return m_xDataProvider.is() && m_xInternalDataProvider.is(); +} + +uno::Reference< chart2::data::XDataProvider > SAL_CALL ChartModel::getDataProvider() +{ + MutexGuard aGuard( m_aModelMutex ); + return m_xDataProvider; +} + +// ____ XDataReceiver ____ + +void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< chart2::data::XDataProvider >& xDataProvider ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + uno::Reference< beans::XPropertySet > xProp( xDataProvider, uno::UNO_QUERY ); + if( xProp.is() ) + { + try + { + bool bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( this ); + xProp->setPropertyValue("IncludeHiddenCells", uno::Any(bIncludeHiddenCells)); + } + catch (const beans::UnknownPropertyException&) + { + } + } + + uno::Reference<util::XModifyBroadcaster> xModifyBroadcaster(xDataProvider, uno::UNO_QUERY); + if (xModifyBroadcaster.is()) + { + xModifyBroadcaster->addModifyListener(this); + } + + m_xDataProvider.set( xDataProvider ); + m_xInternalDataProvider.clear(); + + //the numberformatter is kept independent of the data provider! + } + setModified( true ); +} + +void SAL_CALL ChartModel::attachNumberFormatsSupplier( const uno::Reference< util::XNumberFormatsSupplier >& xNewSupplier ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + if( xNewSupplier == m_xNumberFormatsSupplier ) + return; + if( xNewSupplier == uno::Reference<XNumberFormatsSupplier>(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( true ); +} + +void SAL_CALL ChartModel::setArguments( const Sequence< beans::PropertyValue >& aArguments ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + if( !m_xDataProvider.is() ) + return; + lockControllers(); + + try + { + Reference< chart2::data::XDataSource > xDataSource( m_xDataProvider->createDataSource( aArguments ) ); + if( xDataSource.is() ) + { + rtl::Reference< Diagram > xDia = getFirstChartDiagram(); + if( !xDia.is() ) + { + rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() ); + if( xTemplate.is()) + setFirstDiagram( xTemplate->createDiagramByDataSource( xDataSource, aArguments ) ); + } + else + xDia->setDiagramData( xDataSource, aArguments ); + } + } + catch (const lang::IllegalArgumentException&) + { + throw; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + unlockControllers(); + } + setModified( true ); +} + +Sequence< OUString > SAL_CALL ChartModel::getUsedRangeRepresentations() +{ + return DataSourceHelper::getUsedDataRanges( this ); +} + +Reference< chart2::data::XDataSource > SAL_CALL ChartModel::getUsedData() +{ + return DataSourceHelper::getUsedData( *this ); +} + +Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighlighter() +{ + if( ! m_xRangeHighlighter.is()) + m_xRangeHighlighter.set( ChartModelHelper::createRangeHighlighter( this )); + return m_xRangeHighlighter; +} + +Reference<awt::XRequestCallback> SAL_CALL ChartModel::getPopupRequest() +{ + if (!m_xPopupRequest.is()) + m_xPopupRequest.set(new PopupRequest); + return m_xPopupRequest; +} + +rtl::Reference< ::chart::ChartTypeTemplate > ChartModel::impl_createDefaultChartTypeTemplate() +{ + rtl::Reference< ::chart::ChartTypeTemplate > xTemplate; + if( m_xChartTypeManager.is() ) + xTemplate = m_xChartTypeManager->createTemplate( "com.sun.star.chart2.template.Column" ); + return xTemplate; +} + +void SAL_CALL ChartModel::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + m_xChartTypeManager = dynamic_cast<::chart::ChartTypeManager*>(xNewManager.get()); + assert(!xNewManager || m_xChartTypeManager); + } + setModified( true ); +} + +uno::Reference< chart2::XChartTypeManager > SAL_CALL ChartModel::getChartTypeManager() +{ + MutexGuard aGuard( m_aModelMutex ); + return m_xChartTypeManager; +} + +uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getPageBackground() +{ + MutexGuard aGuard( m_aModelMutex ); + return m_xPageBackground; +} + +void SAL_CALL ChartModel::createDefaultChart() +{ + insertDefaultChart(); +} + +// ____ XTitled ____ +uno::Reference< chart2::XTitle > SAL_CALL ChartModel::getTitleObject() +{ + MutexGuard aGuard( m_aModelMutex ); + return m_xTitle; +} + +void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& xTitle ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + if( m_xTitle.is() ) + ModifyListenerHelper::removeListener( m_xTitle, this ); + m_xTitle = xTitle; + ModifyListenerHelper::addListener( m_xTitle, this ); + } + setModified( true ); +} + +// ____ XInterface (for old API wrapper) ____ +uno::Any SAL_CALL ChartModel::queryInterface( const uno::Type& aType ) +{ + uno::Any aResult( impl::ChartModel_Base::queryInterface( aType )); + + if( ! aResult.hasValue()) + { + // try old API wrapper + try + { + if( m_xOldModelAgg.is()) + aResult = m_xOldModelAgg->queryAggregation( aType ); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +// ____ XCloneable ____ +Reference< util::XCloneable > SAL_CALL ChartModel::createClone() +{ + return Reference< util::XCloneable >( new ChartModel( *this )); +} + +// ____ XVisualObject ____ +void SAL_CALL ChartModel::setVisualAreaSize( ::sal_Int64 nAspect, const awt::Size& aSize ) +{ + if( nAspect == embed::Aspects::MSOLE_CONTENT ) + { + ControllerLockGuard aLockGuard( *this ); + bool bChanged = + (m_aVisualAreaSize.Width != aSize.Width || + m_aVisualAreaSize.Height != aSize.Height); + + // #i12587# support for shapes in chart + if ( bChanged ) + { + impl_adjustAdditionalShapesPositionAndSize( aSize ); + } + + m_aVisualAreaSize = aSize; + if( bChanged ) + setModified( true ); + } + else + { + OSL_FAIL( "setVisualAreaSize: Aspect not implemented yet."); + } +} + +awt::Size SAL_CALL ChartModel::getVisualAreaSize( ::sal_Int64 nAspect ) +{ + OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT, + "No aspects other than content are supported" ); + // other possible aspects are MSOLE_THUMBNAIL, MSOLE_ICON and MSOLE_DOCPRINT + + return m_aVisualAreaSize; +} + +embed::VisualRepresentation SAL_CALL ChartModel::getPreferredVisualRepresentation( ::sal_Int64 nAspect ) +{ + OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT, + "No aspects other than content are supported" ); + + embed::VisualRepresentation aResult; + + try + { + Sequence< sal_Int8 > aMetafile; + + //get view from old api wrapper + Reference< datatransfer::XTransferable > xTransferable( + createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if( xTransferable.is() ) + { + datatransfer::DataFlavor aDataFlavor( lcl_aGDIMetaFileMIMEType, + "GDIMetaFile", + cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ); + + uno::Any aData( xTransferable->getTransferData( aDataFlavor ) ); + aData >>= aMetafile; + } + + aResult.Flavor.MimeType = lcl_aGDIMetaFileMIMEType; + aResult.Flavor.DataType = cppu::UnoType<decltype(aMetafile)>::get(); + + aResult.Data <<= aMetafile; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return aResult; +} + +::sal_Int32 SAL_CALL ChartModel::getMapUnit( ::sal_Int64 nAspect ) +{ + OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT, + "No aspects other than content are supported" ); + return embed::EmbedMapUnits::ONE_100TH_MM; +} + +// ____ datatransfer::XTransferable ____ +uno::Any SAL_CALL ChartModel::getTransferData( const datatransfer::DataFlavor& aFlavor ) +{ + uno::Any aResult; + if( !isDataFlavorSupported( aFlavor ) ) + throw datatransfer::UnsupportedFlavorException( + aFlavor.MimeType, static_cast< ::cppu::OWeakObject* >( this )); + + try + { + //get view from old api wrapper + Reference< datatransfer::XTransferable > xTransferable( + createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if( xTransferable.is() && + xTransferable->isDataFlavorSupported( aFlavor )) + { + aResult = xTransferable->getTransferData( aFlavor ); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return aResult; +} + +Sequence< datatransfer::DataFlavor > SAL_CALL ChartModel::getTransferDataFlavors() +{ + return { datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast, + "GDIMetaFile", + cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ) }; +} + +sal_Bool SAL_CALL ChartModel::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor ) +{ + return aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast; +} + +namespace +{ +enum eServiceType +{ + SERVICE_DASH_TABLE, + SERVICE_GRADIENT_TABLE, + SERVICE_HATCH_TABLE, + SERVICE_BITMAP_TABLE, + SERVICE_TRANSP_GRADIENT_TABLE, + SERVICE_MARKER_TABLE, + SERVICE_NAMESPACE_MAP +}; + +typedef std::map< OUString, enum eServiceType > tServiceNameMap; + +tServiceNameMap & lcl_getStaticServiceNameMap() +{ + static tServiceNameMap aServiceNameMap{ + {"com.sun.star.drawing.DashTable", SERVICE_DASH_TABLE}, + {"com.sun.star.drawing.GradientTable", SERVICE_GRADIENT_TABLE}, + {"com.sun.star.drawing.HatchTable", SERVICE_HATCH_TABLE}, + {"com.sun.star.drawing.BitmapTable", SERVICE_BITMAP_TABLE}, + {"com.sun.star.drawing.TransparencyGradientTable", SERVICE_TRANSP_GRADIENT_TABLE}, + {"com.sun.star.drawing.MarkerTable", SERVICE_MARKER_TABLE}, + {"com.sun.star.xml.NamespaceMap", SERVICE_NAMESPACE_MAP}}; + return aServiceNameMap; +} +} +// ____ XMultiServiceFactory ____ +Reference< uno::XInterface > SAL_CALL ChartModel::createInstance( const OUString& rServiceSpecifier ) +{ + tServiceNameMap & rMap = lcl_getStaticServiceNameMap(); + + tServiceNameMap::const_iterator aIt( rMap.find( rServiceSpecifier )); + if( aIt != rMap.end()) + { + switch( (*aIt).second ) + { + case SERVICE_DASH_TABLE: + case SERVICE_GRADIENT_TABLE: + case SERVICE_HATCH_TABLE: + case SERVICE_BITMAP_TABLE: + case SERVICE_TRANSP_GRADIENT_TABLE: + case SERVICE_MARKER_TABLE: + { + if(!mxChartView.is()) + { + mxChartView = new ChartView( m_xContext, *this); + } + return mxChartView->createInstance( rServiceSpecifier ); + } + break; + case SERVICE_NAMESPACE_MAP: + return static_cast<cppu::OWeakObject*>(m_xXMLNamespaceMap.get()); + } + } + else if(rServiceSpecifier == CHART_VIEW_SERVICE_NAME) + { + if(!mxChartView.is()) + { + mxChartView = new ChartView( m_xContext, *this); + } + + return static_cast< ::cppu::OWeakObject* >( mxChartView.get() ); + } + else + { + if( m_xOldModelAgg.is() ) + { + Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get()); + uno::Reference< lang::XMultiServiceFactory > xOldModelFactory; + if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() ) + { + return xOldModelFactory->createInstance( rServiceSpecifier ); + } + } + } + return nullptr; +} + +Reference< uno::XInterface > SAL_CALL ChartModel::createInstanceWithArguments( + const OUString& rServiceSpecifier , const Sequence< Any >& Arguments ) +{ + OSL_ENSURE( Arguments.hasElements(), "createInstanceWithArguments: Warning: Arguments are ignored" ); + return createInstance( rServiceSpecifier ); +} + +Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames() +{ + uno::Sequence< OUString > aResult; + + if( m_xOldModelAgg.is()) + { + Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get()); + uno::Reference< lang::XMultiServiceFactory > xOldModelFactory; + if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() ) + { + return xOldModelFactory->getAvailableServiceNames(); + } + } + return aResult; +} + +Reference< util::XNumberFormatsSupplier > const & ChartModel::getNumberFormatsSupplier() +{ + if( !m_xNumberFormatsSupplier.is() ) + { + if( !m_xOwnNumberFormatsSupplier.is() ) + { + m_apSvNumberFormatter.reset( new SvNumberFormatter( m_xContext, LANGUAGE_SYSTEM ) ); + m_xOwnNumberFormatsSupplier = new SvNumberFormatsSupplierObj( m_apSvNumberFormatter.get() ); + //pOwnNumberFormatter->ChangeStandardPrec( 15 ); todo? + } + m_xNumberFormatsSupplier = m_xOwnNumberFormatsSupplier; + } + return m_xNumberFormatsSupplier; +} + +// ____ XUnoTunnel ___ +::sal_Int64 SAL_CALL ChartModel::getSomething( const Sequence< ::sal_Int8 >& aIdentifier ) +{ + if( comphelper::isUnoTunnelId<SvNumberFormatsSupplierObj>(aIdentifier) ) + { + Reference< lang::XUnoTunnel > xTunnel( getNumberFormatsSupplier(), uno::UNO_QUERY ); + if( xTunnel.is() ) + return xTunnel->getSomething( aIdentifier ); + } + return 0; +} + +// ____ XNumberFormatsSupplier ____ +uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getNumberFormatSettings() +{ + Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() ); + if( xSupplier.is() ) + return xSupplier->getNumberFormatSettings(); + return uno::Reference< beans::XPropertySet >(); +} + +uno::Reference< util::XNumberFormats > SAL_CALL ChartModel::getNumberFormats() +{ + Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() ); + if( xSupplier.is() ) + return xSupplier->getNumberFormats(); + return uno::Reference< util::XNumberFormats >(); +} + +// ____ XChild ____ +Reference< uno::XInterface > SAL_CALL ChartModel::getParent() +{ + return Reference< uno::XInterface >(m_xParent,uno::UNO_QUERY); +} + +void SAL_CALL ChartModel::setParent( const Reference< uno::XInterface >& Parent ) +{ + if( Parent != m_xParent ) + m_xParent.set( Parent, uno::UNO_QUERY ); +} + +// ____ XDataSource ____ +uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ChartModel::getDataSequences() +{ + rtl::Reference< DataSource > xSource = DataSourceHelper::getUsedData( *this ); + if( xSource.is()) + return xSource->getDataSequences(); + + return uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >(); +} + +//XDumper +OUString SAL_CALL ChartModel::dump() +{ + uno::Reference< qa::XDumper > xDumper( + createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if (xDumper.is()) + return xDumper->dump(); + + return OUString(); +} + +void ChartModel::setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd) +{ + mnStart = nStart; + mnEnd = nEnd; + mbTimeBased = true; +} + +void ChartModel::update() +{ + if(!mxChartView.is()) + { + mxChartView = new ChartView( m_xContext, *this); + } + mxChartView->setViewDirty(); + mxChartView->update(); +} + +bool ChartModel::isDataFromSpreadsheet() +{ + return !isDataFromPivotTable() && !hasInternalDataProvider(); +} + +bool ChartModel::isDataFromPivotTable() const +{ + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(m_xDataProvider, uno::UNO_QUERY); + return xPivotTableDataProvider.is(); +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_ChartModel_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::ChartModel(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/ChartModel_Persistence.cxx b/chart2/source/model/main/ChartModel_Persistence.cxx new file mode 100644 index 000000000..f6f85e5f2 --- /dev/null +++ b/chart2/source/model/main/ChartModel_Persistence.cxx @@ -0,0 +1,808 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <ChartModel.hxx> +#include <MediaDescriptorHelper.hxx> +#include <ChartViewHelper.hxx> +#include <ChartModelHelper.hxx> +#include <ChartTypeManager.hxx> +#include <ChartTypeTemplate.hxx> +#include <DataSourceHelper.hxx> +#include <AxisHelper.hxx> +#include <ThreeDHelper.hxx> +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <BaseCoordinateSystem.hxx> +#include <Legend.hxx> +#include <XMLFilter.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/embed/StorageFactory.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/io/TempFile.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/ContentCreationException.hpp> + +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> + +#include <ucbhelper/content.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/cvtgrf.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/storagehelper.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> +#include <sfx2/objsh.hxx> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::osl::MutexGuard; + +namespace +{ +struct lcl_PropNameEquals +{ + explicit lcl_PropNameEquals( const OUString & rStrToCompareWith ) : + m_aStr( rStrToCompareWith ) + {} + bool operator() ( const beans::PropertyValue & rProp ) + { + return rProp.Name == m_aStr; + } +private: + OUString m_aStr; +}; + +template< typename T > +T lcl_getProperty( + const Sequence< beans::PropertyValue > & rMediaDescriptor, + const OUString & rPropName ) +{ + T aResult; + if( rMediaDescriptor.hasElements()) + { + const beans::PropertyValue * pIt = rMediaDescriptor.getConstArray(); + const beans::PropertyValue * pEndIt = pIt + + rMediaDescriptor.getLength(); + pIt = std::find_if( pIt, pEndIt, lcl_PropNameEquals( rPropName )); + if( pIt != pEndIt ) + (*pIt).Value >>= aResult; + } + return aResult; +} + +void lcl_addStorageToMediaDescriptor( + Sequence< beans::PropertyValue > & rOutMD, + const Reference< embed::XStorage > & xStorage ) +{ + rOutMD.realloc( rOutMD.getLength() + 1 ); + rOutMD.getArray()[rOutMD.getLength() - 1] = beans::PropertyValue( + "Storage", -1, uno::Any( xStorage ), beans::PropertyState_DIRECT_VALUE ); +} + +Reference< embed::XStorage > lcl_createStorage( + const OUString & rURL, + const Reference< uno::XComponentContext > & xContext, + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + // create new storage + Reference< embed::XStorage > xStorage; + if( !xContext.is()) + return xStorage; + + try + { + Reference< io::XStream > xStream( + ::ucbhelper::Content( rURL, Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext()).openStream(), + uno::UNO_QUERY ); + + Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) ); + Sequence< uno::Any > aStorageArgs{ uno::Any(xStream), + uno::Any(embed::ElementModes::READWRITE), + uno::Any(rMediaDescriptor) }; + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW ); + } + catch(const css::ucb::ContentCreationException&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + catch(const css::ucb::CommandFailedException&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xStorage; +} + +} // anonymous namespace + +namespace chart +{ + +Reference< document::XFilter > ChartModel::impl_createFilter( + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + Reference< document::XFilter > xFilter; + + // find FilterName in MediaDescriptor + OUString aFilterName( + lcl_getProperty< OUString >( rMediaDescriptor, "FilterName" ) ); + + // if FilterName was found, get Filter from factory + if( !aFilterName.isEmpty() ) + { + try + { + Reference< container::XNameAccess > xFilterFact( + m_xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.document.FilterFactory", m_xContext ), + uno::UNO_QUERY_THROW ); + uno::Any aFilterProps( xFilterFact->getByName( aFilterName )); + Sequence< beans::PropertyValue > aProps; + + if( aFilterProps.hasValue() && + (aFilterProps >>= aProps)) + { + OUString aFilterServiceName( + lcl_getProperty< OUString >( aProps, "FilterService" ) ); + + if( !aFilterServiceName.isEmpty()) + { + xFilter.set( + m_xContext->getServiceManager()->createInstanceWithContext( + aFilterServiceName, m_xContext ), uno::UNO_QUERY_THROW ); + SAL_INFO("chart2", "Filter found for service " << aFilterServiceName ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + OSL_ENSURE( xFilter.is(), "Filter not found via factory" ); + } + + // fall-back: create XML-Filter + if( ! xFilter.is()) + { + SAL_WARN("chart2", "No FilterName passed in MediaDescriptor" ); + xFilter = new XMLFilter(m_xContext); + } + + return xFilter; +} + +// frame::XStorable2 + +void SAL_CALL ChartModel::storeSelf( const Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + // only some parameters are allowed (see also SfxBaseModel) + // "VersionComment", "Author", "InteractionHandler", "StatusIndicator" + // However, they are ignored here. They would become interesting when + // charts support a standalone format again. + impl_store( rMediaDescriptor, m_xStorage ); +} + +// frame::XStorable (base of XStorable2) +sal_Bool SAL_CALL ChartModel::hasLocation() +{ + //@todo guard + return !m_aResource.isEmpty(); +} + +OUString SAL_CALL ChartModel::getLocation() +{ + return impl_g_getLocation(); +} + +sal_Bool SAL_CALL ChartModel::isReadonly() +{ + //@todo guard + return m_bReadOnly; +} + +void SAL_CALL ChartModel::store() +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall(true)) //start LongLastingCall + return; //behave passive if already disposed or closed or throw exception @todo? + + OUString aLocation = m_aResource; + + if( aLocation.isEmpty() ) + throw io::IOException( "no location specified", static_cast< ::cppu::OWeakObject* >(this)); + //@todo check whether aLocation is something like private:factory... + if( m_bReadOnly ) + throw io::IOException( "document is read only", static_cast< ::cppu::OWeakObject* >(this)); + + aGuard.clear(); + + // store + impl_store( m_aMediaDescriptor, m_xStorage ); +} + +void SAL_CALL ChartModel::storeAsURL( + const OUString& rURL, + const uno::Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall(true)) //start LongLastingCall + return; //behave passive if already disposed or closed or throw exception @todo? + + apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor); + uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor( + aMediaDescriptorHelper.getReducedForModel() ); + + m_bReadOnly = false; + aGuard.clear(); + + // create new storage + Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor )); + + if( xStorage.is()) + { + impl_store( aReducedMediaDescriptor, xStorage ); + attachResource( rURL, aReducedMediaDescriptor ); + } +} + +void SAL_CALL ChartModel::storeToURL( + const OUString& rURL, + const uno::Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall(true)) //start LongLastingCall + return; //behave passive if already disposed or closed or throw exception @todo? + //do not change the internal state of the document here + + aGuard.clear(); + + apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor); + uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor( + aMediaDescriptorHelper.getReducedForModel() ); + + if ( rURL == "private:stream" ) + { + try + { + if( m_xContext.is() && aMediaDescriptorHelper.ISSET_OutputStream ) + { + Reference< io::XStream > xStream( + io::TempFile::create(m_xContext), uno::UNO_QUERY_THROW ); + Reference< io::XInputStream > xInputStream( xStream->getInputStream()); + + Reference< embed::XStorage > xStorage( + ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE, m_xContext )); + if( xStorage.is()) + { + impl_store( aReducedMediaDescriptor, xStorage ); + + Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY_THROW ); + xSeekable->seek( 0 ); + ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, aMediaDescriptorHelper.OutputStream ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + else + { + // create new storage + Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor )); + + if( xStorage.is()) + impl_store( aReducedMediaDescriptor, xStorage ); + } +} + +void ChartModel::impl_store( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const Reference< embed::XStorage > & xStorage ) +{ + Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor)); + if( xFilter.is() && xStorage.is()) + { + Sequence< beans::PropertyValue > aMD( rMediaDescriptor ); + lcl_addStorageToMediaDescriptor( aMD, xStorage ); + try + { + Reference< document::XExporter > xExporter( xFilter, uno::UNO_QUERY_THROW ); + xExporter->setSourceDocument( Reference< lang::XComponent >( this )); + xFilter->filter( aMD ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + else + { + OSL_FAIL( "No filter" ); + } + + setModified( false ); + + //#i66865# + //for data change notification during chart is not loaded: + //notify parent data provider after saving thus the parent document can store + //the ranges for which a load and update of the chart will be necessary + Reference< beans::XPropertySet > xPropSet( m_xParent, uno::UNO_QUERY ); + if ( hasInternalDataProvider() || !xPropSet.is() ) + return; + + apphelper::MediaDescriptorHelper aMDHelper(rMediaDescriptor); + try + { + xPropSet->setPropertyValue( + "SavedObject", + uno::Any( aMDHelper.HierarchicalDocumentName ) ); + } + catch ( const uno::Exception& ) + { + } +} + +void ChartModel::insertDefaultChart() +{ + lockControllers(); + createInternalDataProvider( false ); + try + { + // create default chart + rtl::Reference< ::chart::ChartTypeTemplate > 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 = { beans::PropertyValue( "HasCategories", -1, uno::Any( true ), + beans::PropertyState_DIRECT_VALUE ) }; + } + + rtl::Reference< Diagram > xDiagram( xTemplate->createDiagramByDataSource2( xDataSource, aParam ) ); + + setFirstDiagram( xDiagram ); + + bool bIsRTL = AllSettings::GetMathLayoutRTL(); + //reverse x axis for rtl charts + if( bIsRTL ) + AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); + + // create and attach legend + rtl::Reference< Legend > xLegend = new Legend(); + xLegend->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE )); + xLegend->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE )); + xLegend->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30 + xLegend->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + + if( bIsRTL ) + xLegend->setPropertyValue( "AnchorPosition", uno::Any( chart2::LegendPosition_LINE_START )); + if(xDiagram.is()) + xDiagram->setLegend( xLegend ); + + // set simple 3D look + if( xDiagram.is() ) + { + xDiagram->setPropertyValue( "RightAngledAxes", uno::Any( true )); + xDiagram->setPropertyValue( "D3DScenePerspective", uno::Any( drawing::ProjectionMode_PARALLEL )); + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme::ThreeDLookScheme_Realistic ); + } + + //set some new 'defaults' for wall and floor + if( xDiagram.is() ) + { + Reference< beans::XPropertySet > xWall( xDiagram->getWall() ); + if( xWall.is() ) + { + xWall->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) ); + xWall->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE ) ); + xWall->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + xWall->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + } + Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() ); + if( xFloor.is() ) + { + xFloor->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ) ); + xFloor->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_SOLID ) ); + xFloor->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + xFloor->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20 + } + + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + ChartModelHelper::setIncludeHiddenCells( false, *this ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + setModified( false ); + unlockControllers(); +} + +// frame::XLoadable +void SAL_CALL ChartModel::initNew() +{ +} + +void SAL_CALL ChartModel::load( + const Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + Reference< embed::XStorage > xStorage; + OUString aURL; + try + { + apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor ); + if( aMDHelper.ISSET_Storage ) + { + xStorage = aMDHelper.Storage; + } + else if( aMDHelper.ISSET_Stream || + aMDHelper.ISSET_InputStream ) + { + if( aMDHelper.ISSET_FilterName && + (aMDHelper.FilterName == "StarChart 5.0" || + aMDHelper.FilterName == "StarChart 4.0" || + aMDHelper.FilterName == "StarChart 3.0" )) + { + attachResource( aMDHelper.URL, rMediaDescriptor ); + impl_load( rMediaDescriptor, nullptr ); // cannot create a storage from binary streams, but I do not need the storage here anyhow + m_bReadOnly = true; + return; + } + + Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create(m_xContext) ); + + if( aMDHelper.ISSET_Stream ) + { + // convert XStream to XStorage via the storage factory + Sequence< uno::Any > aStorageArgs{ uno::Any(aMDHelper.Stream), + // todo: check if stream is read-only + uno::Any(embed::ElementModes::READ) }; //WRITE | embed::ElementModes::NOCREATE); + + xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + else + { + OSL_ASSERT( aMDHelper.ISSET_InputStream ); + // convert XInputStream to XStorage via the storage factory + Sequence< uno::Any > aStorageArgs{ uno::Any(aMDHelper.InputStream), + uno::Any(embed::ElementModes::READ) }; + + xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + } + + if( aMDHelper.ISSET_URL ) + aURL = aMDHelper.URL; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + if( xStorage.is()) + { + attachResource( aURL, rMediaDescriptor ); + impl_load( rMediaDescriptor, xStorage ); + } +} + +void ChartModel::impl_load( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const Reference< embed::XStorage >& xStorage ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + m_nInLoad++; + } + + Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor )); + + if( xFilter.is()) + { + Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY_THROW ); + xImporter->setTargetDocument( this ); + Sequence< beans::PropertyValue > aMD( rMediaDescriptor ); + lcl_addStorageToMediaDescriptor( aMD, xStorage ); + + xFilter->filter( aMD ); + xFilter.clear(); + } + else + { + OSL_FAIL( "loadFromStorage cannot create filter" ); + } + + if( xStorage.is() ) + impl_loadGraphics( xStorage ); + + setModified( false ); + + // switchToStorage without notifying listeners (which shouldn't exist at + // this time, anyway) + m_xStorage = xStorage; + + { + MutexGuard aGuard( m_aModelMutex ); + m_nInLoad--; + } +} + +void ChartModel::impl_loadGraphics( + const Reference< embed::XStorage >& xStorage ) +{ + try + { + const Reference< embed::XStorage >& xGraphicsStorage( + xStorage->openStorageElement( "Pictures", + embed::ElementModes::READ ) ); + + if( xGraphicsStorage.is() ) + { + const uno::Sequence< OUString > aElementNames( + xGraphicsStorage->getElementNames() ); + + for( OUString const & streamName : aElementNames ) + { + if( xGraphicsStorage->isStreamElement( streamName ) ) + { + uno::Reference< io::XStream > xElementStream( + xGraphicsStorage->openStreamElement( + streamName, + embed::ElementModes::READ ) ); + + if( xElementStream.is() ) + { + std::unique_ptr< SvStream > apIStm( + ::utl::UcbStreamHelper::CreateStream( + xElementStream, true ) ); + + if (apIStm) + { + SolarMutexGuard aGuard; + Graphic aGraphic; + if (!GraphicConverter::Import(*apIStm, aGraphic)) + { + m_aGraphicObjectVector.emplace_back(aGraphic ); + } + } + } + } + } + } + } + catch ( const uno::Exception& ) + { + } +} + +// util::XModifiable +void ChartModel::impl_notifyModifiedListeners() +{ + { + MutexGuard aGuard( m_aModelMutex ); + m_bUpdateNotificationsPending = false; + } + + //always notify the view first! + ChartViewHelper::setViewToDirtyState( this ); + + ::comphelper::OInterfaceContainerHelper2* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType<util::XModifyListener>::get()); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent*>(this) ); + ::comphelper::OInterfaceIteratorHelper2 aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + static_cast< util::XModifyListener* >( aIt.next() )->modified( aEvent ); + } + } +} + +sal_Bool SAL_CALL ChartModel::isModified() +{ + //@todo guard + return m_bModified; +} + +void SAL_CALL ChartModel::setModified( sal_Bool bModified ) +{ + // tdf#141914: allow to set *unmodified* when parent does not allow to set modified + if (bModified) + { + // tdf#77007: honor parent's IsEnableSetModified + // Check it before LifeTimeGuard, to avoid deadlocking solar mutex and this guard + if (auto pParentShell = SfxObjectShell::GetShellFromComponent(getParent()); + pParentShell && !pParentShell->IsEnableSetModified()) + return; + } + + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall())//@todo ? is this a long lasting call?? + return; //behave passive if already disposed or closed or throw exception @todo? + m_bModified = bModified; + + if( m_nControllerLockCount > 0 ) + { + m_bUpdateNotificationsPending = true; + return;//don't call listeners if controllers are locked + } + aGuard.clear(); + + if(bModified) + impl_notifyModifiedListeners(); +} + +// util::XModifyBroadcaster (base of XModifiable) +void SAL_CALL ChartModel::addModifyListener( + const uno::Reference< util::XModifyListener >& xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.addInterface( + cppu::UnoType<util::XModifyListener>::get(), xListener ); +} + +void SAL_CALL ChartModel::removeModifyListener( + const uno::Reference< util::XModifyListener >& xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( + cppu::UnoType<util::XModifyListener>::get(), xListener ); +} + +// util::XModifyListener +void SAL_CALL ChartModel::modified( const lang::EventObject& rEvenObject) +{ + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rEvenObject.Source, uno::UNO_QUERY); + if (xPivotTableDataProvider.is()) + { + lockControllers(); + uno::Reference<chart2::data::XDataProvider> xDataProvider(xPivotTableDataProvider, uno::UNO_QUERY); + try + { + uno::Sequence<beans::PropertyValue> aArguments = + DataSourceHelper::createArguments("PivotChart", uno::Sequence<sal_Int32>(), true, true, true); + + Reference<chart2::data::XDataSource> xDataSource(xDataProvider->createDataSource(aArguments)); + rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = getTypeManager(); + rtl::Reference<Diagram> xDiagram(getFirstChartDiagram()); + + DiagramHelper::tTemplateWithServiceName aTemplateAndService = DiagramHelper::getTemplateForDiagram(xDiagram, xChartTypeManager); + aTemplateAndService.xChartTypeTemplate->changeDiagramData(xDiagram, xDataSource, aArguments); + } + catch (const uno::Exception &) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + unlockControllers(); + } + + if (m_nInLoad == 0) + setModified(true); +} + +// lang::XEventListener (base of util::XModifyListener) +void SAL_CALL ChartModel::disposing( const lang::EventObject& ) +{ + // child was disposed -- should not happen from outside +} + +// document::XStorageBasedDocument +void SAL_CALL ChartModel::loadFromStorage( + const Reference< embed::XStorage >& xStorage, + const Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + attachResource( OUString(), rMediaDescriptor ); + impl_load( rMediaDescriptor, xStorage ); +} + +void SAL_CALL ChartModel::storeToStorage( + const Reference< embed::XStorage >& xStorage, + const Sequence< beans::PropertyValue >& rMediaDescriptor ) +{ + impl_store( rMediaDescriptor, xStorage ); +} + +void SAL_CALL ChartModel::switchToStorage( const Reference< embed::XStorage >& xStorage ) +{ + m_xStorage = xStorage; + impl_notifyStorageChangeListeners(); +} + +Reference< embed::XStorage > SAL_CALL ChartModel::getDocumentStorage() +{ + return m_xStorage; +} + +void ChartModel::impl_notifyStorageChangeListeners() +{ + ::comphelper::OInterfaceContainerHelper2* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType<document::XStorageChangeListener>::get()); + if( pIC ) + { + ::comphelper::OInterfaceIteratorHelper2 aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + static_cast< document::XStorageChangeListener* >( aIt.next() ) + ->notifyStorageChange( static_cast< ::cppu::OWeakObject* >( this ), m_xStorage ); + } + } +} + +void SAL_CALL ChartModel::addStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.addInterface( + cppu::UnoType<document::XStorageChangeListener>::get(), xListener ); +} + +void SAL_CALL ChartModel::removeStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener ) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( + cppu::UnoType<document::XStorageChangeListener>::get(), xListener ); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataPoint.cxx b/chart2/source/model/main/DataPoint.cxx new file mode 100644 index 000000000..a5838c91f --- /dev/null +++ b/chart2/source/model/main/DataPoint.cxx @@ -0,0 +1,278 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DataPoint.hxx" +#include "DataPointProperties.hxx" +#include <CharacterProperties.hxx> +#include <UserDefinedProperties.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticDataPointInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + ::chart::DataPointProperties::AddPropertiesToVector( aProperties ); + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticDataPointInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticDataPointInfoHelper_Initializer > +{ +}; + +struct StaticDataPointInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticDataPointInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticDataPointInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticDataPointInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +DataPoint::DataPoint( const uno::Reference< beans::XPropertySet > & rParentProperties ) : + ::property::OPropertySet( m_aMutex ), + m_xParentProperties( rParentProperties ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_bNoParentPropAllowed( false ) +{ + SetNewValuesExplicitlyEvenIfTheyEqualDefault(); +} + +DataPoint::DataPoint( const DataPoint & rOther ) : + impl::DataPoint_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_bNoParentPropAllowed( true ) +{ + SetNewValuesExplicitlyEvenIfTheyEqualDefault(); + + // m_xParentProperties has to be set from outside, like in the method + // DataSeries::createClone + + // add as listener to XPropertySet properties + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); + + m_bNoParentPropAllowed = false; +} + +DataPoint::~DataPoint() +{ + try + { + // remove listener from XPropertySet properties + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder ); + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL DataPoint::createClone() +{ + return uno::Reference< util::XCloneable >( new DataPoint( *this )); +} + +// ____ XChild ____ +Reference< uno::XInterface > SAL_CALL DataPoint::getParent() +{ + return Reference< uno::XInterface >( m_xParentProperties.get(), uno::UNO_QUERY ); +} + +void SAL_CALL DataPoint::setParent( + const Reference< uno::XInterface >& Parent ) +{ + m_xParentProperties = Reference< beans::XPropertySet >( Parent, uno::UNO_QUERY ); +} + +// ____ OPropertySet ____ +void DataPoint::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + // the value set at the data series is the default + uno::Reference< beans::XFastPropertySet > xFast( m_xParentProperties.get(), uno::UNO_QUERY ); + if( !xFast.is()) + { + OSL_ENSURE( m_bNoParentPropAllowed, "data point needs a parent property set to provide values correctly" ); + rAny.clear(); + return; + } + + rAny = xFast->getFastPropertyValue( nHandle ); +} + +void SAL_CALL DataPoint::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, const uno::Any& rValue ) +{ + if( nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y + || nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ) + { + uno::Any aOldValue; + Reference< util::XModifyBroadcaster > xBroadcaster; + getFastPropertyValue( aOldValue, nHandle ); + if( aOldValue.hasValue() && + (aOldValue >>= xBroadcaster) && + xBroadcaster.is()) + { + ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder ); + } + + OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE ); + if( rValue.hasValue() && + (rValue >>= xBroadcaster) && + xBroadcaster.is()) + { + ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder ); + } + } + + ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue ); +} + +::cppu::IPropertyArrayHelper & SAL_CALL DataPoint::getInfoHelper() +{ + return *StaticDataPointInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL DataPoint::getPropertySetInfo() +{ + return *StaticDataPointInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL DataPoint::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL DataPoint::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL DataPoint::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL DataPoint::disposing( const lang::EventObject& ) +{ + // nothing +} + +// ____ OPropertySet ____ +void DataPoint::firePropertyChangeEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// needed by MSC compiler +using impl::DataPoint_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( DataPoint, DataPoint_Base, ::property::OPropertySet ) + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL DataPoint::getImplementationName() +{ + return "com.sun.star.comp.chart.DataPoint" ; +} + +sal_Bool SAL_CALL DataPoint::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL DataPoint::getSupportedServiceNames() +{ + return { + "com.sun.star.drawing.FillProperties", + "com.sun.star.chart2.DataPoint", + "com.sun.star.chart2.DataPointProperties", + "com.sun.star.beans.PropertySet" + }; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataPoint.hxx b/chart2/source/model/main/DataPoint.hxx new file mode 100644 index 000000000..52feb197d --- /dev/null +++ b/chart2/source/model/main/DataPoint.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/weakref.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <OPropertySet.hxx> +#include <ModifyListenerHelper.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::container::XChild, + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener, + css::lang::XServiceInfo > + DataPoint_Base; +} + +class DataPoint final : + public cppu::BaseMutex, + public impl::DataPoint_Base, + public ::property::OPropertySet +{ +public: + explicit DataPoint( const css::uno::Reference< css::beans::XPropertySet > & rParentProperties ); + virtual ~DataPoint() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// XServiceInfo declarations + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +private: + explicit DataPoint( const DataPoint & rOther ); + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast + ( sal_Int32 nHandle, + const css::uno::Any& rValue ) override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + // Note: m_xParentProperties are not cloned! + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + // ____ XChild ____ + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override; + virtual void SAL_CALL setParent( + const css::uno::Reference< css::uno::XInterface >& Parent ) override; + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const css::lang::EventObject& aEvent ) override; + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const css::lang::EventObject& Source ) override; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + css::uno::WeakReference< css::beans::XPropertySet > m_xParentProperties; + + rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder; + bool m_bNoParentPropAllowed; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataPointProperties.cxx b/chart2/source/model/main/DataPointProperties.cxx new file mode 100644 index 000000000..267bf9014 --- /dev/null +++ b/chart2/source/model/main/DataPointProperties.cxx @@ -0,0 +1,542 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DataPointProperties.hxx" +#include <LinePropertiesHelper.hxx> +#include <FillProperties.hxx> +#include <unonames.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/LineCap.hpp> +#include <com/sun/star/drawing/BitmapMode.hpp> +#include <com/sun/star/drawing/RectanglePoint.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp> +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/Symbol.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace chart +{ + +void DataPointProperties::AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + // DataPointProperties + + // Common + + rOutProperties.emplace_back( "Color", + PROP_DATAPOINT_COLOR, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillColor", + PROP_DATAPOINT_COLOR, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Transparency", + PROP_DATAPOINT_TRANSPARENCY, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillTransparence", + PROP_DATAPOINT_TRANSPARENCY, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // Fill Properties + rOutProperties.emplace_back( "FillStyle", + PROP_DATAPOINT_FILL_STYLE, + cppu::UnoType<drawing::FillStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TransparencyGradientName", + PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillTransparenceGradientName", + PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GradientName", + PROP_DATAPOINT_GRADIENT_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillGradientName", + PROP_DATAPOINT_GRADIENT_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GradientStepCount", + PROP_DATAPOINT_GRADIENT_STEPCOUNT, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillGradientStepCount", + PROP_DATAPOINT_GRADIENT_STEPCOUNT, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HatchName", + PROP_DATAPOINT_HATCH_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillHatchName", + PROP_DATAPOINT_HATCH_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillBitmapName", + PROP_DATAPOINT_FILL_BITMAP_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillBackground", + PROP_DATAPOINT_FILL_BACKGROUND, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + // border for filled objects + rOutProperties.emplace_back( "BorderColor", + PROP_DATAPOINT_BORDER_COLOR, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "BorderStyle", + PROP_DATAPOINT_BORDER_STYLE, + cppu::UnoType<drawing::LineStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "BorderWidth", + PROP_DATAPOINT_BORDER_WIDTH, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "BorderDashName", + PROP_DATAPOINT_BORDER_DASH_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "BorderTransparency", + PROP_DATAPOINT_BORDER_TRANSPARENCY, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Line Properties + + rOutProperties.emplace_back( "LineColor", + PROP_DATAPOINT_BORDER_COLOR, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineStyle", + LinePropertiesHelper::PROP_LINE_STYLE, + cppu::UnoType<drawing::LineStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineWidth", + LinePropertiesHelper::PROP_LINE_WIDTH, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineDash", + LinePropertiesHelper::PROP_LINE_DASH, + cppu::UnoType<drawing::LineDash>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineDashName", + LinePropertiesHelper::PROP_LINE_DASH_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineTransparence", + PROP_DATAPOINT_BORDER_TRANSPARENCY, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineCap", + ::chart::LinePropertiesHelper::PROP_LINE_CAP, + cppu::UnoType<drawing::LineCap>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // FillProperties + // bitmap properties + rOutProperties.emplace_back( "FillBitmapOffsetX", + FillProperties::PROP_FILL_BITMAP_OFFSETX, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapOffsetY", + FillProperties::PROP_FILL_BITMAP_OFFSETY, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapPositionOffsetX", + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapPositionOffsetY", + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapRectanglePoint", + FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, + cppu::UnoType<drawing::RectanglePoint>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapLogicalSize", + FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapSizeX", + FillProperties::PROP_FILL_BITMAP_SIZEX, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapSizeY", + FillProperties::PROP_FILL_BITMAP_SIZEY, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapMode", + FillProperties::PROP_FILL_BITMAP_MODE, + cppu::UnoType<drawing::BitmapMode>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // others + rOutProperties.emplace_back( "Symbol", + PROP_DATAPOINT_SYMBOL_PROP, + cppu::UnoType<chart2::Symbol>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Offset", + PROP_DATAPOINT_OFFSET, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Geometry3D", + PROP_DATAPOINT_GEOMETRY3D, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_DATAPOINT_NUMBER_FORMAT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT, + PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //additional 'PercentageNumberFormat' + rOutProperties.emplace_back( "PercentageNumberFormat", + PROP_DATAPOINT_PERCENTAGE_NUMBER_FORMAT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LabelPlacement", + PROP_DATAPOINT_LABEL_PLACEMENT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE, + cppu::UnoType<awt::Size>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "TextRotation", + PROP_DATAPOINT_TEXT_ROTATION, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // statistics + rOutProperties.emplace_back( CHART_UNONAME_ERRORBAR_X, + PROP_DATAPOINT_ERROR_BAR_X, + // XPropertySet supporting service ErrorBar + cppu::UnoType<beans::XPropertySet>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_ERRORBAR_Y, + PROP_DATAPOINT_ERROR_BAR_Y, + // XPropertySet supporting service ErrorBar + cppu::UnoType<beans::XPropertySet>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ShowErrorBox", + PROP_DATAPOINT_SHOW_ERROR_BOX, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "PercentDiagonal", + PROP_DATAPOINT_PERCENT_DIAGONAL, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Properties specific to data label. + + rOutProperties.emplace_back( CHART_UNONAME_LABEL, + PROP_DATAPOINT_LABEL, + cppu::UnoType<chart2::DataPointLabel>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextWordWrap", + PROP_DATAPOINT_TEXT_WORD_WRAP, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_SEP, + PROP_DATAPOINT_LABEL_SEPARATOR, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_STYLE, + PROP_DATAPOINT_LABEL_BORDER_STYLE, + cppu::UnoType<drawing::LineStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_COLOR, + PROP_DATAPOINT_LABEL_BORDER_COLOR, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_STYLE, + PROP_DATAPOINT_LABEL_FILL_STYLE, + cppu::UnoType<drawing::FillStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_COLOR, + PROP_DATAPOINT_LABEL_FILL_COLOR, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_BACKGROUND, + PROP_DATAPOINT_LABEL_FILL_BACKGROUND, + cppu::UnoType<sal_Bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_HATCH_NAME, + PROP_DATAPOINT_LABEL_FILL_HATCH_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_WIDTH, + PROP_DATAPOINT_LABEL_BORDER_WIDTH, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_DASH, + PROP_DATAPOINT_LABEL_BORDER_DASH, + cppu::UnoType<drawing::LineDash>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_DASHNAME, + PROP_DATAPOINT_LABEL_BORDER_DASH_NAME, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_TRANS, + PROP_DATAPOINT_LABEL_BORDER_TRANS, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_CUSTOM_LABEL_FIELDS, + PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, + cppu::UnoType<uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>>>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( "CustomLabelPosition", + PROP_DATAPOINT_LABEL_CUSTOM_POS, + cppu::UnoType<chart2::RelativePosition>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +void DataPointProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DATAPOINT_COLOR, 0x0099ccff ); // blue 8 + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_DATAPOINT_TRANSPARENCY, 0 ); + + //fill + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_FILL_STYLE, drawing::FillStyle_SOLID ); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME ); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_GRADIENT_NAME ); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_HATCH_NAME ); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_FILL_BITMAP_NAME ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_FILL_BACKGROUND, false ); + + //border + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DATAPOINT_BORDER_COLOR, 0x000000 ); // black + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_STYLE, drawing::LineStyle_SOLID ); // drawing::LineStyle_NONE + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DATAPOINT_BORDER_WIDTH, 0 ); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_DASH_NAME ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_DATAPOINT_BORDER_TRANSPARENCY, 0 ); + + //line + PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_SOLID ); + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, LinePropertiesHelper::PROP_LINE_WIDTH, 0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_DASH, drawing::LineDash()); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_DASH_NAME ); + PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_CAP, drawing::LineCap_BUTT); + + //fill bitmap + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, 0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, drawing::RectanglePoint_MIDDLE_MIDDLE ); + PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, true ); + + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, 0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_MODE, drawing::BitmapMode_REPEAT ); + + //others + chart2::Symbol aSymbProp; + aSymbProp.Style = chart2::SymbolStyle_NONE; + aSymbProp.StandardSymbol = 0; + aSymbProp.Size = awt::Size( 250, 250 ); // ca. 7pt x 7pt (7pt=246.94) + aSymbProp.BorderColor = 0x000000; // Black + aSymbProp.FillColor = 0xee4000; // OrangeRed2 + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_SYMBOL_PROP, aSymbProp ); + + PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_DATAPOINT_OFFSET, 0.0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_GEOMETRY3D, chart2::DataPointGeometry3D::CUBOID ); + + //@todo maybe choose a different one here -> should be dynamically that of the attached axis + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_ERROR_BAR_X, uno::Reference< beans::XPropertySet >()); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_ERROR_BAR_Y, uno::Reference< beans::XPropertySet >()); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_DATAPOINT_PERCENT_DIAGONAL, 0 ); + + PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_DATAPOINT_TEXT_ROTATION, 0.0 ); + + PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE, true); + + // data label + PropertyHelper::setPropertyValueDefault( + rOutMap, PROP_DATAPOINT_LABEL, + chart2::DataPointLabel( + false, // ShowNumber + false, // ShowNumberInPercent + false, // ShowCategoryName + false, // ShowLegendSymbol + false, // ShowCustomLabel + false // ShowSeriesName + )); + + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TEXT_WORD_WRAP, false ); + PropertyHelper::setPropertyValueDefault< OUString >( rOutMap, PROP_DATAPOINT_LABEL_SEPARATOR, " " ); + PropertyHelper::setPropertyValueDefault<sal_Int32>(rOutMap, PROP_DATAPOINT_LABEL_BORDER_STYLE, sal_Int32(drawing::LineStyle_NONE)); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_COLOR); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_STYLE); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_COLOR); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_BACKGROUND); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_HATCH_NAME); + PropertyHelper::setPropertyValueDefault<sal_Int32>(rOutMap, PROP_DATAPOINT_LABEL_BORDER_WIDTH, 0); + PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH, drawing::LineDash()); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH_NAME); + PropertyHelper::setPropertyValueDefault<sal_Int16>(rOutMap, PROP_DATAPOINT_LABEL_BORDER_TRANS, 0); + + uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields(0); + PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, aFields); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataPointProperties.hxx b/chart2/source/model/main/DataPointProperties.hxx new file mode 100644 index 000000000..ada7907b8 --- /dev/null +++ b/chart2/source/model/main/DataPointProperties.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <PropertyHelper.hxx> +#include <FastPropertyIdRanges.hxx> + +#include <vector> + +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ + +// implements service DataPointProperties +namespace DataPointProperties +{ + // FastProperty Ids for properties + enum + { + PROP_DATAPOINT_LABEL_FILL_STYLE, + PROP_DATAPOINT_LABEL_FILL_COLOR, + PROP_DATAPOINT_LABEL_FILL_BACKGROUND, + PROP_DATAPOINT_LABEL_FILL_HATCH_NAME, + + // common + PROP_DATAPOINT_COLOR = FAST_PROPERTY_ID_START_DATA_POINT, + PROP_DATAPOINT_TRANSPARENCY, + + // fill + PROP_DATAPOINT_FILL_STYLE, + PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME, + PROP_DATAPOINT_GRADIENT_NAME, + PROP_DATAPOINT_GRADIENT_STEPCOUNT, + PROP_DATAPOINT_HATCH_NAME, + PROP_DATAPOINT_FILL_BITMAP_NAME, + PROP_DATAPOINT_FILL_BACKGROUND, + + // border (of filled objects) + PROP_DATAPOINT_BORDER_COLOR, + PROP_DATAPOINT_BORDER_STYLE, + PROP_DATAPOINT_BORDER_WIDTH, + PROP_DATAPOINT_BORDER_DASH_NAME, + PROP_DATAPOINT_BORDER_TRANSPARENCY, + + // others + PROP_DATAPOINT_SYMBOL_PROP, + PROP_DATAPOINT_OFFSET, + PROP_DATAPOINT_GEOMETRY3D, + PROP_DATAPOINT_NUMBER_FORMAT, + PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE, + PROP_DATAPOINT_PERCENTAGE_NUMBER_FORMAT, + PROP_DATAPOINT_LABEL_PLACEMENT, + PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE, + PROP_DATAPOINT_TEXT_ROTATION, + + // statistics + PROP_DATAPOINT_ERROR_BAR_X, + PROP_DATAPOINT_ERROR_BAR_Y, + PROP_DATAPOINT_SHOW_ERROR_BOX, + PROP_DATAPOINT_PERCENT_DIAGONAL, + + // label + PROP_DATAPOINT_LABEL, + PROP_DATAPOINT_LABEL_SEPARATOR, + PROP_DATAPOINT_TEXT_WORD_WRAP, + PROP_DATAPOINT_LABEL_BORDER_STYLE, + PROP_DATAPOINT_LABEL_BORDER_COLOR, + PROP_DATAPOINT_LABEL_BORDER_WIDTH, + PROP_DATAPOINT_LABEL_BORDER_DASH, + PROP_DATAPOINT_LABEL_BORDER_DASH_NAME, + PROP_DATAPOINT_LABEL_BORDER_TRANS, + PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, + PROP_DATAPOINT_LABEL_CUSTOM_POS + + // additionally some properties from ::chart::LineProperties + }; + + void AddPropertiesToVector( + std::vector< css::beans::Property > & rOutProperties ); + + void AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataSeries.cxx b/chart2/source/model/main/DataSeries.cxx new file mode 100644 index 000000000..b54fa3897 --- /dev/null +++ b/chart2/source/model/main/DataSeries.cxx @@ -0,0 +1,566 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <DataSeries.hxx> +#include "DataSeriesProperties.hxx" +#include "DataPointProperties.hxx" +#include <CharacterProperties.hxx> +#include <UserDefinedProperties.hxx> +#include "DataPoint.hxx" +#include <DataSeriesHelper.hxx> +#include <CloneHelper.hxx> +#include <RegressionCurveModel.hxx> +#include <ModifyListenerHelper.hxx> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/ref.hxx> + +#include <algorithm> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::osl::MutexGuard; + +namespace +{ + +struct StaticDataSeriesDefaults : public rtl::StaticWithInit< ::chart::tPropertyValueMap, StaticDataSeriesDefaults > +{ + ::chart::tPropertyValueMap operator()() + { + ::chart::tPropertyValueMap aStaticDefaults; + ::chart::DataSeriesProperties::AddDefaultsToMap( aStaticDefaults ); + ::chart::CharacterProperties::AddDefaultsToMap( aStaticDefaults ); + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + return aStaticDefaults; + } +}; + +struct StaticDataSeriesInfoHelper : public rtl::StaticWithInit< ::cppu::OPropertyArrayHelper, StaticDataSeriesInfoHelper, StaticDataSeriesInfoHelper, uno::Sequence< Property > > +{ + uno::Sequence< Property > operator()() + { + std::vector< css::beans::Property > aProperties; + ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties ); + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticDataSeriesInfo : public rtl::StaticWithInit< uno::Reference< beans::XPropertySetInfo >, StaticDataSeriesInfo > +{ + uno::Reference< beans::XPropertySetInfo > operator()() + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper::get() ); + } +}; + +void lcl_SetParent( + const uno::Reference< uno::XInterface > & xChildInterface, + const uno::Reference< uno::XInterface > & xParentInterface ) +{ + uno::Reference< container::XChild > xChild( xChildInterface, uno::UNO_QUERY ); + if( xChild.is()) + xChild->setParent( xParentInterface ); +} + +typedef std::map< sal_Int32, css::uno::Reference< css::beans::XPropertySet > > + lcl_tDataPointMap; + +void lcl_CloneAttributedDataPoints( + const lcl_tDataPointMap & rSource, lcl_tDataPointMap & rDestination, + const uno::Reference< uno::XInterface > & xSeries ) +{ + for (auto const& elem : rSource) + { + Reference< beans::XPropertySet > xPoint( elem.second ); + if( xPoint.is()) + { + Reference< util::XCloneable > xCloneable( xPoint, uno::UNO_QUERY ); + if( xCloneable.is()) + { + xPoint.set( xCloneable->createClone(), uno::UNO_QUERY ); + if( xPoint.is()) + { + lcl_SetParent( xPoint, xSeries ); + rDestination.emplace( elem.first, xPoint ); + } + } + } + } +} + +} // anonymous namespace + +namespace chart +{ + +DataSeries::DataSeries() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ +} + +DataSeries::DataSeries( const DataSeries & rOther ) : + impl::DataSeries_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ + if( ! rOther.m_aDataSequences.empty()) + { + CloneHelper::CloneRefVector(rOther.m_aDataSequences, m_aDataSequences ); + ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder ); + } + + CloneHelper::CloneRefVector( rOther.m_aRegressionCurves, m_aRegressionCurves ); + ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves, m_xModifyEventForwarder ); + + // add as listener to XPropertySet properties + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); +} + +// late initialization to call after copy-constructing +void DataSeries::Init( const DataSeries & rOther ) +{ + Reference< uno::XInterface > xThisInterface( static_cast< ::cppu::OWeakObject * >( this )); + if( ! rOther.m_aAttributedDataPoints.empty()) + { + lcl_CloneAttributedDataPoints( + rOther.m_aAttributedDataPoints, m_aAttributedDataPoints, xThisInterface ); + ModifyListenerHelper::addListenerToAllMapElements( m_aAttributedDataPoints, m_xModifyEventForwarder ); + } + + // add as parent to error bars + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + lcl_SetParent( xPropertySet, xThisInterface ); + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + lcl_SetParent( xPropertySet, xThisInterface ); +} + +DataSeries::~DataSeries() +{ + try + { + ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints, m_xModifyEventForwarder ); + ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves, m_xModifyEventForwarder ); + ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder ); + + // remove listener from XPropertySet properties + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder ); + + getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL DataSeries::createClone() +{ + rtl::Reference<DataSeries> pNewSeries( new DataSeries( *this )); + // do initialization that uses uno references to the clone + pNewSeries->Init( *this ); + + return pNewSeries; +} + +// ____ OPropertySet ____ +void DataSeries::GetDefaultValue( sal_Int32 nHandle, uno::Any& rDest ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticDataSeriesDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rDest.clear(); + else + rDest = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper() +{ + return StaticDataSeriesInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo() +{ + return StaticDataSeriesInfo::get(); +} + +void SAL_CALL DataSeries::getFastPropertyValue + ( uno::Any& rValue, + sal_Int32 nHandle ) const +{ + // special handling for get. set is not possible for this property + if( nHandle == DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) + { + // TODO: only add those property sets that are really modified + + rValue <<= comphelper::mapKeysToSequence(m_aAttributedDataPoints); + } + else + OPropertySet::getFastPropertyValue( rValue, nHandle ); +} + +void SAL_CALL DataSeries::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, const uno::Any& rValue ) +{ + if( nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y + || nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X ) + { + uno::Any aOldValue; + Reference< util::XModifyBroadcaster > xBroadcaster; + getFastPropertyValue( aOldValue, nHandle ); + if( aOldValue.hasValue() && + (aOldValue >>= xBroadcaster) && + xBroadcaster.is()) + { + ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder ); + } + + OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE ); + if( rValue.hasValue() && + (rValue >>= xBroadcaster) && + xBroadcaster.is()) + { + ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder ); + } + } + + ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue ); +} + +Reference< beans::XPropertySet > + SAL_CALL DataSeries::getDataPointByIndex( sal_Int32 nIndex ) +{ + Reference< beans::XPropertySet > xResult; + + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences; + { + MutexGuard aGuard( m_aMutex ); + aSequences = m_aDataSequences; + } + + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValuesSeries( + DataSeriesHelper::getAllDataSequencesByRole( aSequences , "values" ) ); + + if (aValuesSeries.empty()) + throw lang::IndexOutOfBoundsException(); + + Reference< chart2::data::XDataSequence > xSeq( aValuesSeries.front()->getValues() ); + if( 0 <= nIndex && nIndex < xSeq->getData().getLength() ) + { + { + MutexGuard aGuard( m_aMutex ); + tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ) ); + if( aIt != m_aAttributedDataPoints.end() ) + xResult = (*aIt).second; + } + if( !xResult.is() ) + { + Reference< beans::XPropertySet > xParentProperties; + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xParentProperties = this; + xModifyEventForwarder = m_xModifyEventForwarder; + } + + // create a new XPropertySet for this data point + xResult.set( new DataPoint( xParentProperties ) ); + { + MutexGuard aGuard( m_aMutex ); + m_aAttributedDataPoints[ nIndex ] = xResult; + } + ModifyListenerHelper::addListener( xResult, xModifyEventForwarder ); + } + } + + return xResult; +} + +void SAL_CALL DataSeries::resetDataPoint( sal_Int32 nIndex ) +{ + Reference< beans::XPropertySet > xDataPointProp; + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex )); + if( aIt != m_aAttributedDataPoints.end()) + { + xDataPointProp = (*aIt).second; + m_aAttributedDataPoints.erase(aIt); + } + + } + if( xDataPointProp.is() ) + { + Reference< util::XModifyBroadcaster > xBroadcaster( xDataPointProp, uno::UNO_QUERY ); + if( xBroadcaster.is() && xModifyEventForwarder.is()) + xBroadcaster->removeModifyListener( xModifyEventForwarder ); + fireModifyEvent(); + } +} + +void SAL_CALL DataSeries::resetAllDataPoints() +{ + tDataPointAttributeContainer aOldAttributedDataPoints; + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + std::swap( aOldAttributedDataPoints, m_aAttributedDataPoints ); + } + ModifyListenerHelper::removeListenerFromAllMapElements( aOldAttributedDataPoints, xModifyEventForwarder ); + aOldAttributedDataPoints.clear(); + fireModifyEvent(); +} + +// ____ XDataSink ____ +void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData ) +{ + tDataSequenceContainer aOldDataSequences; + tDataSequenceContainer aNewDataSequences; + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + std::swap( aOldDataSequences, m_aDataSequences ); + for (const auto & i : aData) + { + aNewDataSequences.push_back(i); + } + m_aDataSequences = aNewDataSequences; + } + ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder ); + fireModifyEvent(); +} + +void DataSeries::setData( const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > >& aData ) +{ + tDataSequenceContainer aOldDataSequences; + tDataSequenceContainer aNewDataSequences; + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + std::swap( aOldDataSequences, m_aDataSequences ); + aNewDataSequences = aData; + m_aDataSequences = aNewDataSequences; + } + ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ XDataSource ____ +Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences() +{ + MutexGuard aGuard( m_aMutex ); + return comphelper::containerToSequence<Reference< chart2::data::XLabeledDataSequence >>( m_aDataSequences ); +} + +// ____ XRegressionCurveContainer ____ +void SAL_CALL DataSeries::addRegressionCurve( + const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve ) +{ + auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(xRegressionCurve.get()); + assert(pRegressionCurve); + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + if( std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), pRegressionCurve ) + != m_aRegressionCurves.end()) + throw lang::IllegalArgumentException("curve not found", static_cast<cppu::OWeakObject*>(this), 1); + m_aRegressionCurves.push_back( pRegressionCurve ); + } + ModifyListenerHelper::addListener( rtl::Reference<RegressionCurveModel>(pRegressionCurve), xModifyEventForwarder ); + fireModifyEvent(); +} + +void SAL_CALL DataSeries::removeRegressionCurve( + const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve ) +{ + if( !xRegressionCurve.is() ) + throw container::NoSuchElementException(); + auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(xRegressionCurve.get()); + assert(pRegressionCurve); + + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + tRegressionCurveContainerType::iterator aIt( + std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), pRegressionCurve ) ); + if( aIt == m_aRegressionCurves.end()) + throw container::NoSuchElementException( + "The given regression curve is no element of this series", + static_cast< uno::XWeak * >( this )); + m_aRegressionCurves.erase( aIt ); + } + + ModifyListenerHelper::removeListener( rtl::Reference<RegressionCurveModel>(pRegressionCurve), xModifyEventForwarder ); + fireModifyEvent(); +} + +uno::Sequence< uno::Reference< chart2::XRegressionCurve > > SAL_CALL DataSeries::getRegressionCurves() +{ + MutexGuard aGuard( m_aMutex ); + return comphelper::containerToSequence<uno::Reference< chart2::XRegressionCurve >>( m_aRegressionCurves ); +} + +void SAL_CALL DataSeries::setRegressionCurves( + const Sequence< Reference< chart2::XRegressionCurve > >& aRegressionCurves ) +{ + tRegressionCurveContainerType aOldCurves; + tRegressionCurveContainerType aNewCurves; + for (const auto & i : aRegressionCurves) + { + auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(i.get()); + assert(pRegressionCurve); + aNewCurves.push_back(pRegressionCurve); + } + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + std::swap( aOldCurves, m_aRegressionCurves ); + m_aRegressionCurves = aNewCurves; + } + ModifyListenerHelper::removeListenerFromAllElements( aOldCurves, xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( aNewCurves, xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL DataSeries::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL DataSeries::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL DataSeries::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL DataSeries::disposing( const lang::EventObject& ) +{ +} + +// ____ OPropertySet ____ +void DataSeries::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void DataSeries::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +using impl::DataSeries_Base; +using ::property::OPropertySet; + +IMPLEMENT_FORWARD_XINTERFACE2( DataSeries, DataSeries_Base, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries, DataSeries_Base, OPropertySet ) + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL DataSeries::getImplementationName() +{ + return "com.sun.star.comp.chart.DataSeries"; +} + +sal_Bool SAL_CALL DataSeries::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL DataSeries::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.DataSeries", + "com.sun.star.chart2.DataPointProperties", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_DataSeries_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::DataSeries ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataSeriesProperties.cxx b/chart2/source/model/main/DataSeriesProperties.cxx new file mode 100644 index 000000000..d85d26475 --- /dev/null +++ b/chart2/source/model/main/DataSeriesProperties.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DataSeriesProperties.hxx" +#include "DataPointProperties.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/StackingDirection.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace chart +{ + +void DataSeriesProperties::AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "AttributedDataPoints", + PROP_DATASERIES_ATTRIBUTED_DATA_POINTS, + cppu::UnoType<uno::Sequence< sal_Int32 >>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "StackingDirection", + PROP_DATASERIES_STACKING_DIRECTION, + cppu::UnoType<chart2::StackingDirection>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "VaryColorsByPoint", + PROP_DATASERIES_VARY_COLORS_BY_POINT, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "AttachedAxisIndex", + PROP_DATASERIES_ATTACHED_AXIS_INDEX, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ShowLegendEntry", + PROP_DATASERIES_SHOW_LEGEND_ENTRY, + cppu::UnoType<sal_Bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "DeletedLegendEntries", + PROP_DATASERIES_DELETED_LEGEND_ENTRIES, + cppu::UnoType<uno::Sequence<sal_Int32>>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ShowCustomLeaderLines", + PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, + cppu::UnoType<sal_Bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // add properties of service DataPointProperties + DataPointProperties::AddPropertiesToVector( rOutProperties ); +} + +void DataSeriesProperties::AddDefaultsToMap( + tPropertyValueMap & rOutMap ) +{ + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_STACKING_DIRECTION, chart2::StackingDirection_NO_STACKING ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_VARY_COLORS_BY_POINT, false ); + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DATASERIES_ATTACHED_AXIS_INDEX, 0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_LEGEND_ENTRY, true ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, true ); + + // PROP_DATASERIES_ATTRIBUTED_DATA_POINTS has no default + + // add properties of service DataPointProperties + DataPointProperties::AddDefaultsToMap( rOutMap ); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/DataSeriesProperties.hxx b/chart2/source/model/main/DataSeriesProperties.hxx new file mode 100644 index 000000000..13636d442 --- /dev/null +++ b/chart2/source/model/main/DataSeriesProperties.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <PropertyHelper.hxx> +#include <FastPropertyIdRanges.hxx> + +#include <vector> + +namespace com::sun::star::beans { struct Property; } + +namespace chart::DataSeriesProperties +{ + enum + { + PROP_DATASERIES_ATTRIBUTED_DATA_POINTS = FAST_PROPERTY_ID_START_DATA_SERIES, + PROP_DATASERIES_STACKING_DIRECTION, + PROP_DATASERIES_VARY_COLORS_BY_POINT, + PROP_DATASERIES_ATTACHED_AXIS_INDEX, + PROP_DATASERIES_SHOW_LEGEND_ENTRY, + PROP_DATASERIES_DELETED_LEGEND_ENTRIES, + PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES + }; + + void AddPropertiesToVector( + std::vector< css::beans::Property > & rOutProperties ); + + void AddDefaultsToMap( tPropertyValueMap & rOutMap ); + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Diagram.cxx b/chart2/source/model/main/Diagram.cxx new file mode 100644 index 000000000..7791fabc1 --- /dev/null +++ b/chart2/source/model/main/Diagram.cxx @@ -0,0 +1,699 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <Diagram.hxx> +#include <ChartTypeManager.hxx> +#include <ChartTypeTemplate.hxx> +#include <PropertyHelper.hxx> +#include "Wall.hxx" +#include <ModifyListenerHelper.hxx> +#include <UserDefinedProperties.hxx> +#include <ConfigColorScheme.hxx> +#include <DiagramHelper.hxx> +#include <ThreeDHelper.hxx> +#include <CloneHelper.hxx> +#include <SceneProperties.hxx> +#include <unonames.hxx> +#include <BaseCoordinateSystem.hxx> +#include <Legend.hxx> + +#include <basegfx/numeric/ftools.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans::PropertyAttribute; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::osl::MutexGuard; + +namespace +{ + +enum +{ + PROP_DIAGRAM_REL_POS, + PROP_DIAGRAM_REL_SIZE, + PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, + PROP_DIAGRAM_SORT_BY_X_VALUES, + PROP_DIAGRAM_CONNECT_BARS, + PROP_DIAGRAM_GROUP_BARS_PER_AXIS, + PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, + PROP_DIAGRAM_STARTING_ANGLE, + PROP_DIAGRAM_RIGHT_ANGLED_AXES, + PROP_DIAGRAM_PERSPECTIVE, + PROP_DIAGRAM_ROTATION_HORIZONTAL, + PROP_DIAGRAM_ROTATION_VERTICAL, + PROP_DIAGRAM_MISSING_VALUE_TREATMENT, + PROP_DIAGRAM_3DRELATIVEHEIGHT, + PROP_DIAGRAM_DATATABLEHBORDER, + PROP_DIAGRAM_DATATABLEVBORDER, + PROP_DIAGRAM_DATATABLEOUTLINE, + PROP_DIAGRAM_EXTERNALDATA +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "RelativePosition", + PROP_DIAGRAM_REL_POS, + cppu::UnoType<chart2::RelativePosition>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativeSize", + PROP_DIAGRAM_REL_SIZE, + cppu::UnoType<chart2::RelativeSize>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "PosSizeExcludeAxes", + PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_SORT_BY_XVALUES, + PROP_DIAGRAM_SORT_BY_X_VALUES, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ConnectBars", + PROP_DIAGRAM_CONNECT_BARS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "GroupBarsPerAxis", + PROP_DIAGRAM_GROUP_BARS_PER_AXIS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "IncludeHiddenCells", + PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "StartingAngle", + PROP_DIAGRAM_STARTING_ANGLE, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "RightAngledAxes", + PROP_DIAGRAM_RIGHT_ANGLED_AXES, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Perspective", + PROP_DIAGRAM_PERSPECTIVE, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RotationHorizontal", + PROP_DIAGRAM_ROTATION_HORIZONTAL, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RotationVertical", + PROP_DIAGRAM_ROTATION_VERTICAL, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "MissingValueTreatment", + PROP_DIAGRAM_MISSING_VALUE_TREATMENT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "3DRelativeHeight", + PROP_DIAGRAM_3DRELATIVEHEIGHT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "DataTableHBorder", + PROP_DIAGRAM_DATATABLEHBORDER, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableVBorder", + PROP_DIAGRAM_DATATABLEVBORDER, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableOutline", + PROP_DIAGRAM_DATATABLEOUTLINE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ExternalData", + PROP_DIAGRAM_EXTERNALDATA, + cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID ); +} + +const ::chart::tPropertyValueMap& StaticDiagramDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = []() + { + ::chart::tPropertyValueMap aMap; + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_SORT_BY_X_VALUES, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_CONNECT_BARS, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_GROUP_BARS_PER_AXIS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_RIGHT_ANGLED_AXES, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_DATATABLEHBORDER, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_DATATABLEVBORDER, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_DATATABLEOUTLINE, false ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_DIAGRAM_STARTING_ANGLE, 90 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_DIAGRAM_3DRELATIVEHEIGHT, 100 ); + ::chart::SceneProperties::AddDefaultsToMap( aMap ); + return aMap; + }(); + return aStaticDefaults; +}; + +::cppu::OPropertyArrayHelper& StaticDiagramInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::SceneProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return ::cppu::OPropertyArrayHelper( aProperties.data(), aProperties.size() ); + }(); + return aPropHelper; +}; + +const uno::Reference< beans::XPropertySetInfo >& StaticDiagramInfo() +{ + static const uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDiagramInfoHelper() ) ); + return xPropertySetInfo; +}; + +void lcl_CloneCoordinateSystems( + const ::chart::Diagram::tCoordinateSystemContainerType & rSource, + ::chart::Diagram::tCoordinateSystemContainerType & rDestination ) +{ + for( rtl::Reference< ::chart::BaseCoordinateSystem > const & i : rSource ) + { + auto xClone = i->createClone(); + ::chart::BaseCoordinateSystem* pClone = dynamic_cast<::chart::BaseCoordinateSystem*>(xClone.get()); + assert(pClone); + rDestination.push_back( pClone ); + } +} + +} // anonymous namespace + +namespace chart +{ + +Diagram::Diagram( uno::Reference< uno::XComponentContext > const & xContext ) : + ::property::OPropertySet( m_aMutex ), + m_xContext( xContext ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ + // Set camera position to a default position (that should be set hard, so + // that it will be exported. The property default is a camera looking + // straight ono the scene). These defaults have been acquired from the old + // chart implementation. + setFastPropertyValue_NoBroadcast( + SceneProperties::PROP_SCENE_CAMERA_GEOMETRY, uno::Any( + ThreeDHelper::getDefaultCameraGeometry())); +} + +Diagram::Diagram( const Diagram & rOther ) : + impl::Diagram_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xContext( rOther.m_xContext ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ + lcl_CloneCoordinateSystems( rOther.m_aCoordSystems, m_aCoordSystems ); + for (auto & xSystem : m_aCoordSystems) + xSystem->addModifyListener(m_xModifyEventForwarder); + + if ( rOther.m_xWall ) + m_xWall = new Wall( *rOther.m_xWall ); + if ( rOther.m_xFloor ) + m_xFloor = new Wall( *rOther.m_xFloor ); + m_xTitle.set( CloneHelper::CreateRefClone< chart2::XTitle >()( rOther.m_xTitle )); + if (rOther.m_xLegend) + m_xLegend = new Legend(*rOther.m_xLegend); + + if ( m_xWall ) + m_xWall->addModifyListener( m_xModifyEventForwarder ); + if ( m_xFloor ) + m_xFloor->addModifyListener( m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( m_xTitle, m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( m_xLegend, m_xModifyEventForwarder ); +} + +Diagram::~Diagram() +{ + try + { + for (auto & xSystem : m_aCoordSystems) + xSystem->removeModifyListener(m_xModifyEventForwarder); + + if ( m_xWall ) + m_xWall->removeModifyListener( m_xModifyEventForwarder ); + if ( m_xFloor ) + m_xFloor->removeModifyListener( m_xModifyEventForwarder ); + ModifyListenerHelper::removeListener( m_xTitle, m_xModifyEventForwarder ); + ModifyListenerHelper::removeListener( m_xLegend, m_xModifyEventForwarder ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XDiagram ____ +uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getWall() +{ + rtl::Reference< Wall > xRet; + bool bAddListener = false; + { + MutexGuard aGuard( m_aMutex ); + if( !m_xWall.is() ) + { + m_xWall.set( new Wall() ); + bAddListener = true; + } + xRet = m_xWall; + } + if(bAddListener) + xRet->addModifyListener( m_xModifyEventForwarder ); + return xRet; +} + +uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getFloor() +{ + rtl::Reference< Wall > xRet; + bool bAddListener = false; + { + MutexGuard aGuard( m_aMutex ); + if( !m_xFloor.is() ) + { + m_xFloor.set( new Wall() ); + bAddListener = true; + } + xRet = m_xFloor; + } + if(bAddListener) + xRet->addModifyListener( m_xModifyEventForwarder ); + return xRet; +} + +uno::Reference< chart2::XLegend > SAL_CALL Diagram::getLegend() +{ + MutexGuard aGuard( m_aMutex ); + return m_xLegend; +} + +void SAL_CALL Diagram::setLegend( const uno::Reference< chart2::XLegend >& xNewLegend ) +{ + auto pLegend = dynamic_cast<Legend*>(xNewLegend.get()); + assert(!xNewLegend || pLegend); + setLegend(rtl::Reference< Legend >(pLegend)); +} + +void Diagram::setLegend( const rtl::Reference< Legend >& xNewLegend ) +{ + rtl::Reference< Legend > xOldLegend; + { + MutexGuard aGuard( m_aMutex ); + if( m_xLegend == xNewLegend ) + return; + xOldLegend = m_xLegend; + m_xLegend = xNewLegend; + } + if( xOldLegend.is()) + ModifyListenerHelper::removeListener( xOldLegend, m_xModifyEventForwarder ); + if( xNewLegend.is()) + ModifyListenerHelper::addListener( xNewLegend, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +Reference< chart2::XColorScheme > SAL_CALL Diagram::getDefaultColorScheme() +{ + Reference< chart2::XColorScheme > xRet; + { + MutexGuard aGuard( m_aMutex ); + xRet = m_xColorScheme; + } + + if( !xRet.is()) + { + xRet.set( createConfigColorScheme( m_xContext )); + MutexGuard aGuard( m_aMutex ); + m_xColorScheme = xRet; + } + return xRet; +} + +void SAL_CALL Diagram::setDefaultColorScheme( const Reference< chart2::XColorScheme >& xColorScheme ) +{ + { + MutexGuard aGuard( m_aMutex ); + m_xColorScheme.set( xColorScheme ); + } + fireModifyEvent(); +} + +void SAL_CALL Diagram::setDiagramData( + const Reference< chart2::data::XDataSource >& xDataSource, + const Sequence< beans::PropertyValue >& aArguments ) +{ + rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = new ::chart::ChartTypeManager( m_xContext ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = DiagramHelper::getTemplateForDiagram( this, xChartTypeManager ); + rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( aTemplateAndService.xChartTypeTemplate ); + if( !xTemplate.is() ) + xTemplate = xChartTypeManager->createTemplate( "com.sun.star.chart2.template.Column" ); + if(!xTemplate.is()) + return; + xTemplate->changeDiagramData( rtl::Reference< ::chart::Diagram >(this), xDataSource, aArguments ); +} + +// ____ XTitled ____ +uno::Reference< chart2::XTitle > SAL_CALL Diagram::getTitleObject() +{ + MutexGuard aGuard( m_aMutex ); + return m_xTitle; +} + +void SAL_CALL Diagram::setTitleObject( const uno::Reference< chart2::XTitle >& xNewTitle ) +{ + Reference< chart2::XTitle > xOldTitle; + { + MutexGuard aGuard( m_aMutex ); + if( m_xTitle == xNewTitle ) + return; + xOldTitle = m_xTitle; + m_xTitle = xNewTitle; + } + if( xOldTitle.is()) + ModifyListenerHelper::removeListener( xOldTitle, m_xModifyEventForwarder ); + if( xNewTitle.is()) + ModifyListenerHelper::addListener( xNewTitle, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ X3DDefaultSetter ____ +void SAL_CALL Diagram::set3DSettingsToDefault() +{ + ThreeDHelper::set3DSettingsToDefault( this ); +} + +void SAL_CALL Diagram::setDefaultRotation() +{ + ThreeDHelper::setDefaultRotation( this ); +} + +void SAL_CALL Diagram::setDefaultIllumination() +{ + ThreeDHelper::setDefaultIllumination( this ); +} + +// ____ XCoordinateSystemContainer ____ +void SAL_CALL Diagram::addCoordinateSystem( + const uno::Reference< chart2::XCoordinateSystem >& aCoordSys ) +{ + ::chart::BaseCoordinateSystem* pCoordSys = dynamic_cast<::chart::BaseCoordinateSystem*>(aCoordSys.get()); + assert(pCoordSys); + { + MutexGuard aGuard( m_aMutex ); + if( std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), pCoordSys ) + != m_aCoordSystems.end()) + throw lang::IllegalArgumentException("coordsys not found", static_cast<cppu::OWeakObject*>(this), 1); + + if( !m_aCoordSystems.empty() ) + { + OSL_FAIL( "more than one coordinatesystem is not supported yet by the fileformat" ); + return; + } + m_aCoordSystems.push_back( pCoordSys ); + } + ModifyListenerHelper::addListener( aCoordSys, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +void SAL_CALL Diagram::removeCoordinateSystem( + const uno::Reference< chart2::XCoordinateSystem >& aCoordSys ) +{ + ::chart::BaseCoordinateSystem* pCoordSys = dynamic_cast<::chart::BaseCoordinateSystem*>(aCoordSys.get()); + assert(pCoordSys); + { + MutexGuard aGuard( m_aMutex ); + auto aIt = std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), pCoordSys ); + if( aIt == m_aCoordSystems.end()) + throw container::NoSuchElementException( + "The given coordinate-system is no element of the container", + static_cast< uno::XWeak * >( this )); + m_aCoordSystems.erase( aIt ); + } + ModifyListenerHelper::removeListener( aCoordSys, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > SAL_CALL Diagram::getCoordinateSystems() +{ + MutexGuard aGuard( m_aMutex ); + return comphelper::containerToSequence<uno::Reference< chart2::XCoordinateSystem >>( m_aCoordSystems ); +} + +void SAL_CALL Diagram::setCoordinateSystems( + const Sequence< Reference< chart2::XCoordinateSystem > >& aCoordinateSystems ) +{ + tCoordinateSystemContainerType aNew; + tCoordinateSystemContainerType aOld; + if( aCoordinateSystems.hasElements() ) + { + OSL_ENSURE( aCoordinateSystems.getLength()<=1, "more than one coordinatesystem is not supported yet by the fileformat" ); + ::chart::BaseCoordinateSystem* pCoordSys = dynamic_cast<::chart::BaseCoordinateSystem*>(aCoordinateSystems[0].get()); + assert(pCoordSys); + aNew.push_back( pCoordSys ); + } + { + MutexGuard aGuard( m_aMutex ); + std::swap( aOld, m_aCoordSystems ); + m_aCoordSystems = aNew; + } + for (auto & xSystem : aOld) + xSystem->removeModifyListener(m_xModifyEventForwarder); + for (auto & xSystem : aNew) + xSystem->addModifyListener(m_xModifyEventForwarder); + fireModifyEvent(); +} + +void Diagram::setCoordinateSystems( + const std::vector< rtl::Reference< BaseCoordinateSystem > >& aCoordinateSystems ) +{ + tCoordinateSystemContainerType aNew; + tCoordinateSystemContainerType aOld; + if( !aCoordinateSystems.empty() ) + { + OSL_ENSURE( aCoordinateSystems.size()<=1, "more than one coordinatesystem is not supported yet by the fileformat" ); + aNew.push_back( aCoordinateSystems[0] ); + } + { + MutexGuard aGuard( m_aMutex ); + std::swap( aOld, m_aCoordSystems ); + m_aCoordSystems = aNew; + } + for (auto & xSystem : aOld) + xSystem->removeModifyListener(m_xModifyEventForwarder); + for (auto & xSystem : aNew) + xSystem->addModifyListener(m_xModifyEventForwarder); + fireModifyEvent(); +} + +// ____ XCloneable ____ +Reference< util::XCloneable > SAL_CALL Diagram::createClone() +{ + MutexGuard aGuard( m_aMutex ); + return Reference< util::XCloneable >( new Diagram( *this )); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Diagram::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL Diagram::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL Diagram::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL Diagram::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void Diagram::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void Diagram::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ____ OPropertySet ____ +void Diagram::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticDiagramDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL Diagram::getInfoHelper() +{ + return StaticDiagramInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL Diagram::getPropertySetInfo() +{ + return StaticDiagramInfo(); +} + +// ____ XFastPropertySet ____ +void SAL_CALL Diagram::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue ) +{ + //special treatment for some 3D properties + if( nHandle == PROP_DIAGRAM_PERSPECTIVE ) + { + sal_Int32 fPerspective = 20; + if( rValue >>=fPerspective ) + ThreeDHelper::setCameraDistance( this, ThreeDHelper::PerspectiveToCameraDistance( fPerspective ) ); + } + else if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL + || nHandle == PROP_DIAGRAM_ROTATION_VERTICAL ) + { + sal_Int32 nNewAngleDegree = 0; + if( rValue >>=nNewAngleDegree ) + { + sal_Int32 nHorizontal, nVertical; + ThreeDHelper::getRotationFromDiagram( this, nHorizontal, nVertical ); + if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL ) + nHorizontal = nNewAngleDegree; + else + nVertical = nNewAngleDegree; + ThreeDHelper::setRotationToDiagram( this, nHorizontal, nVertical ); + } + } + else + ::property::OPropertySet::setFastPropertyValue( nHandle, rValue ); +} + +void SAL_CALL Diagram::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + //special treatment for some 3D properties + if( nHandle == PROP_DIAGRAM_PERSPECTIVE ) + { + sal_Int32 nPerspective = ::basegfx::fround( ThreeDHelper::CameraDistanceToPerspective( + ThreeDHelper::getCameraDistance( const_cast< Diagram* >( this ) ) ) ); + rValue <<= nPerspective; + } + else if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL + || nHandle == PROP_DIAGRAM_ROTATION_VERTICAL ) + { + sal_Int32 nHorizontal, nVertical; + ThreeDHelper::getRotationFromDiagram( const_cast< Diagram* >( this ), nHorizontal, nVertical ); + sal_Int32 nAngleDegree = 0; + if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL ) + nAngleDegree = nHorizontal; + else + nAngleDegree = nVertical; + rValue <<= nAngleDegree; + } + else + ::property::OPropertySet::getFastPropertyValue( rValue,nHandle ); +} + +using impl::Diagram_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( Diagram, Diagram_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( Diagram, Diagram_Base, ::property::OPropertySet ) + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL Diagram::getImplementationName() +{ + return "com.sun.star.comp.chart2.Diagram"; +} + +sal_Bool SAL_CALL Diagram::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL Diagram::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.Diagram", + "com.sun.star.layout.LayoutElement", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_Diagram_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::Diagram(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/FormattedString.cxx b/chart2/source/model/main/FormattedString.cxx new file mode 100644 index 000000000..69f871ddc --- /dev/null +++ b/chart2/source/model/main/FormattedString.cxx @@ -0,0 +1,300 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "FormattedString.hxx" + +#include <CharacterProperties.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::osl::MutexGuard; + +namespace +{ + +struct StaticFormattedStringDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::CharacterProperties::AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +}; + +struct StaticFormattedStringDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticFormattedStringDefaults_Initializer > +{ +}; + +struct StaticFormattedStringInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticFormattedStringInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticFormattedStringInfoHelper_Initializer > +{ +}; + +struct StaticFormattedStringInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticFormattedStringInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticFormattedStringInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticFormattedStringInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +FormattedString::FormattedString() : + ::property::OPropertySet( m_aMutex ), + m_aType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT), + m_bDataLabelsRange(false), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +FormattedString::FormattedString( const FormattedString & rOther ) : + impl::FormattedString_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_aString( rOther.m_aString ), + m_aType(rOther.m_aType), + m_aGuid(rOther.m_aGuid), + m_bDataLabelsRange(rOther.m_bDataLabelsRange), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +FormattedString::~FormattedString() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL FormattedString::createClone() +{ + return uno::Reference< util::XCloneable >( new FormattedString( *this )); +} + +// ____ XFormattedString ____ +OUString SAL_CALL FormattedString::getString() +{ + MutexGuard aGuard( m_aMutex); + return m_aString; +} + +void SAL_CALL FormattedString::setString( const OUString& String ) +{ + { + MutexGuard aGuard( m_aMutex); + m_aString = String; + } + //don't keep the mutex locked while calling out + fireModifyEvent(); + +} + +// ____ XDataPointCustomLabelField ____ +css::chart2::DataPointCustomLabelFieldType SAL_CALL FormattedString::getFieldType() +{ + MutexGuard aGuard(m_aMutex); + return m_aType; +} + +void SAL_CALL +FormattedString::setFieldType(const css::chart2::DataPointCustomLabelFieldType Type) +{ + { + MutexGuard aGuard(m_aMutex); + m_aType = Type; + } + //don't keep the mutex locked while calling out + fireModifyEvent(); +} + +OUString SAL_CALL FormattedString::getGuid() +{ + MutexGuard aGuard( m_aMutex); + return m_aGuid; +} + +void SAL_CALL FormattedString::setGuid( const OUString& guid ) +{ + { + MutexGuard aGuard( m_aMutex); + m_aGuid= guid; + } + //don't keep the mutex locked while calling out + fireModifyEvent(); + +} + +sal_Bool SAL_CALL FormattedString::getDataLabelsRange() +{ + MutexGuard aGuard( m_aMutex); + return m_bDataLabelsRange; +} + +void SAL_CALL FormattedString::setDataLabelsRange( sal_Bool dataLabelsRange ) +{ + { + MutexGuard aGuard( m_aMutex); + m_bDataLabelsRange = dataLabelsRange; + } + //don't keep the mutex locked while calling out + fireModifyEvent(); +} + +OUString SAL_CALL FormattedString::getCellRange() +{ + MutexGuard aGuard( m_aMutex); + return m_aCellRange; +} + +void SAL_CALL FormattedString::setCellRange( const OUString& cellRange ) +{ + { + MutexGuard aGuard( m_aMutex); + m_aCellRange = cellRange; + } + //don't keep the mutex locked while calling out + fireModifyEvent(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL FormattedString::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL FormattedString::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL FormattedString::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL FormattedString::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void FormattedString::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void FormattedString::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ____ OPropertySet ____ +void FormattedString::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticFormattedStringDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL FormattedString::getInfoHelper() +{ + return *StaticFormattedStringInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL FormattedString::getPropertySetInfo() +{ + return *StaticFormattedStringInfo::get(); +} + +using impl::FormattedString_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( FormattedString, FormattedString_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( FormattedString, FormattedString_Base, ::property::OPropertySet ) + +// do this in derived classes! + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL FormattedString::getImplementationName() +{ + return "com.sun.star.comp.chart.FormattedString"; +} + +sal_Bool SAL_CALL FormattedString::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL FormattedString::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.DataPointCustomLabelField", + "com.sun.star.chart2.FormattedString", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_FormattedString_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::FormattedString); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/FormattedString.hxx b/chart2/source/model/main/FormattedString.hxx new file mode 100644 index 000000000..878c30015 --- /dev/null +++ b/chart2/source/model/main/FormattedString.hxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <ModifyListenerHelper.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::chart2::XDataPointCustomLabelField, // inherits from XFormattedString2 + css::lang::XServiceInfo, + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + FormattedString_Base; +} + +class FormattedString final : + public cppu::BaseMutex, + public impl::FormattedString_Base, + public ::property::OPropertySet +{ +public: + explicit FormattedString(); + virtual ~FormattedString() override; + + /// declare XServiceInfo methods + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + + virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2) override + { ::property::OPropertySet::setPropertyValue(p1, p2); } + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1) override + { return ::property::OPropertySet::getPropertyValue(p1); } + virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override + { ::property::OPropertySet::addPropertyChangeListener(p1, p2); } + virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override + { ::property::OPropertySet::removePropertyChangeListener(p1, p2); } + virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override + { ::property::OPropertySet::addVetoableChangeListener(p1, p2); } + virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override + { ::property::OPropertySet::removeVetoableChangeListener(p1, p2); } + +private: + explicit FormattedString( const FormattedString & rOther ); + + // ____ XFormattedString ____ + virtual OUString SAL_CALL getString() override; + virtual void SAL_CALL setString( const OUString& String ) override; + + // ____ XDataPointCustomLabelField ____ + virtual css::chart2::DataPointCustomLabelFieldType SAL_CALL getFieldType() override; + virtual void SAL_CALL + setFieldType( const css::chart2::DataPointCustomLabelFieldType FieldType ) override; + virtual OUString SAL_CALL getGuid() override; + void SAL_CALL setGuid( const OUString& guid ) override; + virtual sal_Bool SAL_CALL getDataLabelsRange() override; + virtual void SAL_CALL setDataLabelsRange( sal_Bool dataLabelsRange ) override; + virtual OUString SAL_CALL getCellRange() override; + virtual void SAL_CALL setCellRange( const OUString& cellRange ) override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const css::lang::EventObject& aEvent ) override; + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const css::lang::EventObject& Source ) override; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + void fireModifyEvent(); + + // ____ XFormattedString ____ + OUString m_aString; + + // ____ XDataPointCustomLabelField ____ + css::chart2::DataPointCustomLabelFieldType m_aType; + OUString m_aGuid; + OUString m_aCellRange; + bool m_bDataLabelsRange; + + rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/GridProperties.cxx b/chart2/source/model/main/GridProperties.cxx new file mode 100644 index 000000000..7bfb4453e --- /dev/null +++ b/chart2/source/model/main/GridProperties.cxx @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "GridProperties.hxx" +#include <LinePropertiesHelper.hxx> +#include <UserDefinedProperties.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::beans { class XPropertySetInfo; } +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_GRID_SHOW +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "Show", + PROP_GRID_SHOW, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticGridDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_GRID_SHOW, false ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( + rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_COLOR, 0xb3b3b3 ); // gray30 + } +}; + +struct StaticGridDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticGridDefaults_Initializer > +{ +}; + +struct StaticGridInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticGridInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticGridInfoHelper_Initializer > +{ +}; + +struct StaticGridInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticGridInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticGridInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticGridInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +GridProperties::GridProperties() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +GridProperties::GridProperties( const GridProperties & rOther ) : + impl::GridProperties_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ +} + +GridProperties::~GridProperties() +{} + +// ____ OPropertySet ____ +void GridProperties::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticGridDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL GridProperties::getInfoHelper() +{ + return *StaticGridInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL GridProperties::getPropertySetInfo() +{ + return *StaticGridInfo::get(); +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL GridProperties::createClone() +{ + return uno::Reference< util::XCloneable >( new GridProperties( *this )); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL GridProperties::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL GridProperties::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL GridProperties::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL GridProperties::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void GridProperties::firePropertyChangeEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL GridProperties::getImplementationName() +{ + return "com.sun.star.comp.chart2.GridProperties"; +} + +sal_Bool SAL_CALL GridProperties::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL GridProperties::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.GridProperties", + "com.sun.star.beans.PropertySet" }; +} + +// needed by MSC compiler +using impl::GridProperties_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( GridProperties, GridProperties_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridProperties, GridProperties_Base, ::property::OPropertySet ) + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_GridProperties_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::GridProperties); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/GridProperties.hxx b/chart2/source/model/main/GridProperties.hxx new file mode 100644 index 000000000..43ab136c8 --- /dev/null +++ b/chart2/source/model/main/GridProperties.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <ModifyListenerHelper.hxx> + +#include <OPropertySet.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::lang::XServiceInfo, + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + GridProperties_Base; +} + +class GridProperties final : + public cppu::BaseMutex, + public impl::GridProperties_Base, + public ::property::OPropertySet +{ +public: + explicit GridProperties(); + virtual ~GridProperties() override; + + /// XServiceInfo declarations + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +private: + explicit GridProperties( const GridProperties & rOther ); + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const css::lang::EventObject& aEvent ) override; + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const css::lang::EventObject& Source ) override; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Legend.cxx b/chart2/source/model/main/Legend.cxx new file mode 100644 index 000000000..8a0676e74 --- /dev/null +++ b/chart2/source/model/main/Legend.cxx @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <Legend.hxx> +#include <LinePropertiesHelper.hxx> +#include <FillProperties.hxx> +#include <CharacterProperties.hxx> +#include <UserDefinedProperties.hxx> +#include <ModifyListenerHelper.hxx> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart/ChartLegendExpansion.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> +#include <cppuhelper/supportsservice.hxx> + +#include <algorithm> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans::PropertyAttribute; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_LEGEND_ANCHOR_POSITION, + PROP_LEGEND_EXPANSION, + PROP_LEGEND_SHOW, + PROP_LEGEND_OVERLAY, + PROP_LEGEND_REF_PAGE_SIZE, + PROP_LEGEND_REL_POS, + PROP_LEGEND_REL_SIZE +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "AnchorPosition", + PROP_LEGEND_ANCHOR_POSITION, + cppu::UnoType<chart2::LegendPosition>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Expansion", + PROP_LEGEND_EXPANSION, + cppu::UnoType<css::chart::ChartLegendExpansion>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Show", + PROP_LEGEND_SHOW, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Overlay", + PROP_LEGEND_OVERLAY, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_LEGEND_REF_PAGE_SIZE, + cppu::UnoType<awt::Size>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativePosition", + PROP_LEGEND_REL_POS, + cppu::UnoType<chart2::RelativePosition>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativeSize", + PROP_LEGEND_REL_SIZE, + cppu::UnoType<chart2::RelativeSize>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + +} + +struct StaticLegendDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + ::chart::CharacterProperties::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_ANCHOR_POSITION, chart2::LegendPosition_LINE_END ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_EXPANSION, css::chart::ChartLegendExpansion_HIGH ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_SHOW, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_OVERLAY, false ); + + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + } +}; + +struct StaticLegendDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticLegendDefaults_Initializer > +{ +}; + +struct StaticLegendInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::FillProperties::AddPropertiesToVector( aProperties ); + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticLegendInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticLegendInfoHelper_Initializer > +{ +}; + +struct StaticLegendInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticLegendInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticLegendInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticLegendInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +Legend::Legend() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ +} + +Legend::Legend( const Legend & rOther ) : + impl::Legend_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ +} + +Legend::~Legend() +{ +} + +// ____ XCloneable ____ +Reference< util::XCloneable > SAL_CALL Legend::createClone() +{ + return Reference< util::XCloneable >( new Legend( *this )); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Legend::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL Legend::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL Legend::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL Legend::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void Legend::firePropertyChangeEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ____ OPropertySet ____ +void Legend::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticLegendDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Legend::getInfoHelper() +{ + return *StaticLegendInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL Legend::getPropertySetInfo() +{ + return *StaticLegendInfo::get(); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +OUString SAL_CALL Legend::getImplementationName() +{ + return "com.sun.star.comp.chart2.Legend"; +} + +sal_Bool SAL_CALL Legend::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL Legend::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.Legend", + "com.sun.star.beans.PropertySet", + "com.sun.star.drawing.FillProperties", + "com.sun.star.drawing.LineProperties", + "com.sun.star.style.CharacterProperties", + "com.sun.star.layout.LayoutElement" + }; +} + +// needed by MSC compiler +using impl::Legend_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( Legend, Legend_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( Legend, Legend_Base, ::property::OPropertySet ) + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_Legend_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::Legend); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/PageBackground.cxx b/chart2/source/model/main/PageBackground.cxx new file mode 100644 index 000000000..b61720318 --- /dev/null +++ b/chart2/source/model/main/PageBackground.cxx @@ -0,0 +1,222 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "PageBackground.hxx" +#include <LinePropertiesHelper.hxx> +#include <FillProperties.hxx> +#include <UserDefinedProperties.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> + +#include <com/sun/star/drawing/LineStyle.hpp> +#include <cppuhelper/supportsservice.hxx> + +#include <vector> +#include <algorithm> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticPageBackgroundDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( rOutMap, ::chart::FillProperties::PROP_FILL_COLOR, 0xffffff ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + } +}; + +struct StaticPageBackgroundDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticPageBackgroundDefaults_Initializer > +{ +}; + +struct StaticPageBackgroundInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::FillProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticPageBackgroundInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticPageBackgroundInfoHelper_Initializer > +{ +}; + +struct StaticPageBackgroundInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticPageBackgroundInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticPageBackgroundInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticPageBackgroundInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +PageBackground::PageBackground() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +PageBackground::PageBackground( const PageBackground & rOther ) : + impl::PageBackground_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +PageBackground::~PageBackground() +{} + +// ____ XTypeProvider ____ +uno::Sequence< css::uno::Type > SAL_CALL PageBackground::getTypes() +{ + return ::comphelper::concatSequences( + impl::PageBackground_Base::getTypes(), + ::property::OPropertySet::getTypes()); +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL PageBackground::createClone() +{ + return uno::Reference< util::XCloneable >( new PageBackground( *this )); +} + +// ____ OPropertySet ____ +void PageBackground::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticPageBackgroundDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL PageBackground::getInfoHelper() +{ + return *StaticPageBackgroundInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL PageBackground::getPropertySetInfo() +{ + return *StaticPageBackgroundInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL PageBackground::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL PageBackground::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL PageBackground::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL PageBackground::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void PageBackground::firePropertyChangeEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +OUString SAL_CALL PageBackground::getImplementationName() +{ + return "com.sun.star.comp.chart2.PageBackground"; +} + +sal_Bool SAL_CALL PageBackground::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL PageBackground::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.PageBackground", + "com.sun.star.beans.PropertySet" }; +} + +using impl::PageBackground_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( PageBackground, PageBackground_Base, ::property::OPropertySet ) + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_PageBackground_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::PageBackground ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/PageBackground.hxx b/chart2/source/model/main/PageBackground.hxx new file mode 100644 index 000000000..15c32234c --- /dev/null +++ b/chart2/source/model/main/PageBackground.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/uno3.hxx> +#include <ModifyListenerHelper.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener, + css::lang::XServiceInfo > + PageBackground_Base; +} + +class PageBackground final : + public cppu::BaseMutex, + public impl::PageBackground_Base, + public ::property::OPropertySet +{ +public: + explicit PageBackground(); + virtual ~PageBackground() override; + + /// XServiceInfo declarations + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + + explicit PageBackground( const PageBackground & rOther ); + + // ____ XTypeProvider ____ + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + +private: + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const css::lang::EventObject& aEvent ) override; + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const css::lang::EventObject& Source ) override; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/PolarCoordinateSystem.cxx b/chart2/source/model/main/PolarCoordinateSystem.cxx new file mode 100644 index 000000000..5c891989e --- /dev/null +++ b/chart2/source/model/main/PolarCoordinateSystem.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <PolarCoordinateSystem.hxx> +#include <servicenames_coosystems.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +constexpr OUStringLiteral CHART2_COOSYSTEM_POLAR_SERVICE_NAME + = u"com.sun.star.chart2.CoordinateSystems.Polar"; + +} + +namespace chart +{ + +// explicit +PolarCoordinateSystem::PolarCoordinateSystem( sal_Int32 nDimensionCount /* = 2 */ ) : + BaseCoordinateSystem( nDimensionCount ) +{} + +PolarCoordinateSystem::PolarCoordinateSystem( + const PolarCoordinateSystem & rSource ) : + BaseCoordinateSystem( rSource ) +{} + +PolarCoordinateSystem::~PolarCoordinateSystem() +{} + +// ____ XCoordinateSystem ____ +OUString SAL_CALL PolarCoordinateSystem::getCoordinateSystemType() +{ + return CHART2_COOSYSTEM_POLAR_SERVICE_NAME; +} + +OUString SAL_CALL PolarCoordinateSystem::getViewServiceName() +{ + return CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME; +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL PolarCoordinateSystem::createClone() +{ + return Reference< util::XCloneable >( new PolarCoordinateSystem( *this )); +} + +// ____ XServiceInfo ____ +OUString SAL_CALL PolarCoordinateSystem::getImplementationName() +{ + return "com.sun.star.comp.chart.PolarCoordinateSystem"; +} + +sal_Bool SAL_CALL PolarCoordinateSystem::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL PolarCoordinateSystem::getSupportedServiceNames() +{ + return { CHART2_COOSYSTEM_POLAR_SERVICE_NAME }; +} + +// ==== PolarCoordinateSystem2d ==== + +PolarCoordinateSystem2d::PolarCoordinateSystem2d() : + PolarCoordinateSystem( 2 ) +{} + +PolarCoordinateSystem2d::~PolarCoordinateSystem2d() +{} + +// ____ XServiceInfo ____ +OUString SAL_CALL PolarCoordinateSystem2d::getImplementationName() +{ + return "com.sun.star.comp.chart2.PolarCoordinateSystem2d" ; +} + +sal_Bool SAL_CALL PolarCoordinateSystem2d::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL PolarCoordinateSystem2d::getSupportedServiceNames() +{ + return { + CHART2_COOSYSTEM_POLAR_SERVICE_NAME, + "com.sun.star.chart2.PolarCoordinateSystem2d" }; +} + +// ==== PolarCoordinateSystem3d ==== + +PolarCoordinateSystem3d::PolarCoordinateSystem3d() : + PolarCoordinateSystem( 3 ) +{} + +PolarCoordinateSystem3d::~PolarCoordinateSystem3d() +{} + +// ____ XServiceInfo ____ +OUString SAL_CALL PolarCoordinateSystem3d::getImplementationName() +{ + return "com.sun.star.comp.chart2.PolarCoordinateSystem3d"; +} + +sal_Bool SAL_CALL PolarCoordinateSystem3d::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL PolarCoordinateSystem3d::getSupportedServiceNames() +{ + return { + CHART2_COOSYSTEM_POLAR_SERVICE_NAME, + "com.sun.star.chart2.PolarCoordinateSystem3d" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_PolarCoordinateSystem2d_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::PolarCoordinateSystem2d); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_PolarCoordinateSystem3d_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::PolarCoordinateSystem3d); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/StockBar.cxx b/chart2/source/model/main/StockBar.cxx new file mode 100644 index 000000000..f319478e0 --- /dev/null +++ b/chart2/source/model/main/StockBar.cxx @@ -0,0 +1,205 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <StockBar.hxx> +#include <LinePropertiesHelper.hxx> +#include <FillProperties.hxx> +#include <UserDefinedProperties.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#include <algorithm> + +namespace com::sun::star::beans { class XPropertySetInfo; } + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticStockBarInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::FillProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticStockBarInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticStockBarInfoHelper_Initializer > +{ +}; + +struct StaticStockBarInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticStockBarInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticStockBarInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticStockBarInfo_Initializer > +{ +}; + +struct StaticStockBarDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( rOutMap, ::chart::FillProperties::PROP_FILL_COLOR, 0xffffff ); // white + } +}; + +struct StaticStockBarDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticStockBarDefaults_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +StockBar::StockBar( bool bRisingCourse ) : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ + if( ! bRisingCourse ) + { + setFastPropertyValue_NoBroadcast( + ::chart::FillProperties::PROP_FILL_COLOR, + uno::Any( sal_Int32( 0x000000 ))); // black + setFastPropertyValue_NoBroadcast( + ::chart::LinePropertiesHelper::PROP_LINE_COLOR, + uno::Any( sal_Int32( 0xb3b3b3 ))); // gray30 + } +} + +StockBar::StockBar( const StockBar & rOther ) : + impl::StockBar_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +StockBar::~StockBar() +{} + +// ____ XTypeProvider ____ +uno::Sequence< css::uno::Type > SAL_CALL StockBar::getTypes() +{ + return ::comphelper::concatSequences( + impl::StockBar_Base::getTypes(), + ::property::OPropertySet::getTypes()); +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL StockBar::createClone() +{ + return uno::Reference< util::XCloneable >( new StockBar( *this )); +} + +// ____ OPropertySet ____ +void StockBar::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticStockBarDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL StockBar::getInfoHelper() +{ + return *StaticStockBarInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL StockBar::getPropertySetInfo() +{ + return *StaticStockBarInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL StockBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL StockBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL StockBar::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL StockBar::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void StockBar::firePropertyChangeEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +using impl::StockBar_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( StockBar, StockBar_Base, ::property::OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Title.cxx b/chart2/source/model/main/Title.cxx new file mode 100644 index 000000000..98004e30a --- /dev/null +++ b/chart2/source/model/main/Title.cxx @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <Title.hxx> +#include <LinePropertiesHelper.hxx> +#include <FillProperties.hxx> +#include <CloneHelper.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <cppuhelper/supportsservice.hxx> + +#include <vector> +#include <algorithm> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans::PropertyAttribute; + +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; + +namespace +{ + +enum +{ + PROP_TITLE_PARA_ADJUST, + PROP_TITLE_PARA_LAST_LINE_ADJUST, + PROP_TITLE_PARA_LEFT_MARGIN, + PROP_TITLE_PARA_RIGHT_MARGIN, + PROP_TITLE_PARA_TOP_MARGIN, + PROP_TITLE_PARA_BOTTOM_MARGIN, + PROP_TITLE_PARA_IS_HYPHENATION, + PROP_TITLE_VISIBLE, + + PROP_TITLE_TEXT_ROTATION, + PROP_TITLE_TEXT_STACKED, + PROP_TITLE_REL_POS, + + PROP_TITLE_REF_PAGE_SIZE +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "ParaAdjust", + PROP_TITLE_PARA_ADJUST, + cppu::UnoType<css::style::ParagraphAdjust>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaLastLineAdjust", + PROP_TITLE_PARA_LAST_LINE_ADJUST, + cppu::UnoType<sal_Int16>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaLeftMargin", + PROP_TITLE_PARA_LEFT_MARGIN, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaRightMargin", + PROP_TITLE_PARA_RIGHT_MARGIN, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaTopMargin", + PROP_TITLE_PARA_TOP_MARGIN, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaBottomMargin", + PROP_TITLE_PARA_BOTTOM_MARGIN, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaIsHyphenation", + PROP_TITLE_PARA_IS_HYPHENATION, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + + rOutProperties.emplace_back( "Visible", + PROP_TITLE_VISIBLE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextRotation", + PROP_TITLE_TEXT_ROTATION, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "StackCharacters", + PROP_TITLE_TEXT_STACKED, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "RelativePosition", + PROP_TITLE_REL_POS, + cppu::UnoType<chart2::RelativePosition>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_TITLE_REF_PAGE_SIZE, + cppu::UnoType<awt::Size>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticTitleDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // ParagraphProperties + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_PARA_ADJUST, + css::style::ParagraphAdjust_CENTER ); + // PROP_TITLE_PARA_LAST_LINE_ADJUST + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_LEFT_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_RIGHT_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_TOP_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_BOTTOM_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_PARA_IS_HYPHENATION, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_VISIBLE, true ); + + // own properties + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_TITLE_TEXT_ROTATION, 0.0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_TEXT_STACKED, false ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + } +}; + +struct StaticTitleDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticTitleDefaults_Initializer > +{ +}; + +struct StaticTitleInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::FillProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticTitleInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticTitleInfoHelper_Initializer > +{ +}; + +struct StaticTitleInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticTitleInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticTitleInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticTitleInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +Title::Title() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +Title::Title( const Title & rOther ) : + impl::Title_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{ + CloneHelper::CloneRefSequence<chart2::XFormattedString>( + rOther.m_aStrings, m_aStrings ); + ModifyListenerHelper::addListenerToAllElements( + comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( m_aStrings ), + m_xModifyEventForwarder ); +} + +Title::~Title() +{ + ModifyListenerHelper::removeListenerFromAllElements( + comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( m_aStrings ), + m_xModifyEventForwarder ); +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL Title::createClone() +{ + return uno::Reference< util::XCloneable >( new Title( *this )); +} + +// ____ XTitle ____ +uno::Sequence< uno::Reference< chart2::XFormattedString > > SAL_CALL Title::getText() +{ + MutexGuard aGuard( m_aMutex ); + return m_aStrings; +} + +void SAL_CALL Title::setText( const uno::Sequence< uno::Reference< chart2::XFormattedString > >& rNewStrings ) +{ + uno::Sequence< uno::Reference< chart2::XFormattedString > > aOldStrings; + { + MutexGuard aGuard( m_aMutex ); + std::swap( m_aStrings, aOldStrings ); + m_aStrings = rNewStrings; + } + //don't keep the mutex locked while calling out + ModifyListenerHelper::removeListenerFromAllElements( + comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( aOldStrings ), + m_xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( + comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( rNewStrings ), + m_xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ OPropertySet ____ +void Title::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticTitleDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Title::getInfoHelper() +{ + return *StaticTitleInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL Title::getPropertySetInfo() +{ + return *StaticTitleInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Title::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL Title::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL Title::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL Title::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void Title::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void Title::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +OUString SAL_CALL Title::getImplementationName() +{ + return "com.sun.star.comp.chart2.Title"; +} + +sal_Bool SAL_CALL Title::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL Title::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.Title", + "com.sun.star.style.ParagraphProperties", + "com.sun.star.beans.PropertySet", + "com.sun.star.layout.LayoutElement" }; +} + +// needed by MSC compiler +using impl::Title_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( Title, Title_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( Title, Title_Base, ::property::OPropertySet ) + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_Title_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::Title); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/UndoManager.cxx b/chart2/source/model/main/UndoManager.cxx new file mode 100644 index 000000000..63dacf484 --- /dev/null +++ b/chart2/source/model/main/UndoManager.cxx @@ -0,0 +1,349 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "UndoManager.hxx" +#include <ChartViewHelper.hxx> + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> + +#include <framework/undomanagerhelper.hxx> +#include <framework/imutex.hxx> +#include <officecfg/Office/Common.hxx> +#include <svl/undo.hxx> + +namespace chart +{ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::document::XUndoManager; + using ::com::sun::star::document::XUndoAction; + using ::com::sun::star::document::XUndoManagerListener; + using ::com::sun::star::lang::NoSupportException; + using ::com::sun::star::util::XModifyListener; + using ::com::sun::star::frame::XModel; + + namespace impl + { + class UndoManager_Impl : public ::framework::IUndoManagerImplementation + { + public: + UndoManager_Impl( UndoManager& i_antiImpl, ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex ) + :m_rAntiImpl( i_antiImpl ) + ,m_rParent( i_parent ) + ,m_rMutex( i_mutex ) + ,m_bDisposed( false ) + ,m_aUndoHelper( *this ) + { + m_aUndoManager.SetMaxUndoActionCount( + officecfg::Office::Common::Undo::Steps::get()); + } + + virtual ~UndoManager_Impl() + { + } + + ::osl::Mutex& getMutex(); + // IUndoManagerImplementation + virtual SfxUndoManager& getImplUndoManager() override; + virtual Reference< XUndoManager > getThis() override; + + // attribute access + ::cppu::OWeakObject& getParent() { return m_rParent; } + ::framework::UndoManagerHelper& getUndoHelper() { return m_aUndoHelper; } + + // public interface + + /// is called when the owner of the UndoManager is being disposed + void disposing(); + + /// checks whether we're already disposed, throws a DisposedException if so + void checkDisposed_lck(); + + private: + UndoManager& m_rAntiImpl; + ::cppu::OWeakObject& m_rParent; + ::osl::Mutex& m_rMutex; + bool m_bDisposed; + + SfxUndoManager m_aUndoManager; + ::framework::UndoManagerHelper m_aUndoHelper; + }; + + ::osl::Mutex& UndoManager_Impl::getMutex() + { + return m_rMutex; + } + + SfxUndoManager& UndoManager_Impl::getImplUndoManager() + { + return m_aUndoManager; + } + + Reference< XUndoManager > UndoManager_Impl::getThis() + { + return &m_rAntiImpl; + } + + void UndoManager_Impl::disposing() + { + { + ::osl::MutexGuard aGuard( m_rMutex ); + m_bDisposed = true; + } + m_aUndoHelper.disposing(); + } + + void UndoManager_Impl::checkDisposed_lck() + { + if ( m_bDisposed ) + throw DisposedException( OUString(), getThis() ); + } + + namespace { + + /** guard for public UNO methods of the UndoManager + + The only purpose of this guard is to check for the instance being disposed already. Everything else, + in particular the IMutexGuard functionality required by the UndoManagerHelper class, is a dummy only, + as all involved classes (means we ourselves, the UndoManagerHelper, the SfxUndoManager, and the Undo actions + we create) are inherently thread-safe, thus need no external lock (in particular no SolarMutex!). + */ + class UndoManagerMethodGuard : public ::framework::IMutexGuard + { + public: + explicit UndoManagerMethodGuard( UndoManager_Impl& i_impl ) + { + ::osl::MutexGuard aGuard( i_impl.getMutex() ); + // throw if the instance is already disposed + i_impl.checkDisposed_lck(); + } + virtual ~UndoManagerMethodGuard() + { + } + + // IMutexGuard + virtual void clear() override; + virtual ::framework::IMutex& getGuardedMutex() override; + }; + + class DummyMutex : public ::framework::IMutex + { + public: + virtual ~DummyMutex() {} + virtual void acquire() override { } + virtual void release() override { } + }; + + } + + ::framework::IMutex& UndoManagerMethodGuard::getGuardedMutex() + { + static DummyMutex s_aDummyMutex; + return s_aDummyMutex; + } + + void UndoManagerMethodGuard::clear() + { + // nothing to do. This interface implementation is a dummy. + } + } + + using impl::UndoManagerMethodGuard; + + UndoManager::UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex ) + :m_pImpl( new impl::UndoManager_Impl( *this, i_parent, i_mutex ) ) + { + } + + UndoManager::~UndoManager() + { + } + + void SAL_CALL UndoManager::acquire() noexcept + { + m_pImpl->getParent().acquire(); + } + + void SAL_CALL UndoManager::release() noexcept + { + m_pImpl->getParent().release(); + } + + void UndoManager::disposing() + { + m_pImpl->disposing(); + } + + void SAL_CALL UndoManager::enterUndoContext( const OUString& i_title ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().enterUndoContext( i_title, aGuard ); + } + + void SAL_CALL UndoManager::enterHiddenUndoContext( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().enterHiddenUndoContext( aGuard ); + } + + void SAL_CALL UndoManager::leaveUndoContext( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().leaveUndoContext( aGuard ); + } + + void SAL_CALL UndoManager::addUndoAction( const Reference< XUndoAction >& i_action ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().addUndoAction( i_action, aGuard ); + } + + void SAL_CALL UndoManager::undo( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().undo( aGuard ); + + ChartViewHelper::setViewToDirtyState( Reference< XModel >( getParent(), UNO_QUERY ) ); + } + + void SAL_CALL UndoManager::redo( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().redo( aGuard ); + + ChartViewHelper::setViewToDirtyState( Reference< XModel >( getParent(), UNO_QUERY ) ); + } + + sal_Bool SAL_CALL UndoManager::isUndoPossible( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().isUndoPossible(); + } + + sal_Bool SAL_CALL UndoManager::isRedoPossible( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().isRedoPossible(); + } + + OUString SAL_CALL UndoManager::getCurrentUndoActionTitle( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().getCurrentUndoActionTitle(); + } + + OUString SAL_CALL UndoManager::getCurrentRedoActionTitle( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().getCurrentRedoActionTitle(); + } + + Sequence< OUString > SAL_CALL UndoManager::getAllUndoActionTitles( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().getAllUndoActionTitles(); + } + + Sequence< OUString > SAL_CALL UndoManager::getAllRedoActionTitles( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().getAllRedoActionTitles(); + } + + void SAL_CALL UndoManager::clear( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().clear( aGuard ); + } + + void SAL_CALL UndoManager::clearRedo( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().clearRedo( aGuard ); + } + + void SAL_CALL UndoManager::reset( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().reset( aGuard ); + } + + void SAL_CALL UndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().addUndoManagerListener( i_listener ); + } + + void SAL_CALL UndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().removeUndoManagerListener( i_listener ); + } + + void SAL_CALL UndoManager::lock( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().lock(); + } + + void SAL_CALL UndoManager::unlock( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().unlock(); + } + + sal_Bool SAL_CALL UndoManager::isLocked( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getUndoHelper().isLocked(); + } + + Reference< XInterface > SAL_CALL UndoManager::getParent( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + return m_pImpl->getParent(); + } + + void SAL_CALL UndoManager::setParent( const Reference< XInterface >& ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + throw NoSupportException( OUString(), m_pImpl->getThis() ); + } + + void SAL_CALL UndoManager::addModifyListener( const Reference< XModifyListener >& i_listener ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().addModifyListener( i_listener ); + } + + void SAL_CALL UndoManager::removeModifyListener( const Reference< XModifyListener >& i_listener ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().removeModifyListener( i_listener ); + } + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/UndoManager.hxx b/chart2/source/model/main/UndoManager.hxx new file mode 100644 index 000000000..4d0a214e5 --- /dev/null +++ b/chart2/source/model/main/UndoManager.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/document/XUndoManager.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> + +#include <cppuhelper/implbase2.hxx> + +#include <memory> + +namespace chart +{ + + namespace impl + { + class UndoManager_Impl; + typedef ::cppu::ImplHelper2 < css::document::XUndoManager + , css::util::XModifyBroadcaster + > UndoManager_Base; + } + + class UndoManager : public impl::UndoManager_Base + { + public: + UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex ); + virtual ~UndoManager(); + + // XInterface + virtual void SAL_CALL acquire( ) noexcept override; + virtual void SAL_CALL release( ) noexcept override; + + // XComponent equivalents + void disposing(); + + // XUndoManager + virtual void SAL_CALL enterUndoContext( const OUString& i_title ) override; + virtual void SAL_CALL enterHiddenUndoContext( ) override; + virtual void SAL_CALL leaveUndoContext( ) override; + virtual void SAL_CALL addUndoAction( const css::uno::Reference< css::document::XUndoAction >& i_action ) override; + virtual void SAL_CALL undo( ) override; + virtual void SAL_CALL redo( ) override; + virtual sal_Bool SAL_CALL isUndoPossible( ) override; + virtual sal_Bool SAL_CALL isRedoPossible( ) override; + virtual OUString SAL_CALL getCurrentUndoActionTitle( ) override; + virtual OUString SAL_CALL getCurrentRedoActionTitle( ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getAllUndoActionTitles( ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getAllRedoActionTitles( ) override; + virtual void SAL_CALL clear( ) override; + virtual void SAL_CALL clearRedo( ) override; + virtual void SAL_CALL reset( ) override; + virtual void SAL_CALL addUndoManagerListener( const css::uno::Reference< css::document::XUndoManagerListener >& i_listener ) override; + virtual void SAL_CALL removeUndoManagerListener( const css::uno::Reference< css::document::XUndoManagerListener >& i_listener ) override; + + // XLockable (base of XUndoManager) + virtual void SAL_CALL lock( ) override; + virtual void SAL_CALL unlock( ) override; + virtual sal_Bool SAL_CALL isLocked( ) override; + + // XChild (base of XUndoManager) + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override; + virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override; + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + + private: + std::unique_ptr< impl::UndoManager_Impl > m_pImpl; + }; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Wall.cxx b/chart2/source/model/main/Wall.cxx new file mode 100644 index 000000000..f139a3e9d --- /dev/null +++ b/chart2/source/model/main/Wall.cxx @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "Wall.hxx" +#include <LinePropertiesHelper.hxx> +#include <FillProperties.hxx> +#include <UserDefinedProperties.hxx> +#include <PropertyHelper.hxx> +#include <ModifyListenerHelper.hxx> +#include <com/sun/star/drawing/LineStyle.hpp> + +#include <vector> +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticWallDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + } +}; + +struct StaticWallDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticWallDefaults_Initializer > +{ +}; + +struct StaticWallInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); + ::chart::FillProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticWallInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticWallInfoHelper_Initializer > +{ +}; + +struct StaticWallInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticWallInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticWallInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticWallInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +Wall::Wall() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +Wall::Wall( const Wall & rOther ) : + impl::Wall_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) +{} + +Wall::~Wall() +{} + +// ____ XTypeProvider ____ +uno::Sequence< css::uno::Type > SAL_CALL Wall::getTypes() +{ + return ::comphelper::concatSequences( + impl::Wall_Base::getTypes(), + ::property::OPropertySet::getTypes()); +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL Wall::createClone() +{ + return uno::Reference< util::XCloneable >( new Wall( *this )); +} + +// ____ OPropertySet ____ +void Wall::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticWallDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Wall::getInfoHelper() +{ + return *StaticWallInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL Wall::getPropertySetInfo() +{ + return *StaticWallInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Wall::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->addModifyListener( aListener ); +} + +void SAL_CALL Wall::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + m_xModifyEventForwarder->removeModifyListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL Wall::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL Wall::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void Wall::firePropertyChangeEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +using impl::Wall_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( Wall, Wall_Base, ::property::OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Wall.hxx b/chart2/source/model/main/Wall.hxx new file mode 100644 index 000000000..696772438 --- /dev/null +++ b/chart2/source/model/main/Wall.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <com/sun/star/util/XCloneable.hpp> +#include <OPropertySet.hxx> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/uno3.hxx> +#include <ModifyListenerHelper.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + Wall_Base; +} + +class Wall final : + public cppu::BaseMutex, + public impl::Wall_Base, + public ::property::OPropertySet +{ +public: + Wall(); + virtual ~Wall() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + + explicit Wall( const Wall & rOther ); + + // ____ XTypeProvider ____ + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + virtual void SAL_CALL removeModifyListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ) override; + +private: + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const css::lang::EventObject& aEvent ) override; + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const css::lang::EventObject& Source ) override; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + +private: + + rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/AreaChartType.cxx b/chart2/source/model/template/AreaChartType.cxx new file mode 100644 index 000000000..b0581ddc8 --- /dev/null +++ b/chart2/source/model/template/AreaChartType.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "AreaChartType.hxx" +#include <servicenames_charttypes.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +namespace chart +{ + +AreaChartType::AreaChartType() +{} + +AreaChartType::AreaChartType( const AreaChartType & rOther ) : + ChartType( rOther ) +{} + +AreaChartType::~AreaChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL AreaChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new AreaChartType( *this )); +} + +rtl::Reference< ChartType > AreaChartType::cloneChartType() const +{ + return new AreaChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL AreaChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_AREA; +} + +OUString SAL_CALL AreaChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.AreaChartType"; +} + +sal_Bool SAL_CALL AreaChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL AreaChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_AREA, + "com.sun.star.chart2.ChartType" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_AreaChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::AreaChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/AreaChartType.hxx b/chart2/source/model/template/AreaChartType.hxx new file mode 100644 index 000000000..8ca01e1f3 --- /dev/null +++ b/chart2/source/model/template/AreaChartType.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class AreaChartType final : public ChartType +{ +public: + explicit AreaChartType(); + virtual ~AreaChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit AreaChartType( const AreaChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/AreaChartTypeTemplate.cxx b/chart2/source/model/template/AreaChartTypeTemplate.cxx new file mode 100644 index 000000000..32df26a18 --- /dev/null +++ b/chart2/source/model/template/AreaChartTypeTemplate.cxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "AreaChartTypeTemplate.hxx" +#include "AreaChartType.hxx" +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +enum +{ + PROP_AREA_TEMPLATE_DIMENSION +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "Dimension", + PROP_AREA_TEMPLATE_DIMENSION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticAreaChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aStaticDefaults, PROP_AREA_TEMPLATE_DIMENSION, 2 ); + return &aStaticDefaults; + } +}; + +struct StaticAreaChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticAreaChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticAreaChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticAreaChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticAreaChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticAreaChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticAreaChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticAreaChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticAreaChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +AreaChartTypeTemplate::AreaChartTypeTemplate( + uno::Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + sal_Int32 nDim /* = 2 */ ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ) +{ + setFastPropertyValue_NoBroadcast( PROP_AREA_TEMPLATE_DIMENSION, uno::Any( nDim )); +} + +AreaChartTypeTemplate::~AreaChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void AreaChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticAreaChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL AreaChartTypeTemplate::getInfoHelper() +{ + return *StaticAreaChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL AreaChartTypeTemplate::getPropertySetInfo() +{ + return *StaticAreaChartTypeTemplateInfo::get(); +} + +sal_Int32 AreaChartTypeTemplate::getDimension() const +{ + sal_Int32 nDim = 2; + try + { + // note: UNO-methods are never const + const_cast< AreaChartTypeTemplate * >( this )-> + getFastPropertyValue( PROP_AREA_TEMPLATE_DIMENSION ) >>= nDim; + } + catch( const beans::UnknownPropertyException & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return nDim; +} + +StackMode AreaChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return m_eStackMode; +} + +// ____ ChartTypeTemplate ____ +void AreaChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); +} + +void AreaChartTypeTemplate::resetStyles2( const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + ChartTypeTemplate::resetStyles2( xDiagram ); + std::vector< rtl::Reference< ::chart::DataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + uno::Any aLineStyleAny( drawing::LineStyle_NONE ); + for (auto const& series : aSeriesVec) + { + if( series->getPropertyValue( "BorderStyle") == aLineStyleAny ) + { + series->setPropertyToDefault( "BorderStyle"); + } + } +} + +rtl::Reference< ChartType > AreaChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + return new AreaChartType(); +} + +rtl::Reference< ChartType > AreaChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult( getChartTypeForIndex( 0 ) ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + return xResult; +} + +IMPLEMENT_FORWARD_XINTERFACE2( AreaChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( AreaChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/AreaChartTypeTemplate.hxx b/chart2/source/model/template/AreaChartTypeTemplate.hxx new file mode 100644 index 000000000..3116c0d59 --- /dev/null +++ b/chart2/source/model/template/AreaChartTypeTemplate.hxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <StackMode.hxx> + +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class AreaChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + explicit AreaChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + sal_Int32 nDim = 2 ); + virtual ~AreaChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void resetStyles2( + const rtl::Reference< ::chart::Diagram >& xDiagram ) override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + +private: + StackMode m_eStackMode; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BarChartType.cxx b/chart2/source/model/template/BarChartType.cxx new file mode 100644 index 000000000..2a94db82b --- /dev/null +++ b/chart2/source/model/template/BarChartType.cxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "BarChartType.hxx" +#include <servicenames_charttypes.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +namespace chart +{ + +BarChartType::BarChartType() +{} + +BarChartType::BarChartType( const BarChartType & rOther ) : + ChartType( rOther ) +{ +} + +BarChartType::~BarChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL BarChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new BarChartType( *this )); +} + +rtl::Reference< ChartType > BarChartType::cloneChartType() const +{ + return new BarChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL BarChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_BAR; +} + +uno::Sequence< OUString > BarChartType::getSupportedPropertyRoles() +{ + return { "FillColor", "BorderColor" }; +} + +OUString SAL_CALL BarChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.BarChartType"; +} + +sal_Bool SAL_CALL BarChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL BarChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_BAR, + "com.sun.star.chart2.ChartType" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_BarChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::BarChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BarChartType.hxx b/chart2/source/model/template/BarChartType.hxx new file mode 100644 index 000000000..cceaf0577 --- /dev/null +++ b/chart2/source/model/template/BarChartType.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class BarChartType final : public ChartType +{ +public: + explicit BarChartType(); + virtual ~BarChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit BarChartType( const BarChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedPropertyRoles() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BarChartTypeTemplate.cxx b/chart2/source/model/template/BarChartTypeTemplate.cxx new file mode 100644 index 000000000..0c3ca6566 --- /dev/null +++ b/chart2/source/model/template/BarChartTypeTemplate.cxx @@ -0,0 +1,292 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "BarChartTypeTemplate.hxx" +#include "ColumnChartType.hxx" +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_BAR_TEMPLATE_DIMENSION, + PROP_BAR_TEMPLATE_GEOMETRY3D +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "Dimension", + PROP_BAR_TEMPLATE_DIMENSION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Geometry3D", + PROP_BAR_TEMPLATE_GEOMETRY3D, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticBarChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_BAR_TEMPLATE_DIMENSION, 2 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_BAR_TEMPLATE_GEOMETRY3D, ::chart2::DataPointGeometry3D::CUBOID ); + } +}; + +struct StaticBarChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticBarChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticBarChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticBarChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticBarChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticBarChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticBarChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticBarChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticBarChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +BarChartTypeTemplate::BarChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + BarDirection eDirection, + sal_Int32 nDim /* = 2 */ ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ), + m_eBarDirection( eDirection ), + m_nDim( nDim ) +{} + +BarChartTypeTemplate::~BarChartTypeTemplate() +{} + +sal_Int32 BarChartTypeTemplate::getDimension() const +{ + return m_nDim; +} + +StackMode BarChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return m_eStackMode; +} + +bool BarChartTypeTemplate::isSwapXAndY() const +{ + return (m_eBarDirection == HORIZONTAL); +} + +// ____ ChartTypeTemplate ____ +bool BarChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties ); + + //check BarDirection + if( bResult ) + { + bool bFound = false; + bool bAmbiguous = false; + bool bVertical = DiagramHelper::getVertical( xDiagram, bFound, bAmbiguous ); + if( m_eBarDirection == HORIZONTAL ) + bResult = bVertical; + else if( m_eBarDirection == VERTICAL ) + bResult = !bVertical; + } + + // adapt solid-type of template according to values in series + if( bAdaptProperties && + bResult && + getDimension() == 3 ) + { + + bool bGeomFound = false, bGeomAmbiguous = false; + sal_Int32 aCommonGeom = DiagramHelper::getGeometry3D( xDiagram, bGeomFound, bGeomAmbiguous ); + + if( !bGeomAmbiguous ) + { + setFastPropertyValue_NoBroadcast( + PROP_BAR_TEMPLATE_GEOMETRY3D, uno::Any( aCommonGeom )); + } + } + + return bResult; +} + +rtl::Reference< ChartType > BarChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + return new ColumnChartType(); +} + +rtl::Reference< ChartType > BarChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult( getChartTypeForIndex( 0 ) ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + return xResult; +} + +// ____ OPropertySet ____ +void BarChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticBarChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL BarChartTypeTemplate::getInfoHelper() +{ + return *StaticBarChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL BarChartTypeTemplate::getPropertySetInfo() +{ + return *StaticBarChartTypeTemplateInfo::get(); +} + +void BarChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); + if( getDimension() != 3 ) + return; + + try + { + //apply Geometry3D + uno::Any aAGeometry3D; + getFastPropertyValue( aAGeometry3D, PROP_BAR_TEMPLATE_GEOMETRY3D ); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "Geometry3D", aAGeometry3D ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void BarChartTypeTemplate::resetStyles2( + const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + ChartTypeTemplate::resetStyles2( xDiagram ); + std::vector< rtl::Reference< DataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + uno::Any aLineStyleAny( drawing::LineStyle_NONE ); + for (auto const& series : aSeriesVec) + { + if( getDimension() == 3 ) + series->setPropertyToDefault( "Geometry3D"); + if( series->getPropertyValue( "BorderStyle") == aLineStyleAny ) + { + series->setPropertyToDefault( "BorderStyle"); + } + } + + DiagramHelper::setVertical( xDiagram, false ); +} + +void BarChartTypeTemplate::createCoordinateSystems( + const rtl::Reference< ::chart::Diagram > & xDiagram ) +{ + ChartTypeTemplate::createCoordinateSystems( xDiagram ); + + DiagramHelper::setVertical( xDiagram, m_eBarDirection == HORIZONTAL ); +} + +IMPLEMENT_FORWARD_XINTERFACE2( BarChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( BarChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BarChartTypeTemplate.hxx b/chart2/source/model/template/BarChartTypeTemplate.hxx new file mode 100644 index 000000000..62188279e --- /dev/null +++ b/chart2/source/model/template/BarChartTypeTemplate.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +#include <ChartTypeTemplate.hxx> +#include <StackMode.hxx> + +namespace chart +{ + +class BarChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + enum BarDirection + { + HORIZONTAL, + VERTICAL + }; + + explicit BarChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + BarDirection eDirection, + sal_Int32 nDim = 2 ); + virtual ~BarChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void resetStyles2( + const rtl::Reference< ::chart::Diagram >& xDiagram ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + virtual bool isSwapXAndY() const override; + + virtual void createCoordinateSystems( + const rtl::Reference< ::chart::Diagram > & xDiagram ) override; + +private: + StackMode m_eStackMode; + BarDirection m_eBarDirection; + sal_Int32 m_nDim; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BubbleChartType.cxx b/chart2/source/model/template/BubbleChartType.cxx new file mode 100644 index 000000000..3521f7909 --- /dev/null +++ b/chart2/source/model/template/BubbleChartType.cxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "BubbleChartType.hxx" +#include <PropertyHelper.hxx> +#include <servicenames_charttypes.hxx> +#include <CartesianCoordinateSystem.hxx> +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <AxisIndexDefines.hxx> +#include <com/sun/star/chart2/AxisType.hpp> +#include <cppuhelper/supportsservice.hxx> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +struct StaticBubbleChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + return &aStaticDefaults; + } +}; + +struct StaticBubbleChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticBubbleChartTypeDefaults_Initializer > +{ +}; + +struct StaticBubbleChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticBubbleChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticBubbleChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticBubbleChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticBubbleChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticBubbleChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticBubbleChartTypeInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +BubbleChartType::BubbleChartType() +{ +} + +BubbleChartType::BubbleChartType( const BubbleChartType & rOther ) : + ChartType( rOther ) +{ +} + +BubbleChartType::~BubbleChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL BubbleChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new BubbleChartType( *this )); +} + +rtl::Reference< ChartType > BubbleChartType::cloneChartType() const +{ + return new BubbleChartType( *this ); +} + +// ____ XChartType ____ +rtl::Reference< ::chart::BaseCoordinateSystem > + BubbleChartType::createCoordinateSystem2( sal_Int32 DimensionCount ) +{ + rtl::Reference< CartesianCoordinateSystem > xResult = + new CartesianCoordinateSystem( DimensionCount ); + + for( sal_Int32 i=0; i<DimensionCount; ++i ) + { + rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX ); + if( !xAxis.is() ) + { + OSL_FAIL("a created coordinate system should have an axis for each dimension"); + continue; + } + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + + if( i == 2 ) + aScaleData.AxisType = chart2::AxisType::SERIES; + else + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + + xAxis->setScaleData( aScaleData ); + } + + return xResult; +} + +OUString SAL_CALL BubbleChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE; +} + +uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedMandatoryRoles() +{ + return { "label", "values-x", "values-y", "values-size" }; +} + +uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedPropertyRoles() +{ + return { "FillColor", "BorderColor" }; +} + +OUString SAL_CALL BubbleChartType::getRoleOfSequenceForSeriesLabel() +{ + return "values-size"; +} + +// ____ OPropertySet ____ +void BubbleChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticBubbleChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartType::getInfoHelper() +{ + return *StaticBubbleChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL BubbleChartType::getPropertySetInfo() +{ + return *StaticBubbleChartTypeInfo::get(); +} + +OUString SAL_CALL BubbleChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.BubbleChartType"; +} + +sal_Bool SAL_CALL BubbleChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_BubbleChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::BubbleChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BubbleChartType.hxx b/chart2/source/model/template/BubbleChartType.hxx new file mode 100644 index 000000000..a2afa7e69 --- /dev/null +++ b/chart2/source/model/template/BubbleChartType.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class BubbleChartType final : public ChartType +{ +public: + explicit BubbleChartType(); + virtual ~BubbleChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit BubbleChartType( const BubbleChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedMandatoryRoles() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedPropertyRoles() override; + virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + virtual rtl::Reference< ::chart::BaseCoordinateSystem > + createCoordinateSystem2( sal_Int32 DimensionCount ) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.cxx b/chart2/source/model/template/BubbleChartTypeTemplate.cxx new file mode 100644 index 000000000..b09c9b9da --- /dev/null +++ b/chart2/source/model/template/BubbleChartTypeTemplate.cxx @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "BubbleChartTypeTemplate.hxx" +#include "BubbleChartType.hxx" +#include "BubbleDataInterpreter.hxx" +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <PropertyHelper.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticBubbleChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + return &aStaticDefaults; + } +}; + +struct StaticBubbleChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticBubbleChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticBubbleChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticBubbleChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticBubbleChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticBubbleChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticBubbleChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticBubbleChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticBubbleChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +BubbleChartTypeTemplate::BubbleChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ) +{ +} + +BubbleChartTypeTemplate::~BubbleChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void BubbleChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticBubbleChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartTypeTemplate::getInfoHelper() +{ + return *StaticBubbleChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL BubbleChartTypeTemplate::getPropertySetInfo() +{ + return *StaticBubbleChartTypeTemplateInfo::get(); +} + +sal_Int32 BubbleChartTypeTemplate::getDimension() const +{ + return 2; +} + +StackMode BubbleChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return StackMode::NONE; +} + +void BubbleChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL BubbleChartTypeTemplate::supportsCategories() +{ + return false; +} + +rtl::Reference< ChartType > BubbleChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + return new BubbleChartType(); +} + +rtl::Reference< ChartType > BubbleChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new BubbleChartType(); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< DataInterpreter > BubbleChartTypeTemplate::getDataInterpreter2() +{ + if( ! m_xDataInterpreter.is()) + m_xDataInterpreter.set( new BubbleDataInterpreter ); + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2( BubbleChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( BubbleChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.hxx b/chart2/source/model/template/BubbleChartTypeTemplate.hxx new file mode 100644 index 000000000..f4e5c9b3c --- /dev/null +++ b/chart2/source/model/template/BubbleChartTypeTemplate.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class BubbleChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + explicit BubbleChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName ); + virtual ~BubbleChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual sal_Bool SAL_CALL supportsCategories() override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BubbleDataInterpreter.cxx b/chart2/source/model/template/BubbleDataInterpreter.cxx new file mode 100644 index 000000000..7243b43aa --- /dev/null +++ b/chart2/source/model/template/BubbleDataInterpreter.cxx @@ -0,0 +1,278 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cstddef> + +#include "BubbleDataInterpreter.hxx" +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <CommonConverters.hxx> +#include <com/sun/star/util/XCloneable.hpp> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +BubbleDataInterpreter::BubbleDataInterpreter() +{ +} + +BubbleDataInterpreter::~BubbleDataInterpreter() +{ +} + +// ____ XDataInterpreter ____ +InterpretedData BubbleDataInterpreter::interpretDataSource( + const Reference< chart2::data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = DataInterpreter::getDataSequences(xSource); + + uno::Reference< chart2::data::XLabeledDataSequence > xValuesX; + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aYValuesVector; + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSizeValuesVector; + + uno::Reference< chart2::data::XLabeledDataSequence > xCategories; + bool bHasCategories = HasCategories( aArguments, aData ); + bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); + + sal_Int32 nDataSeqCount = aData.size(); + + bool bSetXValues = bHasCategories ? ( (nDataSeqCount-1) > 2 && (nDataSeqCount-1) % 2 != 0 ) + :( nDataSeqCount > 2 && nDataSeqCount % 2 != 0 ); + + bool bCategoriesUsed = false; + bool bNextIsYValues = bHasCategories ? nDataSeqCount>2 : nDataSeqCount>1; + for( sal_Int32 nDataIdx = 0; nDataIdx < nDataSeqCount; ++nDataIdx ) + { + try + { + if( bHasCategories && !bCategoriesUsed ) + { + xCategories = aData[nDataIdx]; + if( xCategories.is()) + { + SetRole( xCategories->getValues(), "categories"); + if( bUseCategoriesAsX ) + { + bSetXValues = false; + bNextIsYValues = nDataSeqCount > 2; + } + } + bCategoriesUsed = true; + } + else if( !xValuesX.is() && bSetXValues ) + { + xValuesX = aData[nDataIdx]; + if( xValuesX.is()) + SetRole( xValuesX->getValues(), "values-x"); + } + else if( bNextIsYValues ) + { + aYValuesVector.push_back( aData[nDataIdx] ); + if( aData[nDataIdx].is()) + SetRole( aData[nDataIdx]->getValues(), "values-y"); + bNextIsYValues = false; + } + else if( !bNextIsYValues ) + { + aSizeValuesVector.push_back( aData[nDataIdx] ); + if( aData[nDataIdx].is()) + SetRole( aData[nDataIdx]->getValues(), "values-size"); + bNextIsYValues = (nDataSeqCount-(nDataIdx+1)) >= 2;//two or more left + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + // create DataSeries + std::size_t nSeriesIndex = 0; + vector< rtl::Reference< DataSeries > > aSeriesVec; + aSeriesVec.reserve( aSizeValuesVector.size()); + + Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; + Reference< util::XCloneable > xCloneableX( xValuesX, uno::UNO_QUERY ); + + for( size_t nN = 0; nN < aSizeValuesVector.size(); ++nN, ++nSeriesIndex ) + { + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewData; + if( xValuesX.is() ) + { + if( nN > 0 && xCloneableX.is() ) + xClonedXValues.set( xCloneableX->createClone(), uno::UNO_QUERY ); + aNewData.push_back( xClonedXValues ); + } + if( aYValuesVector.size() > nN ) + aNewData.push_back( aYValuesVector[nN] ); + aNewData.push_back(aSizeValuesVector[nN]); + + rtl::Reference< DataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.size()) + xSeries = aSeriesToReUse[nSeriesIndex]; + else + xSeries = new DataSeries; + assert( xSeries.is() ); + xSeries->setData( aNewData ); + + aSeriesVec.push_back( xSeries ); + } + + return { { aSeriesVec }, xCategories }; +} + +InterpretedData BubbleDataInterpreter::reinterpretDataSeries( + const InterpretedData& aInterpretedData ) +{ + InterpretedData aResult( aInterpretedData ); + + sal_Int32 i=0; + std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + const sal_Int32 nCount = aSeries.size(); + for( ; i<nCount; ++i ) + { + try + { + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences; + + uno::Reference< chart2::data::XLabeledDataSequence > xValuesSize( + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-size" )); + uno::Reference< chart2::data::XLabeledDataSequence > xValuesY( + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-y" )); + uno::Reference< chart2::data::XLabeledDataSequence > xValuesX( + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-x" )); + + if( ! xValuesX.is() || + ! xValuesY.is() || + ! xValuesSize.is() ) + { + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValueSeqVec( + DataSeriesHelper::getAllDataSequencesByRole( + aSeries[i]->getDataSequences2(), "values" )); + if( xValuesX.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX )); + if( xValuesY.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY )); + if( xValuesSize.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesSize )); + + size_t nIndex = 0; + + if( ! xValuesSize.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesSize = aValueSeqVec[nIndex++]; + if( xValuesSize.is()) + SetRole( xValuesSize->getValues(), "values-size"); + } + + if( ! xValuesY.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesY = aValueSeqVec[nIndex++]; + if( xValuesY.is()) + SetRole( xValuesY->getValues(), "values-y"); + } + + if( ! xValuesX.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesX = aValueSeqVec[nIndex++]; + if( xValuesX.is()) + SetRole( xValuesY->getValues(), "values-x"); + } + } + if( xValuesSize.is()) + { + if( xValuesY.is() ) + { + if( xValuesX.is() ) + { + aNewSequences = { xValuesX, xValuesY, xValuesSize }; + } + else + { + aNewSequences = { xValuesY, xValuesSize }; + } + } + else + { + aNewSequences = { xValuesSize }; + } + } + + const std::vector< uno::Reference< data::XLabeledDataSequence > > & aSeqs = aSeries[i]->getDataSequences2(); + if( aSeqs.size() != aNewSequences.size() ) + { +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + for( auto const & j : aSeqs ) + { + assert( (j == xValuesY || j == xValuesX || j == xValuesSize) && "All sequences should be used" ); + } +#endif + aSeries[i]->setData( aNewSequences ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +bool BubbleDataInterpreter::isDataCompatible( + const InterpretedData& aInterpretedData ) +{ + const std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( rtl::Reference< DataSeries > const & dataSeries : aSeries ) + { + try + { + if( dataSeries->getDataSequences2().size() != 3 ) + return false; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return true; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/BubbleDataInterpreter.hxx b/chart2/source/model/template/BubbleDataInterpreter.hxx new file mode 100644 index 000000000..ff4b56de6 --- /dev/null +++ b/chart2/source/model/template/BubbleDataInterpreter.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <DataInterpreter.hxx> + +namespace chart +{ + +class BubbleDataInterpreter : public DataInterpreter +{ +public: + explicit BubbleDataInterpreter(); + virtual ~BubbleDataInterpreter() override; + +protected: + // ____ DataInterpreter ____ + virtual InterpretedData interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse ) override; + virtual InterpretedData reinterpretDataSeries( + const InterpretedData& aInterpretedData ) override; + virtual bool isDataCompatible( + const InterpretedData& aInterpretedData ) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/CandleStickChartType.cxx b/chart2/source/model/template/CandleStickChartType.cxx new file mode 100644 index 000000000..553a13748 --- /dev/null +++ b/chart2/source/model/template/CandleStickChartType.cxx @@ -0,0 +1,348 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "CandleStickChartType.hxx" +#include <PropertyHelper.hxx> +#include <StockBar.hxx> +#include <ModifyListenerHelper.hxx> +#include <servicenames_charttypes.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +enum +{ + PROP_CANDLESTICKCHARTTYPE_JAPANESE, + PROP_CANDLESTICKCHARTTYPE_WHITE_DAY, + PROP_CANDLESTICKCHARTTYPE_BLACK_DAY, + + PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST, + PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "Japanese", + PROP_CANDLESTICKCHARTTYPE_JAPANESE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "WhiteDay", + PROP_CANDLESTICKCHARTTYPE_WHITE_DAY, + cppu::UnoType<beans::XPropertySet>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "BlackDay", + PROP_CANDLESTICKCHARTTYPE_BLACK_DAY, + cppu::UnoType<beans::XPropertySet>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ShowFirst", + PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ShowHighLow", + PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticCandleStickChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + // must match default in CTOR! + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CANDLESTICKCHARTTYPE_JAPANESE, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW, true ); + } +}; + +struct StaticCandleStickChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticCandleStickChartTypeDefaults_Initializer > +{ +}; + +struct StaticCandleStickChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticCandleStickChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticCandleStickChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticCandleStickChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticCandleStickChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticCandleStickChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticCandleStickChartTypeInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +CandleStickChartType::CandleStickChartType() +{ + Reference< beans::XPropertySet > xWhiteDayProps( new ::chart::StockBar( true )); + Reference< beans::XPropertySet > xBlackDayProps( new ::chart::StockBar( false )); + + ModifyListenerHelper::addListener( xWhiteDayProps, m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( xBlackDayProps, m_xModifyEventForwarder ); + + setFastPropertyValue_NoBroadcast( + PROP_CANDLESTICKCHARTTYPE_WHITE_DAY, uno::Any( xWhiteDayProps )); + setFastPropertyValue_NoBroadcast( + PROP_CANDLESTICKCHARTTYPE_BLACK_DAY, uno::Any( xBlackDayProps )); +} + +CandleStickChartType::CandleStickChartType( const CandleStickChartType & rOther ) : + ChartType( rOther ) +{ + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_WHITE_DAY ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); + + getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_BLACK_DAY ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); +} + +CandleStickChartType::~CandleStickChartType() +{ + try + { + Reference< beans::XPropertySet > xPropertySet; + uno::Any aValue; + + getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_WHITE_DAY ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder ); + + getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_BLACK_DAY ); + if( ( aValue >>= xPropertySet ) + && xPropertySet.is()) + ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL CandleStickChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new CandleStickChartType( *this )); +} + +rtl::Reference< ChartType > CandleStickChartType::cloneChartType() const +{ + return new CandleStickChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL CandleStickChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK; +} + +uno::Sequence< OUString > SAL_CALL CandleStickChartType::getSupportedMandatoryRoles() +{ + bool bShowFirst = true; + bool bShowHiLow = false; + getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST ) >>= bShowFirst; + getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW ) >>= bShowHiLow; + + std::vector< OUString > aMandRoles; + + aMandRoles.emplace_back("label"); + if( bShowFirst ) + aMandRoles.emplace_back("values-first"); + + if( bShowHiLow ) + { + aMandRoles.emplace_back("values-min"); + aMandRoles.emplace_back("values-max"); + } + + aMandRoles.emplace_back("values-last"); + + return comphelper::containerToSequence( aMandRoles ); +} + +Sequence< OUString > SAL_CALL CandleStickChartType::getSupportedOptionalRoles() +{ + bool bShowFirst = true; + bool bShowHiLow = false; + getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST ) >>= bShowFirst; + getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW ) >>= bShowHiLow; + + std::vector< OUString > aOptRoles; + + if( ! bShowFirst ) + aOptRoles.emplace_back("values-first"); + + if( ! bShowHiLow ) + { + aOptRoles.emplace_back("values-min"); + aOptRoles.emplace_back("values-max"); + } + + return comphelper::containerToSequence( aOptRoles ); +} + +OUString SAL_CALL CandleStickChartType::getRoleOfSequenceForSeriesLabel() +{ + return "values-last"; +} + +// ____ OPropertySet ____ +void CandleStickChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticCandleStickChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL CandleStickChartType::getInfoHelper() +{ + return *StaticCandleStickChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL CandleStickChartType::getPropertySetInfo() +{ + return *StaticCandleStickChartTypeInfo::get(); +} + +void SAL_CALL CandleStickChartType::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, const uno::Any& rValue ) +{ + if( nHandle == PROP_CANDLESTICKCHARTTYPE_WHITE_DAY + || nHandle == PROP_CANDLESTICKCHARTTYPE_BLACK_DAY ) + { + uno::Any aOldValue; + Reference< util::XModifyBroadcaster > xBroadcaster; + getFastPropertyValue( aOldValue, nHandle ); + if( aOldValue.hasValue() && + (aOldValue >>= xBroadcaster) && + xBroadcaster.is()) + { + ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder ); + } + + OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE ); + if( rValue.hasValue() && + (rValue >>= xBroadcaster) && + xBroadcaster.is()) + { + ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder ); + } + } + + ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue ); +} + +OUString SAL_CALL CandleStickChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.CandleStickChartType" ; +} + +sal_Bool SAL_CALL CandleStickChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL CandleStickChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_CandleStickChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::CandleStickChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/CandleStickChartType.hxx b/chart2/source/model/template/CandleStickChartType.hxx new file mode 100644 index 000000000..e76107507 --- /dev/null +++ b/chart2/source/model/template/CandleStickChartType.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +// see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100797> "[10/11/12 Regression] using +// declaration causing virtual call with wrongly adjusted this pointer" before restoring 'final' +class CandleStickChartType /* final */ : public ChartType +{ +public: + explicit CandleStickChartType(); + virtual ~CandleStickChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit CandleStickChartType( const CandleStickChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedMandatoryRoles() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedOptionalRoles() override; + virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ OPropertySet ____ + virtual void SAL_CALL setFastPropertyValue_NoBroadcast + ( sal_Int32 nHandle, + const css::uno::Any& rValue ) override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ChartType.cxx b/chart2/source/model/template/ChartType.cxx new file mode 100644 index 000000000..eff91f9cc --- /dev/null +++ b/chart2/source/model/template/ChartType.cxx @@ -0,0 +1,335 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartType.hxx> +#include <CartesianCoordinateSystem.hxx> +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <CloneHelper.hxx> +#include <AxisIndexDefines.hxx> +#include <ModifyListenerHelper.hxx> +#include <DataSeries.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +ChartType::ChartType() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_bNotifyChanges( true ) +{} + +ChartType::ChartType( const ChartType & rOther ) : + impl::ChartType_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyEventForwarder() ), + m_bNotifyChanges( true ) +{ + { + SolarMutexGuard g; // access to rOther.m_aDataSeries + CloneHelper::CloneRefVector( + rOther.m_aDataSeries, m_aDataSeries); + } + ModifyListenerHelper::addListenerToAllElements( m_aDataSeries, m_xModifyEventForwarder ); +} + +ChartType::~ChartType() +{ + ModifyListenerHelper::removeListenerFromAllElements( m_aDataSeries, m_xModifyEventForwarder ); + m_aDataSeries.clear(); +} + +// ____ XChartType ____ +Reference< chart2::XCoordinateSystem > SAL_CALL + ChartType::createCoordinateSystem( ::sal_Int32 DimensionCount ) +{ + return createCoordinateSystem2(DimensionCount); +} + +rtl::Reference< BaseCoordinateSystem > + ChartType::createCoordinateSystem2( ::sal_Int32 DimensionCount ) +{ + rtl::Reference< CartesianCoordinateSystem > xResult = + new CartesianCoordinateSystem( DimensionCount ); + + for( sal_Int32 i=0; i<DimensionCount; ++i ) + { + rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX ); + if( !xAxis.is() ) + { + OSL_FAIL("a created coordinate system should have an axis for each dimension"); + continue; + } + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + + switch( i ) + { + case 0: aScaleData.AxisType = chart2::AxisType::CATEGORY; break; + case 2: aScaleData.AxisType = chart2::AxisType::SERIES; break; + default: aScaleData.AxisType = chart2::AxisType::REALNUMBER; break; + } + + xAxis->setScaleData( aScaleData ); + } + + return xResult; +} + +Sequence< OUString > SAL_CALL ChartType::getSupportedMandatoryRoles() +{ + return { "label", "values-y" }; +} + +Sequence< OUString > SAL_CALL ChartType::getSupportedOptionalRoles() +{ + return Sequence< OUString >(); +} + +Sequence< OUString > SAL_CALL ChartType::getSupportedPropertyRoles() +{ + return Sequence< OUString >(); +} + +OUString SAL_CALL ChartType::getRoleOfSequenceForSeriesLabel() +{ + return "values-y"; +} + +void ChartType::impl_addDataSeriesWithoutNotification( + const rtl::Reference< DataSeries >& xDataSeries ) +{ + if( std::find( m_aDataSeries.begin(), m_aDataSeries.end(), xDataSeries ) + != m_aDataSeries.end()) + throw lang::IllegalArgumentException("dataseries not found", static_cast<cppu::OWeakObject*>(this), 1); + + m_aDataSeries.push_back( xDataSeries ); + ModifyListenerHelper::addListener( xDataSeries, m_xModifyEventForwarder ); +} + +// ____ XDataSeriesContainer ____ +void SAL_CALL ChartType::addDataSeries( const Reference< chart2::XDataSeries >& xDataSeries ) +{ + rtl::Reference<DataSeries> xTmp = dynamic_cast<DataSeries*>(xDataSeries.get()); + assert(xTmp); + addDataSeries(xTmp); +} + +void ChartType::addDataSeries( const rtl::Reference< DataSeries >& xDataSeries ) +{ + SolarMutexGuard g; + + impl_addDataSeriesWithoutNotification( xDataSeries ); + fireModifyEvent(); +} + +void SAL_CALL ChartType::removeDataSeries( const Reference< chart2::XDataSeries >& xDataSeries ) +{ + rtl::Reference<DataSeries> xTmp = dynamic_cast<DataSeries*>(xDataSeries.get()); + assert(xTmp); + removeDataSeries(xTmp); +} + +void ChartType::removeDataSeries( const rtl::Reference< DataSeries >& xDataSeries ) +{ + if( !xDataSeries.is()) + throw container::NoSuchElementException(); + + SolarMutexGuard g; + + auto aIt = std::find( m_aDataSeries.begin(), m_aDataSeries.end(), xDataSeries ); + + if( aIt == m_aDataSeries.end()) + throw container::NoSuchElementException( + "The given series is no element of this charttype", + static_cast< uno::XWeak * >( this )); + + ModifyListenerHelper::removeListener( xDataSeries, m_xModifyEventForwarder ); + m_aDataSeries.erase( aIt ); + fireModifyEvent(); +} + +Sequence< Reference< chart2::XDataSeries > > SAL_CALL ChartType::getDataSeries() +{ + SolarMutexGuard g; + + return comphelper::containerToSequence< Reference< chart2::XDataSeries > >( m_aDataSeries ); +} + +void SAL_CALL ChartType::setDataSeries( const Sequence< Reference< chart2::XDataSeries > >& aDataSeries ) +{ + std::vector< rtl::Reference<DataSeries> > aTmp; + for (auto const & i : aDataSeries) + { + auto p = dynamic_cast<DataSeries*>(i.get()); + assert(p); + aTmp.push_back(p); + } + setDataSeries(aTmp); +} + +void ChartType::setDataSeries( const std::vector< rtl::Reference< DataSeries > >& aDataSeries ) +{ + SolarMutexGuard g; + + m_bNotifyChanges = false; + try + { + for( auto const & i : m_aDataSeries ) + ModifyListenerHelper::removeListener( i, m_xModifyEventForwarder ); + m_aDataSeries.clear(); + + for( auto const & i : aDataSeries ) + impl_addDataSeriesWithoutNotification( i ); + } + catch( ... ) + { + m_bNotifyChanges = true; + throw; + } + m_bNotifyChanges = true; + fireModifyEvent(); +} + +// ____ OPropertySet ____ +void ChartType::GetDefaultValue( sal_Int32 /* nHandle */, uno::Any& rAny ) const +{ + rAny.clear(); +} + +namespace +{ + +struct StaticChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( Sequence< beans::Property >{} ); + return &aPropHelper; + } +}; + +struct StaticChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticChartTypeInfo_Initializer > +{ +}; + +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL ChartType::getInfoHelper() +{ + return *StaticChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ChartType::getPropertySetInfo() +{ + return *StaticChartTypeInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL ChartType::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + m_xModifyEventForwarder->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL ChartType::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + m_xModifyEventForwarder->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XModifyListener ____ +void SAL_CALL ChartType::modified( const lang::EventObject& aEvent ) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL ChartType::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ OPropertySet ____ +void ChartType::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void ChartType::fireModifyEvent() +{ + bool bNotifyChanges; + + { + SolarMutexGuard g; + bNotifyChanges = m_bNotifyChanges; + } + + if (bNotifyChanges) + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +using impl::ChartType_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( ChartType, ChartType_Base, ::property::OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( ChartType, ChartType_Base, ::property::OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ChartTypeManager.cxx b/chart2/source/model/template/ChartTypeManager.cxx new file mode 100644 index 000000000..b1abde352 --- /dev/null +++ b/chart2/source/model/template/ChartTypeManager.cxx @@ -0,0 +1,588 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartTypeManager.hxx> +#include <StackMode.hxx> + +#include "LineChartTypeTemplate.hxx" +#include "BarChartTypeTemplate.hxx" +#include "ColumnLineChartTypeTemplate.hxx" +#include "AreaChartTypeTemplate.hxx" +#include "PieChartTypeTemplate.hxx" +#include "ScatterChartTypeTemplate.hxx" +#include "StockChartTypeTemplate.hxx" +#include "NetChartTypeTemplate.hxx" +#include "BubbleChartTypeTemplate.hxx" +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <sal/log.hxx> + +#include <algorithm> +#include <iterator> +#include <o3tl/functional.hxx> +#include <map> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Sequence; + +namespace +{ + +enum TemplateId +{ + TEMPLATE_SYMBOL, + TEMPLATE_STACKEDSYMBOL, + TEMPLATE_PERCENTSTACKEDSYMBOL, + TEMPLATE_LINE, + TEMPLATE_STACKEDLINE, + TEMPLATE_PERCENTSTACKEDLINE, + TEMPLATE_LINESYMBOL, + TEMPLATE_STACKEDLINESYMBOL, + TEMPLATE_PERCENTSTACKEDLINESYMBOL, + TEMPLATE_THREEDLINE, + TEMPLATE_STACKEDTHREEDLINE, + TEMPLATE_PERCENTSTACKEDTHREEDLINE, + TEMPLATE_THREEDLINEDEEP, + TEMPLATE_COLUMN, + TEMPLATE_STACKEDCOLUMN, + TEMPLATE_PERCENTSTACKEDCOLUMN, + TEMPLATE_BAR, + TEMPLATE_STACKEDBAR, + TEMPLATE_PERCENTSTACKEDBAR, + TEMPLATE_THREEDCOLUMNDEEP, + TEMPLATE_THREEDCOLUMNFLAT, + TEMPLATE_STACKEDTHREEDCOLUMNFLAT, + TEMPLATE_PERCENTSTACKEDTHREEDCOLUMNFLAT, + TEMPLATE_THREEDBARDEEP, + TEMPLATE_THREEDBARFLAT, + TEMPLATE_STACKEDTHREEDBARFLAT, + TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT, + TEMPLATE_COLUMNWITHLINE, + TEMPLATE_STACKEDCOLUMNWITHLINE, + TEMPLATE_AREA, + TEMPLATE_STACKEDAREA, + TEMPLATE_PERCENTSTACKEDAREA, + TEMPLATE_THREEDAREA, + TEMPLATE_STACKEDTHREEDAREA, + TEMPLATE_PERCENTSTACKEDTHREEDAREA, + TEMPLATE_PIE, + TEMPLATE_PIEALLEXPLODED, + TEMPLATE_DONUT, + TEMPLATE_DONUTALLEXPLODED, + TEMPLATE_THREEDPIE, + TEMPLATE_THREEDPIEALLEXPLODED, + TEMPLATE_THREEDDONUT, + TEMPLATE_THREEDDONUTALLEXPLODED, + TEMPLATE_SCATTERLINESYMBOL, + TEMPLATE_SCATTERLINE, + TEMPLATE_SCATTERSYMBOL, + TEMPLATE_THREEDSCATTER, + TEMPLATE_NET, + TEMPLATE_NETSYMBOL, + TEMPLATE_NETLINE, + TEMPLATE_STACKEDNET, + TEMPLATE_STACKEDNETSYMBOL, + TEMPLATE_STACKEDNETLINE, + TEMPLATE_PERCENTSTACKEDNET, + TEMPLATE_PERCENTSTACKEDNETSYMBOL, + TEMPLATE_PERCENTSTACKEDNETLINE, + TEMPLATE_FILLEDNET, + TEMPLATE_STACKEDFILLEDNET, + TEMPLATE_PERCENTSTACKEDFILLEDNET, + TEMPLATE_STOCKLOWHIGHCLOSE, + TEMPLATE_STOCKOPENLOWHIGHCLOSE, + TEMPLATE_STOCKVOLUMELOWHIGHCLOSE, + TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE, + TEMPLATE_BUBBLE, +// TEMPLATE_SURFACE, +// TEMPLATE_ADDIN, + TEMPLATE_NOT_FOUND = 0xffff +}; + +typedef std::map< OUString, TemplateId > tTemplateMapType; + +const tTemplateMapType & lcl_DefaultChartTypeMap() +{ + static const tTemplateMapType aMap{ + {"com.sun.star.chart2.template.Symbol", TEMPLATE_SYMBOL}, + {"com.sun.star.chart2.template.StackedSymbol", TEMPLATE_STACKEDSYMBOL}, + {"com.sun.star.chart2.template.PercentStackedSymbol", TEMPLATE_PERCENTSTACKEDSYMBOL}, + {"com.sun.star.chart2.template.Line", TEMPLATE_LINE}, + {"com.sun.star.chart2.template.StackedLine", TEMPLATE_STACKEDLINE}, + {"com.sun.star.chart2.template.PercentStackedLine", TEMPLATE_PERCENTSTACKEDLINE}, + {"com.sun.star.chart2.template.LineSymbol", TEMPLATE_LINESYMBOL}, + {"com.sun.star.chart2.template.StackedLineSymbol", TEMPLATE_STACKEDLINESYMBOL}, + {"com.sun.star.chart2.template.PercentStackedLineSymbol", TEMPLATE_PERCENTSTACKEDLINESYMBOL}, + {"com.sun.star.chart2.template.ThreeDLine", TEMPLATE_THREEDLINE}, + {"com.sun.star.chart2.template.StackedThreeDLine", TEMPLATE_STACKEDTHREEDLINE}, + {"com.sun.star.chart2.template.PercentStackedThreeDLine", TEMPLATE_PERCENTSTACKEDTHREEDLINE}, + {"com.sun.star.chart2.template.ThreeDLineDeep", TEMPLATE_THREEDLINEDEEP}, + {"com.sun.star.chart2.template.Column", TEMPLATE_COLUMN}, + {"com.sun.star.chart2.template.StackedColumn", TEMPLATE_STACKEDCOLUMN}, + {"com.sun.star.chart2.template.PercentStackedColumn", TEMPLATE_PERCENTSTACKEDCOLUMN}, + {"com.sun.star.chart2.template.Bar", TEMPLATE_BAR}, + {"com.sun.star.chart2.template.StackedBar", TEMPLATE_STACKEDBAR}, + {"com.sun.star.chart2.template.PercentStackedBar", TEMPLATE_PERCENTSTACKEDBAR}, + {"com.sun.star.chart2.template.ThreeDColumnDeep", TEMPLATE_THREEDCOLUMNDEEP}, + {"com.sun.star.chart2.template.ThreeDColumnFlat", TEMPLATE_THREEDCOLUMNFLAT}, + {"com.sun.star.chart2.template.StackedThreeDColumnFlat", TEMPLATE_STACKEDTHREEDCOLUMNFLAT}, + {"com.sun.star.chart2.template.PercentStackedThreeDColumnFlat", TEMPLATE_PERCENTSTACKEDTHREEDCOLUMNFLAT}, + {"com.sun.star.chart2.template.ThreeDBarDeep", TEMPLATE_THREEDBARDEEP}, + {"com.sun.star.chart2.template.ThreeDBarFlat", TEMPLATE_THREEDBARFLAT}, + {"com.sun.star.chart2.template.StackedThreeDBarFlat", TEMPLATE_STACKEDTHREEDBARFLAT}, + {"com.sun.star.chart2.template.PercentStackedThreeDBarFlat", TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT}, + {"com.sun.star.chart2.template.ColumnWithLine", TEMPLATE_COLUMNWITHLINE}, + {"com.sun.star.chart2.template.StackedColumnWithLine", TEMPLATE_STACKEDCOLUMNWITHLINE}, + {"com.sun.star.chart2.template.Area", TEMPLATE_AREA}, + {"com.sun.star.chart2.template.StackedArea", TEMPLATE_STACKEDAREA}, + {"com.sun.star.chart2.template.PercentStackedArea", TEMPLATE_PERCENTSTACKEDAREA}, + {"com.sun.star.chart2.template.ThreeDArea", TEMPLATE_THREEDAREA}, + {"com.sun.star.chart2.template.StackedThreeDArea", TEMPLATE_STACKEDTHREEDAREA}, + {"com.sun.star.chart2.template.PercentStackedThreeDArea", TEMPLATE_PERCENTSTACKEDTHREEDAREA}, + {"com.sun.star.chart2.template.Pie", TEMPLATE_PIE}, + {"com.sun.star.chart2.template.PieAllExploded", TEMPLATE_PIEALLEXPLODED}, + {"com.sun.star.chart2.template.Donut", TEMPLATE_DONUT}, + {"com.sun.star.chart2.template.DonutAllExploded", TEMPLATE_DONUTALLEXPLODED}, + {"com.sun.star.chart2.template.ThreeDPie", TEMPLATE_THREEDPIE}, + {"com.sun.star.chart2.template.ThreeDPieAllExploded", TEMPLATE_THREEDPIEALLEXPLODED}, + {"com.sun.star.chart2.template.ThreeDDonut", TEMPLATE_THREEDDONUT}, + {"com.sun.star.chart2.template.ThreeDDonutAllExploded", TEMPLATE_THREEDDONUTALLEXPLODED}, + {"com.sun.star.chart2.template.ScatterLineSymbol", TEMPLATE_SCATTERLINESYMBOL}, + {"com.sun.star.chart2.template.ScatterLine", TEMPLATE_SCATTERLINE}, + {"com.sun.star.chart2.template.ScatterSymbol", TEMPLATE_SCATTERSYMBOL}, + {"com.sun.star.chart2.template.ThreeDScatter", TEMPLATE_THREEDSCATTER}, + {"com.sun.star.chart2.template.Net", TEMPLATE_NET}, + {"com.sun.star.chart2.template.NetSymbol", TEMPLATE_NETSYMBOL}, + {"com.sun.star.chart2.template.NetLine", TEMPLATE_NETLINE}, + {"com.sun.star.chart2.template.StackedNet", TEMPLATE_STACKEDNET}, + {"com.sun.star.chart2.template.StackedNetSymbol", TEMPLATE_STACKEDNETSYMBOL}, + {"com.sun.star.chart2.template.StackedNetLine", TEMPLATE_STACKEDNETLINE}, + {"com.sun.star.chart2.template.PercentStackedNet", TEMPLATE_PERCENTSTACKEDNET}, + {"com.sun.star.chart2.template.PercentStackedNetSymbol", TEMPLATE_PERCENTSTACKEDNETSYMBOL}, + {"com.sun.star.chart2.template.PercentStackedNetLine", TEMPLATE_PERCENTSTACKEDNETLINE}, + {"com.sun.star.chart2.template.FilledNet", TEMPLATE_FILLEDNET}, + {"com.sun.star.chart2.template.StackedFilledNet", TEMPLATE_STACKEDFILLEDNET}, + {"com.sun.star.chart2.template.PercentStackedFilledNet", TEMPLATE_PERCENTSTACKEDFILLEDNET}, + {"com.sun.star.chart2.template.StockLowHighClose", TEMPLATE_STOCKLOWHIGHCLOSE}, + {"com.sun.star.chart2.template.StockOpenLowHighClose", TEMPLATE_STOCKOPENLOWHIGHCLOSE}, + {"com.sun.star.chart2.template.StockVolumeLowHighClose", TEMPLATE_STOCKVOLUMELOWHIGHCLOSE}, + {"com.sun.star.chart2.template.StockVolumeOpenLowHighClose", TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE}, + {"com.sun.star.chart2.template.Bubble", TEMPLATE_BUBBLE}, +// {"com.sun.star.chart2.template.Surface", TEMPLATE_SURFACE}, +// {"com.sun.star.chart2.template.Addin", TEMPLATE_ADDIN}, + }; + return aMap; +} + +TemplateId lcl_GetTemplateIdForService( const OUString & rServiceName ) +{ + TemplateId eResult = TEMPLATE_NOT_FOUND; + const tTemplateMapType & rMap = lcl_DefaultChartTypeMap(); + tTemplateMapType::const_iterator aIt( rMap.find( rServiceName )); + + if( aIt != rMap.end()) + eResult = (*aIt).second; + + return eResult; +} + +} // anonymous namespace + +namespace chart +{ + +ChartTypeManager::ChartTypeManager( + uno::Reference< + uno::XComponentContext > const & xContext ) : + m_xContext( xContext ) +{} + +ChartTypeManager::~ChartTypeManager() +{} + +// ____ XMultiServiceFactory ____ +uno::Reference< uno::XInterface > SAL_CALL ChartTypeManager::createInstance( + const OUString& aServiceSpecifier ) +{ + return static_cast<cppu::OWeakObject*>(createTemplate(aServiceSpecifier).get()); +} + +rtl::Reference< ::chart::ChartTypeTemplate > ChartTypeManager::createTemplate( + const OUString& aServiceSpecifier ) +{ + TemplateId nId = lcl_GetTemplateIdForService( aServiceSpecifier ); + + rtl::Reference< ::chart::ChartTypeTemplate > xTemplate; + switch( nId ) + { + // Point (category x axis) + case TEMPLATE_SYMBOL: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, true, false )); + break; + case TEMPLATE_STACKEDSYMBOL: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, true, false )); + break; + case TEMPLATE_PERCENTSTACKEDSYMBOL: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, true, false )); + break; + // Line (category x axis) + case TEMPLATE_LINE: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, false )); + break; + case TEMPLATE_STACKEDLINE: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, false )); + break; + case TEMPLATE_PERCENTSTACKEDLINE: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, false )); + break; + case TEMPLATE_LINESYMBOL: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, true )); + break; + case TEMPLATE_STACKEDLINESYMBOL: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, true )); + break; + case TEMPLATE_PERCENTSTACKEDLINESYMBOL: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, true )); + break; + case TEMPLATE_THREEDLINE: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, false, true, 3 )); + break; + case TEMPLATE_STACKEDTHREEDLINE: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, false, true, 3 )); + break; + case TEMPLATE_PERCENTSTACKEDTHREEDLINE: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, false, true, 3 )); + break; + case TEMPLATE_THREEDLINEDEEP: + xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::ZStacked, false, true, 3 )); + break; + + // Bar/Column + case TEMPLATE_COLUMN: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, BarChartTypeTemplate::VERTICAL )); + break; + case TEMPLATE_STACKEDCOLUMN: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, BarChartTypeTemplate::VERTICAL )); + break; + case TEMPLATE_PERCENTSTACKEDCOLUMN: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, BarChartTypeTemplate::VERTICAL )); + break; + case TEMPLATE_BAR: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, BarChartTypeTemplate::HORIZONTAL )); + break; + case TEMPLATE_STACKEDBAR: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, BarChartTypeTemplate::HORIZONTAL )); + break; + case TEMPLATE_PERCENTSTACKEDBAR: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, BarChartTypeTemplate::HORIZONTAL )); + break; + case TEMPLATE_THREEDCOLUMNDEEP: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::ZStacked, BarChartTypeTemplate::VERTICAL, 3 )); + break; + case TEMPLATE_THREEDCOLUMNFLAT: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, BarChartTypeTemplate::VERTICAL, 3 )); + break; + case TEMPLATE_STACKEDTHREEDCOLUMNFLAT: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, BarChartTypeTemplate::VERTICAL, 3 )); + break; + case TEMPLATE_PERCENTSTACKEDTHREEDCOLUMNFLAT: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, BarChartTypeTemplate::VERTICAL, 3 )); + break; + case TEMPLATE_THREEDBARDEEP: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::ZStacked, BarChartTypeTemplate::HORIZONTAL, 3 )); + break; + case TEMPLATE_THREEDBARFLAT: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, BarChartTypeTemplate::HORIZONTAL, 3 )); + break; + case TEMPLATE_STACKEDTHREEDBARFLAT: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, BarChartTypeTemplate::HORIZONTAL, 3 )); + break; + case TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT: + xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, BarChartTypeTemplate::HORIZONTAL, 3 )); + break; + + // Combi-Chart Line/Column + case TEMPLATE_COLUMNWITHLINE: + case TEMPLATE_STACKEDCOLUMNWITHLINE: + { + StackMode eMode = ( nId == TEMPLATE_COLUMNWITHLINE ) + ? StackMode::NONE + : StackMode::YStacked; + + xTemplate.set( new ColumnLineChartTypeTemplate( m_xContext, aServiceSpecifier, eMode, 1 )); + } + break; + + // Area + case TEMPLATE_AREA: + xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::NONE )); + break; + case TEMPLATE_STACKEDAREA: + xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStacked )); + break; + case TEMPLATE_PERCENTSTACKEDAREA: + xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStackedPercent )); + break; + case TEMPLATE_THREEDAREA: + xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::ZStacked, 3 )); + break; + case TEMPLATE_STACKEDTHREEDAREA: + xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStacked, 3 )); + break; + case TEMPLATE_PERCENTSTACKEDTHREEDAREA: + xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStackedPercent, 3 )); + break; + + case TEMPLATE_PIE: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_NONE, false )); + break; + case TEMPLATE_PIEALLEXPLODED: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_ALL_EXPLODED, false )); + break; + case TEMPLATE_DONUT: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_NONE, true )); + break; + case TEMPLATE_DONUTALLEXPLODED: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_ALL_EXPLODED, true )); + break; + case TEMPLATE_THREEDPIE: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_NONE, false, 3 )); + break; + case TEMPLATE_THREEDPIEALLEXPLODED: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_ALL_EXPLODED, false, 3 )); + break; + case TEMPLATE_THREEDDONUT: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_NONE, true, 3 )); + break; + case TEMPLATE_THREEDDONUTALLEXPLODED: + xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier, + chart2::PieChartOffsetMode_ALL_EXPLODED, true, 3 )); + break; + + case TEMPLATE_SCATTERLINESYMBOL: + xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ true )); + break; + case TEMPLATE_SCATTERLINE: + xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ false )); + break; + case TEMPLATE_SCATTERSYMBOL: + xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ true, /* bHasLines */ false )); + break; + case TEMPLATE_THREEDSCATTER: + xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ false, /* bHasLines */ true, 3 )); + break; + + // NetChart + case TEMPLATE_NET: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, true )); + break; + case TEMPLATE_NETSYMBOL: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, true, false )); + break; + case TEMPLATE_NETLINE: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, false )); + break; + + case TEMPLATE_STACKEDNET: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, true )); + break; + case TEMPLATE_STACKEDNETSYMBOL: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, true, false )); + break; + case TEMPLATE_STACKEDNETLINE: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, false, true )); + break; + + case TEMPLATE_PERCENTSTACKEDNET: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, true )); + break; + case TEMPLATE_PERCENTSTACKEDNETSYMBOL: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, true, false )); + break; + case TEMPLATE_PERCENTSTACKEDNETLINE: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, false, true )); + break; + + case TEMPLATE_FILLEDNET: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::NONE, false, false, true )); + break; + case TEMPLATE_STACKEDFILLEDNET: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStacked, false, false, true )); + break; + case TEMPLATE_PERCENTSTACKEDFILLEDNET: + xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier, + StackMode::YStackedPercent, false, false, true )); + break; + + case TEMPLATE_STOCKLOWHIGHCLOSE: + xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier, + StockChartTypeTemplate::StockVariant::NONE, false )); + break; + case TEMPLATE_STOCKOPENLOWHIGHCLOSE: + xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier, + StockChartTypeTemplate::StockVariant::Open, true )); + break; + case TEMPLATE_STOCKVOLUMELOWHIGHCLOSE: + xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier, + StockChartTypeTemplate::StockVariant::Volume, false )); + break; + case TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE: + xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier, + StockChartTypeTemplate::StockVariant::VolumeOpen, true )); + break; + + //BubbleChart + case TEMPLATE_BUBBLE: + xTemplate.set( new BubbleChartTypeTemplate( m_xContext, aServiceSpecifier )); + break; + + case TEMPLATE_NOT_FOUND: + SAL_WARN("chart2", "Couldn't instantiate service: "<< aServiceSpecifier ); + assert(false); + break; + + default: break; +// case TEMPLATE_SURFACE: +// case TEMPLATE_ADDIN: +// break; + } + + return xTemplate; +} + +uno::Reference< uno::XInterface > SAL_CALL ChartTypeManager::createInstanceWithArguments( + const OUString& ServiceSpecifier, + const uno::Sequence< uno::Any >& /* Arguments */ ) +{ + OSL_FAIL( "createInstanceWithArguments: No arguments supported" ); + return createInstance( ServiceSpecifier ); +} + +uno::Sequence< OUString > SAL_CALL ChartTypeManager::getAvailableServiceNames() +{ + std::vector< OUString > aServices; + const tTemplateMapType & rMap = lcl_DefaultChartTypeMap(); + aServices.reserve( rMap.size()); + + // get own default templates + std::transform( rMap.begin(), rMap.end(), std::back_inserter( aServices ), + ::o3tl::select1st< tTemplateMapType::value_type >() ); + + // add components that were registered in the context's factory + uno::Reference< container::XContentEnumerationAccess > xEnumAcc( + m_xContext->getServiceManager(), uno::UNO_QUERY ); + if( xEnumAcc.is()) + { + uno::Reference< container::XEnumeration > xEnum( + xEnumAcc->createContentEnumeration( "com.sun.star.chart2.ChartTypeTemplate" )); + if( xEnum.is()) + { + uno::Reference< uno::XInterface > xFactIntf; + + while( xEnum->hasMoreElements()) + { + if( xEnum->nextElement() >>= xFactIntf ) + { + uno::Reference< lang::XServiceName > xServiceName( xFactIntf, uno::UNO_QUERY ); + if( xServiceName.is()) + aServices.push_back( xServiceName->getServiceName()); + } + } + } + } + + return comphelper::containerToSequence( aServices ); +} + +// ____ XServiceInfo ____ +OUString SAL_CALL ChartTypeManager::getImplementationName() +{ + return "com.sun.star.comp.chart.ChartTypeManager"; +} + +sal_Bool SAL_CALL ChartTypeManager::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL ChartTypeManager::getSupportedServiceNames() +{ + return { + "com.sun.star.chart2.ChartTypeManager", + "com.sun.star.lang.MultiServiceFactory" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_ChartTypeManager_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::ChartTypeManager(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ChartTypeTemplate.cxx b/chart2/source/model/template/ChartTypeTemplate.cxx new file mode 100644 index 000000000..a785635f9 --- /dev/null +++ b/chart2/source/model/template/ChartTypeTemplate.cxx @@ -0,0 +1,861 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartTypeTemplate.hxx> +#include <DataInterpreter.hxx> +#include <CommonConverters.hxx> +#include <ChartTypeHelper.hxx> +#include <ChartType.hxx> +#include <DataSeries.hxx> +#include <DataSource.hxx> + +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <AxisIndexDefines.hxx> +#include <BaseCoordinateSystem.hxx> +#include <unonames.hxx> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/StackingDirection.hpp> +#include <com/sun/star/chart2/XColorScheme.hpp> +#include <tools/diagnose_ex.h> +#include <comphelper/property.hxx> + +#include <algorithm> +#include <cstddef> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +void lcl_applyDefaultStyle( + const rtl::Reference< ::chart::DataSeries > & xSeries, + sal_Int32 nIndex, + const rtl::Reference< ::chart::Diagram > & xDiagram ) +{ + // @deprecated: correct default color should be found by view without + // setting color as hard attribute + if( xSeries.is() && xDiagram.is()) + { + Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is() ) + xSeries->setPropertyValue( + "Color", + uno::Any( xColorScheme->getColorByIndex( nIndex ))); + } +} + +void lcl_ensureCorrectLabelPlacement( const Reference< beans::XPropertySet >& xProp, const uno::Sequence < sal_Int32 >& rAvailablePlacements ) +{ + sal_Int32 nLabelPlacement=0; + if( !(xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement)) ) + return; + + bool bValid = false; + for( sal_Int32 i : rAvailablePlacements ) + { + if( i == nLabelPlacement ) + { + bValid = true; + break; + } + } + if( !bValid ) + { + uno::Any aNewValue; + //otherwise use the first supported one + if( rAvailablePlacements.hasElements() ) + aNewValue <<=rAvailablePlacements[0]; + xProp->setPropertyValue( "LabelPlacement", aNewValue ); + } +} + +void lcl_resetLabelPlacementIfDefault( const Reference< beans::XPropertySet >& xProp, sal_Int32 nDefaultPlacement ) +{ + + sal_Int32 nLabelPlacement=0; + if( xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement) ) + { + if( nDefaultPlacement == nLabelPlacement ) + xProp->setPropertyValue( "LabelPlacement", uno::Any() ); + } +} + +void lcl_ensureCorrectMissingValueTreatment( const rtl::Reference< ::chart::Diagram >& xDiagram, const rtl::Reference< ::chart::ChartType >& xChartType ) +{ + if( xDiagram.is() ) + { + uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment( + ::chart::ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) ); + + if( aAvailableMissingValueTreatment.hasElements() ) + xDiagram->setPropertyValue( "MissingValueTreatment", uno::Any( aAvailableMissingValueTreatment[0] ) ); + else + xDiagram->setPropertyValue( "MissingValueTreatment", uno::Any() ); + } +} + +} // anonymous namespace + +namespace chart +{ + +ChartTypeTemplate::ChartTypeTemplate( + Reference< uno::XComponentContext > const & xContext, + const OUString & rServiceName ) : + m_xContext( xContext ), + m_aServiceName( rServiceName ) +{ +} + +ChartTypeTemplate::~ChartTypeTemplate() +{} + +// ____ ChartTypeTemplate ____ +rtl::Reference< Diagram > ChartTypeTemplate::createDiagramByDataSource2( + const uno::Reference< data::XDataSource >& xDataSource, + const uno::Sequence< beans::PropertyValue >& aArguments ) +{ + rtl::Reference< Diagram > xDia; + + try + { + // create diagram + xDia = new Diagram(GetComponentContext()); + + // modify diagram + rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2()); + InterpretedData aData( + xInterpreter->interpretDataSource( + xDataSource, aArguments, {} )); + + sal_Int32 nCount = 0; + for( auto const & i : aData.Series ) + for( auto const & j : i ) + lcl_applyDefaultStyle( j, nCount++, xDia ); + + std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq; + FillDiagram( xDia, aData.Series, aData.Categories, aOldChartTypesSeq ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xDia; +} + +sal_Bool SAL_CALL ChartTypeTemplate::supportsCategories() +{ + return true; +} + +void ChartTypeTemplate::changeDiagram( const rtl::Reference< Diagram >& xDiagram ) +{ + if( ! xDiagram.is()) + return; + + try + { + std::vector< std::vector< rtl::Reference< DataSeries > > > aSeriesSeq = + DiagramHelper::getDataSeriesGroups( xDiagram ); + std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq )); + const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size(); + + // chart-type specific interpretation of existing data series + rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2()); + InterpretedData aData; + aData.Series = aSeriesSeq; + aData.Categories = DiagramHelper::getCategoriesFromDiagram( xDiagram ); + + if( xInterpreter->isDataCompatible( aData ) ) + { + aData = xInterpreter->reinterpretDataSeries( aData ); + } + else + { + rtl::Reference< DataSource > xSource = DataInterpreter::mergeInterpretedData( aData ); + // todo: get a "range-union" from the data provider by calling + // OUString aRange = getRangeRepresentationByData( xSource ); + // xSource.set( getDataByRangeRepresentation( aRange, aParam )); + // where aParam == ?? + Sequence< beans::PropertyValue > aParam; + if( aData.Categories.is()) + { + aParam = { beans::PropertyValue( "HasCategories", -1, uno::Any( true ), + beans::PropertyState_DIRECT_VALUE ) }; + } + aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq ); + } + aSeriesSeq = aData.Series; + + sal_Int32 nIndex = 0; + for( auto const & i : std::as_const(aSeriesSeq) ) + for( auto const & j : i ) + { + if( nIndex >= nFormerSeriesCount ) + lcl_applyDefaultStyle( j, nIndex++, xDiagram ); + } + + // remove charttype groups from all coordinate systems + std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq = + DiagramHelper::getChartTypesFromDiagram(xDiagram); + + for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() ) + { + coords->setChartTypes( Sequence< Reference< XChartType > >() ); + } + + FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ChartTypeTemplate::changeDiagramData( + const rtl::Reference< Diagram >& xDiagram, + const Reference< chart2::data::XDataSource >& xDataSource, + const Sequence< beans::PropertyValue >& aArguments ) +{ + if( ! (xDiagram.is() && + xDataSource.is()) ) + return; + + try + { + // interpret new data and re-use existing series + std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size(); + rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2()); + InterpretedData aData = + xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq ); + + // data series + sal_Int32 nIndex = 0; + for( std::size_t i=0; i<aData.Series.size(); ++i ) + for( std::size_t j=0; j<aData.Series[i].size(); ++j, ++nIndex ) + { + if( nIndex >= nFormerSeriesCount ) + { + lcl_applyDefaultStyle( aData.Series[i][j], nIndex, xDiagram ); + applyStyle2( aData.Series[i][j], i, j, aData.Series[i].size() ); + } + } + + // categories + DiagramHelper::setCategoriesToDiagram( aData.Categories, xDiagram, true, supportsCategories() ); + + std::vector< rtl::Reference< ChartType > > aChartTypes = + DiagramHelper::getChartTypesFromDiagram( xDiagram ); + sal_Int32 nMax = std::min( aChartTypes.size(), aData.Series.size()); + for( sal_Int32 i=0; i<nMax; ++i ) + { + aChartTypes[i]->setDataSeries( aData.Series[i] ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +bool ChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool /* bAdaptProperties */ ) +{ + bool bResult = false; + + if( ! xDiagram.is()) + return bResult; + + try + { + const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq( + xDiagram->getBaseCoordinateSystems()); + + // need to have at least one coordinate system + bResult = !aCooSysSeq.empty(); + if( bResult ) + { + std::vector< rtl::Reference< ChartType > > aFormerlyUsedChartTypes; + rtl::Reference<ChartType> xOldCT = getChartTypeForNewSeries2(aFormerlyUsedChartTypes); + if (!xOldCT.is()) + return false; + + const OUString aChartTypeToMatch = xOldCT->getChartType(); + const sal_Int32 nDimensionToMatch = getDimension(); + for( std::size_t nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.size()); ++nCooSysIdx ) + { + // match dimension + bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch); + + const std::vector< rtl::Reference< ChartType > > & aChartTypeSeq( aCooSysSeq[nCooSysIdx]->getChartTypes2()); + for( std::size_t nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.size()); ++nCTIdx ) + { + // match chart type + bResult = bResult && aChartTypeSeq[nCTIdx]->getChartType() == aChartTypeToMatch; + bool bFound=false; + bool bAmbiguous=false; + // match stacking mode + bResult = bResult && + ( DiagramHelper::getStackModeFromChartType( + aChartTypeSeq[nCTIdx], bFound, bAmbiguous, + aCooSysSeq[nCooSysIdx] ) + == getStackMode( nCTIdx ) ); + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return bResult; +} + +rtl::Reference< DataInterpreter > ChartTypeTemplate::getDataInterpreter2() +{ + if( ! m_xDataInterpreter.is()) + m_xDataInterpreter.set( new DataInterpreter ); + + return m_xDataInterpreter; +} + +void ChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 /* nSeriesIndex */, + ::sal_Int32 /* nSeriesCount */ ) +{ + // sset stacking mode + if( !xSeries.is()) + return; + + try + { + StackMode eStackMode = getStackMode( nChartTypeIndex ); + const uno::Any aPropValue( + ( (eStackMode == StackMode::YStacked) || + (eStackMode == StackMode::YStackedPercent) ) + ? chart2::StackingDirection_Y_STACKING + : (eStackMode == StackMode::ZStacked ) + ? chart2::StackingDirection_Z_STACKING + : chart2::StackingDirection_NO_STACKING ); + xSeries->setPropertyValue( "StackingDirection", aPropValue ); + + //ensure valid label placement + { + uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements( + getChartTypeForIndex( nChartTypeIndex ), isSwapXAndY(), xSeries ) ); + lcl_ensureCorrectLabelPlacement( xSeries, aAvailablePlacements ); + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeries->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList ) + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + lcl_ensureCorrectLabelPlacement( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), aAvailablePlacements ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ChartTypeTemplate::applyStyles( const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + // apply chart-type specific styles, like "symbols on" for example + std::vector< std::vector< rtl::Reference< DataSeries > > > aNewSeriesSeq( + DiagramHelper::getDataSeriesGroups( xDiagram )); + for( std::size_t i=0; i<aNewSeriesSeq.size(); ++i ) + { + const sal_Int32 nNumSeries = aNewSeriesSeq[i].size(); + for( sal_Int32 j=0; j<nNumSeries; ++j ) + applyStyle2( aNewSeriesSeq[i][j], i, j, nNumSeries ); + } + + //ensure valid empty cell handling (for first chart type...) + lcl_ensureCorrectMissingValueTreatment( xDiagram, getChartTypeForIndex( 0 ) ); +} + +void ChartTypeTemplate::resetStyles2( const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + // reset number format if we had percent stacking on + bool bPercent = (getStackMode(0) == StackMode::YStackedPercent); + if( bPercent ) + { + const std::vector< rtl::Reference< Axis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( rtl::Reference< Axis > const & axis : aAxisSeq ) + { + if( AxisHelper::getDimensionIndexOfAxis( axis, xDiagram )== 1 ) + { + // set number format to source format + axis->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true)); + axis->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any()); + } + } + } + + //reset label placement if default + for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : xDiagram->getBaseCoordinateSystems() ) + { + //iterate through all chart types in the current coordinate system + for( rtl::Reference< ChartType > const & xChartType : xCooSys->getChartTypes2() ) + { + //iterate through all series in this chart type + for( rtl::Reference< DataSeries > const & xSeries : xChartType->getDataSeries2() ) + { + uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements( + xChartType, isSwapXAndY(), xSeries ) ); + if(!aAvailablePlacements.hasElements()) + continue; + + sal_Int32 nDefaultPlacement = aAvailablePlacements[0]; + + lcl_resetLabelPlacementIfDefault( xSeries, nDefaultPlacement ); + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeries->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList ) + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + lcl_resetLabelPlacementIfDefault( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), nDefaultPlacement ); + } + } + } + +} + +// ____ XServiceName ____ + OUString SAL_CALL ChartTypeTemplate::getServiceName() +{ + return m_aServiceName; +} + +sal_Int32 ChartTypeTemplate::getDimension() const +{ + return 2; +} + +StackMode ChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return StackMode::NONE; +} + +bool ChartTypeTemplate::isSwapXAndY() const +{ + return false; +} + +void ChartTypeTemplate::createCoordinateSystems( + const rtl::Reference< ::chart::Diagram > & xDiagram ) +{ + if( ! xDiagram.is()) + return; + std::vector< rtl::Reference< ChartType > > aFormerlyUsedChartTypes; + rtl::Reference< ChartType > xChartType( getChartTypeForNewSeries2(aFormerlyUsedChartTypes)); + if( ! xChartType.is()) + return; + rtl::Reference< BaseCoordinateSystem > xCooSys = xChartType->createCoordinateSystem2( getDimension()); + if( ! xCooSys.is()) + { + // chart type wants no coordinate systems + xDiagram->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >()); + return; + } + // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before) + if( xCooSys->getDimension() >= 2 ) + { + rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1, 0 ); + if( xAxis.is()) + AxisHelper::makeGridVisible( xAxis->getGridProperties() ); + } + + std::vector< rtl::Reference< BaseCoordinateSystem > > aCoordinateSystems( + xDiagram->getBaseCoordinateSystems()); + + if( !aCoordinateSystems.empty() ) + { + bool bOk = true; + for( std::size_t i=0; bOk && i<aCoordinateSystems.size(); ++i ) + bOk = bOk && ( xCooSys->getCoordinateSystemType() == aCoordinateSystems[i]->getCoordinateSystemType() && + (xCooSys->getDimension() == aCoordinateSystems[i]->getDimension()) ); + // coordinate systems are ok + if( bOk ) + return; + // there are coordinate systems but they do not fit. So overwrite them. + } + + //copy as much info from former coordinate system as possible: + if( !aCoordinateSystems.empty() ) + { + rtl::Reference< BaseCoordinateSystem > xOldCooSys( aCoordinateSystems[0] ); + sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() ); + + for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nMaxDimensionCount; nDimensionIndex++) + { + const sal_Int32 nMaximumAxisIndex = xOldCooSys->getMaximumAxisIndexByDimension(nDimensionIndex); + for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex) + { + rtl::Reference< Axis > xAxis = xOldCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex ); + if( xAxis.is()) + { + xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex ); + } + } + } + } + + // set new coordinate systems + aCoordinateSystems = { xCooSys }; + + xDiagram->setCoordinateSystems( aCoordinateSystems ); +} + +void ChartTypeTemplate::adaptScales( + const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq, + 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() ); + for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : aCooSysSeq ) + { + try + { + // attach categories to first axis + sal_Int32 nDim( xCooSys->getDimension()); + if( nDim > 0 ) + { + const sal_Int32 nDimensionX = 0; + const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionX); + for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI) + { + rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(nDimensionX,nI); + if( xAxis.is()) + { + ScaleData aData( xAxis->getScaleData() ); + aData.Categories = xCategories; + if(bSupportsCategories) + { + rtl::Reference< ChartType > xChartType = getChartTypeForNewSeries2({}); + if( aData.AxisType == AxisType::CATEGORY ) + { + aData.ShiftedCategoryPosition = m_aServiceName.indexOf("Column") != -1 || m_aServiceName.indexOf("Bar") != -1 || m_aServiceName.endsWith("Close"); + } + bool bSupportsDates = ::chart::ChartTypeHelper::isSupportingDateAxis( xChartType, nDimensionX ); + if( aData.AxisType != AxisType::CATEGORY && ( aData.AxisType != AxisType::DATE || !bSupportsDates) ) + { + aData.AxisType = AxisType::CATEGORY; + aData.AutoDateAxis = true; + AxisHelper::removeExplicitScaling( aData ); + } + } + else + aData.AxisType = AxisType::REALNUMBER; + + xAxis->setScaleData( aData ); + } + } + } + // set percent stacking mode at second axis + if( nDim > 1 ) + { + const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1); + for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI) + { + rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1,nI ); + if( xAxis.is()) + { + bool bPercent = (getStackMode(0) == StackMode::YStackedPercent); + chart2::ScaleData aScaleData = xAxis->getScaleData(); + + if( bPercent != (aScaleData.AxisType==AxisType::PERCENT) ) + { + if( bPercent ) + aScaleData.AxisType = AxisType::PERCENT; + else + aScaleData.AxisType = AxisType::REALNUMBER; + xAxis->setScaleData( aScaleData ); + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } +} + +void ChartTypeTemplate::adaptDiagram( const rtl::Reference< ::chart::Diagram > & /* xDiagram */ ) +{ +} + +void ChartTypeTemplate::createAxes( + const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys ) +{ + //create missing axes + if( rCoordSys.empty() ) + return; + + rtl::Reference< BaseCoordinateSystem > xCooSys( rCoordSys[0] ); + if(!xCooSys.is()) + return; + + //create main axis in first coordinate system + sal_Int32 nDimCount = xCooSys->getDimension(); + sal_Int32 nDim=0; + for( nDim=0; nDim<nDimCount; ++nDim ) + { + sal_Int32 nAxisCount = getAxisCountByDimension( nDim ); + if( nDim == 1 && + nAxisCount < 2 && AxisHelper::isSecondaryYAxisNeeded( xCooSys )) + nAxisCount = 2; + for( sal_Int32 nAxisIndex = 0; nAxisIndex < nAxisCount; ++nAxisIndex ) + { + Reference< XAxis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys ); + if( !xAxis.is()) + { + // create and add axis + xAxis.set( AxisHelper::createAxis( + nDim, nAxisIndex, xCooSys, GetComponentContext() )); + } + } + } +} + +void ChartTypeTemplate::adaptAxes( + const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys ) +{ + //adapt properties of existing axes and remove superfluous axes + + if( rCoordSys.empty() ) + return; + + for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : rCoordSys ) + { + if( !xCooSys.is() ) + continue; + sal_Int32 nDimCount = xCooSys->getDimension(); + for( sal_Int32 nDim=0; nDim<nDimCount; ++nDim ) + { + sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension( nDim ); + for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ ) + { + rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys ); + if( !xAxis.is() ) + continue; + + if( nAxisIndex == MAIN_AXIS_INDEX || nAxisIndex == SECONDARY_AXIS_INDEX ) + { + // adapt scales + bool bPercent = (getStackMode(0) == StackMode::YStackedPercent); + if( bPercent && nDim == 1 ) + { + // set number format to source format + xAxis->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true)); + xAxis->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any()); + } + } + } + } + } +} + +sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension ) +{ + return (nDimension < getDimension()) ? 1 : 0; +} + +void ChartTypeTemplate::FillDiagram( + const rtl::Reference< ::chart::Diagram >& xDiagram, + const std::vector< std::vector< rtl::Reference< DataSeries > > >& aSeriesSeq, + const uno::Reference< chart2::data::XLabeledDataSequence >& xCategories, + const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq ) +{ + adaptDiagram( xDiagram ); + + try + { + // create coordinate systems and scales + createCoordinateSystems( xDiagram ); + std::vector< rtl::Reference< BaseCoordinateSystem > > aCoordinateSystems( xDiagram->getBaseCoordinateSystems()); + createAxes( aCoordinateSystems ); + adaptAxes( aCoordinateSystems ); + adaptScales( aCoordinateSystems, xCategories ); + + // chart types + createChartTypes( aSeriesSeq, aCoordinateSystems, aOldChartTypesSeq ); + applyStyles( xDiagram ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ChartTypeTemplate::createChartTypes( + const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq, + const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq ) +{ + if( rCoordSys.empty() ) + return; + + try + { + std::size_t nCooSysIdx=0; + rtl::Reference< ChartType > xCT; + if( aSeriesSeq.empty() ) + { + // we need a new chart type + xCT = getChartTypeForNewSeries2( aOldChartTypesSeq ); + rCoordSys[nCooSysIdx]->setChartTypes(std::vector{ xCT }); + } + else + { + for( std::size_t nSeriesIdx=0; nSeriesIdx<aSeriesSeq.size(); ++nSeriesIdx ) + { + if( nSeriesIdx == nCooSysIdx ) + { + // we need a new chart type + xCT = getChartTypeForNewSeries2( aOldChartTypesSeq ); + std::vector< rtl::Reference< ChartType > > aCTSeq( rCoordSys[nCooSysIdx]->getChartTypes2()); + if( !aCTSeq.empty()) + { + aCTSeq[0] = xCT; + rCoordSys[nCooSysIdx]->setChartTypes( aCTSeq ); + } + else + rCoordSys[nCooSysIdx]->addChartType( xCT ); + + xCT->setDataSeries( aSeriesSeq[nSeriesIdx] ); + } + else + { + // reuse existing chart type + OSL_ASSERT( xCT.is()); + std::vector< rtl::Reference< DataSeries > > aNewSeriesSeq = xCT->getDataSeries2(); + sal_Int32 nNewStartIndex = aNewSeriesSeq.size(); + aNewSeriesSeq.resize( nNewStartIndex + aSeriesSeq[nSeriesIdx].size() ); + std::copy( aSeriesSeq[nSeriesIdx].begin(), + aSeriesSeq[nSeriesIdx].end(), + aNewSeriesSeq.begin() + nNewStartIndex ); + xCT->setDataSeries( aNewSeriesSeq ); + } + + // spread the series over the available coordinate systems + if( rCoordSys.size() > (nCooSysIdx + 1) ) + ++nCooSysIdx; + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( + const std::vector< rtl::Reference< ChartType > > & rOldChartTypesSeq, + const rtl::Reference< ChartType > & xNewChartType ) +{ + if( !xNewChartType.is() ) + return; + + OUString aNewChartType( xNewChartType->getChartType() ); + + Reference< beans::XPropertySet > xSource; + for( rtl::Reference< ChartType > const & xOldType : rOldChartTypesSeq ) + { + if( xOldType.is() && xOldType->getChartType() == aNewChartType ) + { + xSource = xOldType; + if( xSource.is() ) + break; + } + } + if( xSource.is() ) + comphelper::copyProperties( xSource, xNewChartType ); +} + +css::uno::Reference< css::uno::XInterface > ChartTypeTemplate::getDataInterpreter() +{ + return static_cast<cppu::OWeakObject*>(getDataInterpreter2().get()); +} +css::uno::Reference< css::chart2::XDiagram > ChartTypeTemplate::createDiagramByDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) +{ + return createDiagramByDataSource2(xDataSource, aArguments); +} +void ChartTypeTemplate::changeDiagram( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) +{ + changeDiagram(rtl::Reference<Diagram>(dynamic_cast<Diagram*>(xDiagram.get()))); +} +void ChartTypeTemplate::changeDiagramData( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) +{ + changeDiagramData(rtl::Reference<Diagram>(dynamic_cast<Diagram*>(xDiagram.get())), xDataSource, aArguments); +} +sal_Bool ChartTypeTemplate::matchesTemplate( + const css::uno::Reference<css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + return matchesTemplate2(dynamic_cast<Diagram*>(xDiagram.get()), static_cast<bool>(bAdaptProperties)); +} +css::uno::Reference< ::css::chart2::XChartType > ChartTypeTemplate::getChartTypeForNewSeries( + const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + std::vector< rtl::Reference< ::chart::ChartType > > aTmp; + aTmp.reserve(aFormerlyUsedChartTypes.getLength()); + for (auto const & rxChartType : aFormerlyUsedChartTypes) + aTmp.push_back(dynamic_cast<ChartType*>(rxChartType.get())); + return getChartTypeForNewSeries2(aTmp); +} +void ChartTypeTemplate::applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + applyStyle2(dynamic_cast<DataSeries*>(xSeries.get()), nChartTypeIndex, nSeriesIndex, nSeriesCount); +} +void ChartTypeTemplate::resetStyles( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) +{ + resetStyles2(dynamic_cast<Diagram*>(xDiagram.get())); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ColumnChartType.cxx b/chart2/source/model/template/ColumnChartType.cxx new file mode 100644 index 000000000..50fdca0e1 --- /dev/null +++ b/chart2/source/model/template/ColumnChartType.cxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ColumnChartType.hxx" +#include <servicenames_charttypes.hxx> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_BARCHARTTYPE_OVERLAP_SEQUENCE, + PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "OverlapSequence", + PROP_BARCHARTTYPE_OVERLAP_SEQUENCE, + cppu::UnoType<Sequence< sal_Int32 >>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "GapwidthSequence", + PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType<Sequence< sal_Int32 >>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticColumnChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + Sequence< sal_Int32 > aSeq{ 0, 0 }; + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_BARCHARTTYPE_OVERLAP_SEQUENCE, aSeq ); + + aSeq = { 100, 100 }; + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq ); + } +}; + +struct StaticColumnChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticColumnChartTypeDefaults_Initializer > +{ +}; + +struct StaticColumnChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticColumnChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticColumnChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticColumnChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticColumnChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticColumnChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticColumnChartTypeInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +ColumnChartType::ColumnChartType() +{} + +ColumnChartType::ColumnChartType( const ColumnChartType & rOther ) : + ChartType( rOther ) +{ +} + +ColumnChartType::~ColumnChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL ColumnChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new ColumnChartType( *this )); +} + +rtl::Reference< ChartType > ColumnChartType::cloneChartType() const +{ + return new ColumnChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL ColumnChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_COLUMN; +} + +uno::Sequence< OUString > ColumnChartType::getSupportedPropertyRoles() +{ + return { "FillColor", "BorderColor" }; +} + +// ____ OPropertySet ____ +void ColumnChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticColumnChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL ColumnChartType::getInfoHelper() +{ + return *StaticColumnChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnChartType::getPropertySetInfo() +{ + return *StaticColumnChartTypeInfo::get(); +} + +OUString SAL_CALL ColumnChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.ColumnChartType"; +} + +sal_Bool SAL_CALL ColumnChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL ColumnChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_COLUMN, + "com.sun.star.chart2.ChartType" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_ColumnChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::ColumnChartType()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ColumnChartType.hxx b/chart2/source/model/template/ColumnChartType.hxx new file mode 100644 index 000000000..2c6b3d762 --- /dev/null +++ b/chart2/source/model/template/ColumnChartType.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class ColumnChartType final : public ChartType +{ +public: + explicit ColumnChartType(); + virtual ~ColumnChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit ColumnChartType( const ColumnChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedPropertyRoles() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx b/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx new file mode 100644 index 000000000..f0a18708a --- /dev/null +++ b/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx @@ -0,0 +1,356 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ColumnLineChartTypeTemplate.hxx" +#include "ColumnChartType.hxx" +#include "LineChartType.hxx" +#include <CommonConverters.hxx> +#include <BaseCoordinateSystem.hxx> +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <servicenames_charttypes.hxx> +#include "ColumnLineDataInterpreter.hxx" +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_COL_LINE_NUMBER_OF_LINES +}; + +::chart::tPropertyValueMap& StaticColumnLineChartTypeTemplateDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + []() + { + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_COL_LINE_NUMBER_OF_LINES, 1 ); + return aOutMap; + }(); + return aStaticDefaults; +} + +::cppu::OPropertyArrayHelper& StaticColumnLineChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { "NumberOfLines", + PROP_COL_LINE_NUMBER_OF_LINES, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT } }; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + }()); + return aPropHelper; +} + +uno::Reference< beans::XPropertySetInfo >& StaticColumnLineChartTypeTemplateInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticColumnLineChartTypeTemplateInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +ColumnLineChartTypeTemplate::ColumnLineChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + sal_Int32 nNumberOfLines ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ) +{ + setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::Any( nNumberOfLines )); +} + +ColumnLineChartTypeTemplate::~ColumnLineChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void ColumnLineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticColumnLineChartTypeTemplateDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL ColumnLineChartTypeTemplate::getInfoHelper() +{ + return StaticColumnLineChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnLineChartTypeTemplate::getPropertySetInfo() +{ + return StaticColumnLineChartTypeTemplateInfo(); +} + +void ColumnLineChartTypeTemplate::createChartTypes( + const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq, + const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq ) +{ + if( rCoordSys.empty() ) + return; + + try + { + const std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq )); + sal_Int32 nNumberOfSeries = aFlatSeriesSeq.size(); + sal_Int32 nNumberOfLines = 0; + sal_Int32 nNumberOfColumns = 0; + + getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines; + OSL_ENSURE( nNumberOfLines>=0, "number of lines should be not negative" ); + if( nNumberOfLines < 0 ) + nNumberOfLines = 0; + + if( nNumberOfLines >= nNumberOfSeries ) + { + if( nNumberOfSeries > 0 ) + { + nNumberOfLines = nNumberOfSeries - 1; + nNumberOfColumns = 1; + } + else + nNumberOfLines = 0; + } + else + nNumberOfColumns = nNumberOfSeries - nNumberOfLines; + + // Columns + + rtl::Reference< ChartType > xCT = new ColumnChartType(); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aOldChartTypesSeq, xCT ); + + rCoordSys[ 0 ]->setChartTypes( std::vector{xCT} ); + + if( nNumberOfColumns > 0 ) + { + std::vector< rtl::Reference< DataSeries > > aColumnSeq( nNumberOfColumns ); + std::copy( aFlatSeriesSeq.begin(), + aFlatSeriesSeq.begin() + nNumberOfColumns, + aColumnSeq.begin()); + xCT->setDataSeries( aColumnSeq ); + } + + // Lines + + xCT = new LineChartType(); + rCoordSys[ 0 ]->addChartType( xCT ); + + if( nNumberOfLines > 0 ) + { + std::vector< rtl::Reference< DataSeries > > aLineSeq( nNumberOfLines ); + std::copy( aFlatSeriesSeq.begin() + nNumberOfColumns, + aFlatSeriesSeq.end(), + aLineSeq.begin()); + xCT->setDataSeries( aLineSeq ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ColumnLineChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + if( nChartTypeIndex==0 ) // columns + { + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); + } + else if( nChartTypeIndex==1 ) // lines + { + DataSeriesHelper::switchLinesOnOrOff( xSeries, true ); + DataSeriesHelper::switchSymbolsOnOrOff( xSeries, false, nSeriesIndex ); + DataSeriesHelper::makeLinesThickOrThin( xSeries, true ); + } +} + +StackMode ColumnLineChartTypeTemplate::getStackMode( sal_Int32 nChartTypeIndex ) const +{ + if( nChartTypeIndex == 0 ) + return m_eStackMode; + return StackMode::NONE; +} + +// ____ XChartTypeTemplate ____ +bool ColumnLineChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) +{ + bool bResult = false; + + if( ! xDiagram.is()) + return bResult; + + try + { + rtl::Reference< ChartType > xColumnChartType; + rtl::Reference< BaseCoordinateSystem > xColumnChartCooSys; + rtl::Reference< ChartType > xLineChartType; + sal_Int32 nNumberOfChartTypes = 0; + + for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() ) + { + const std::vector< rtl::Reference< ChartType > > aChartTypeSeq( coords->getChartTypes2()); + for( rtl::Reference< ChartType > const & chartType : aChartTypeSeq ) + { + ++nNumberOfChartTypes; + if( nNumberOfChartTypes > 2 ) + break; + OUString aCTService = chartType->getChartType(); + if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) + { + xColumnChartType = chartType; + xColumnChartCooSys = coords; + } + else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_LINE ) + xLineChartType = chartType; + } + if( nNumberOfChartTypes > 2 ) + break; + } + + if( nNumberOfChartTypes == 2 && + xColumnChartType.is() && + xLineChartType.is()) + { + OSL_ASSERT( xColumnChartCooSys.is()); + + // check stackmode of bars + bResult = (xColumnChartCooSys->getDimension() == getDimension()); + if( bResult ) + { + bool bFound=false; + bool bAmbiguous=false; + bResult = ( DiagramHelper::getStackModeFromChartType( + xColumnChartType, bFound, bAmbiguous, + xColumnChartCooSys ) + == getStackMode( 0 ) ); + + if( bResult && bAdaptProperties ) + { + if( xLineChartType.is() ) + { + sal_Int32 nNumberOfLines = xLineChartType->getDataSeries().getLength(); + setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::Any( nNumberOfLines )); + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return bResult; +} + +rtl::Reference< ChartType > ColumnLineChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex ) +{ + if( nChartTypeIndex == 0 ) + return new ColumnChartType(); + else + return new LineChartType(); +} + +rtl::Reference< ChartType > ColumnLineChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new LineChartType(); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< DataInterpreter > ColumnLineChartTypeTemplate::getDataInterpreter2() +{ + if( ! m_xDataInterpreter.is()) + { + sal_Int32 nNumberOfLines = 1; + getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines; + m_xDataInterpreter = new ColumnLineDataInterpreter( nNumberOfLines ); + } + else + { + //todo... + OSL_FAIL( "number of lines may not be valid anymore in the datainterpreter" ); + + } + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2( ColumnLineChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( ColumnLineChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ColumnLineChartTypeTemplate.hxx b/chart2/source/model/template/ColumnLineChartTypeTemplate.hxx new file mode 100644 index 000000000..f76f329a1 --- /dev/null +++ b/chart2/source/model/template/ColumnLineChartTypeTemplate.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <StackMode.hxx> + +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class ColumnLineChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + explicit ColumnLineChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + sal_Int32 nNumberOfLines ); + virtual ~ColumnLineChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override; + + // ____ ChartTypeTemplate ____ + virtual void createChartTypes( + const std::vector< + std::vector< + rtl::Reference< + ::chart::DataSeries > > > & aSeriesSeq, + const std::vector< + rtl::Reference< + ::chart::BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq + ) override; + + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + +private: + StackMode m_eStackMode; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ColumnLineDataInterpreter.cxx b/chart2/source/model/template/ColumnLineDataInterpreter.cxx new file mode 100644 index 000000000..15ce4adce --- /dev/null +++ b/chart2/source/model/template/ColumnLineDataInterpreter.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ColumnLineDataInterpreter.hxx" +#include <DataSeries.hxx> +#include <osl/diagnose.h> + +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +// explicit +ColumnLineDataInterpreter::ColumnLineDataInterpreter( + sal_Int32 nNumberOfLines ) : + m_nNumberOfLines( nNumberOfLines ) +{} + +ColumnLineDataInterpreter::~ColumnLineDataInterpreter() +{} + +// ____ DataInterpreter ____ +InterpretedData ColumnLineDataInterpreter::interpretDataSource( + const Reference< data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse ) +{ + InterpretedData aResult( DataInterpreter::interpretDataSource( xSource, aArguments, aSeriesToReUse )); + + // the base class should return one group + OSL_ASSERT( aResult.Series.size() == 1 ); + if( aResult.Series.size() == 1 ) + { + sal_Int32 nNumberOfSeries = aResult.Series[0].size(); + + // if we have more than one series put the last nNumOfLines ones into a new group + if( nNumberOfSeries > 1 && m_nNumberOfLines > 0 ) + { + sal_Int32 nNumOfLines = std::min( m_nNumberOfLines, nNumberOfSeries - 1 ); + aResult.Series.resize(2); + + std::vector< rtl::Reference< DataSeries > > & rColumnDataSeries = aResult.Series[0]; + std::vector< rtl::Reference< DataSeries > > & rLineDataSeries = aResult.Series[1]; + rLineDataSeries.resize( nNumOfLines ); + std::copy( std::cbegin(rColumnDataSeries) + nNumberOfSeries - nNumOfLines, + std::cbegin(rColumnDataSeries) + nNumberOfSeries, + rLineDataSeries.begin() ); + rColumnDataSeries.resize( nNumberOfSeries - nNumOfLines ); + } + } + + return aResult; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ColumnLineDataInterpreter.hxx b/chart2/source/model/template/ColumnLineDataInterpreter.hxx new file mode 100644 index 000000000..c2ec75826 --- /dev/null +++ b/chart2/source/model/template/ColumnLineDataInterpreter.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <DataInterpreter.hxx> + +namespace chart +{ +class ColumnLineDataInterpreter : public DataInterpreter +{ +public: + explicit ColumnLineDataInterpreter(sal_Int32 nNumberOfLines); + virtual ~ColumnLineDataInterpreter() override; + +protected: + // ____ DataInterpreter ____ + virtual InterpretedData interpretDataSource( + const css::uno::Reference<css::chart2::data::XDataSource>& xSource, + const css::uno::Sequence<css::beans::PropertyValue>& aArguments, + const std::vector<rtl::Reference<::chart::DataSeries>>& aSeriesToReUse) override; + +private: + sal_Int32 m_nNumberOfLines; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/DataInterpreter.cxx b/chart2/source/model/template/DataInterpreter.cxx new file mode 100644 index 000000000..5b8899dcc --- /dev/null +++ b/chart2/source/model/template/DataInterpreter.cxx @@ -0,0 +1,445 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <DataInterpreter.hxx> +#include <DataSeries.hxx> +#include <DataSource.hxx> +#include <DataSeriesHelper.hxx> +#include <CommonConverters.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> +#include <cstddef> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +#ifdef DEBUG_CHART2_TEMPLATE +namespace +{ +void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource ); +} +#endif + +namespace chart +{ + +DataInterpreter::DataInterpreter() +{} + +DataInterpreter::~DataInterpreter() +{} + +// ____ XDataInterpreter ____ +InterpretedData DataInterpreter::interpretDataSource( + const Reference< data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + +#ifdef DEBUG_CHART2_TEMPLATE + lcl_ShowDataSource( xSource ); +#endif + + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = getDataSequences(xSource); + + uno::Reference< chart2::data::XLabeledDataSequence > xCategories; + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequencesVec; + + // check if we should use categories + + bool bHasCategories( HasCategories( aArguments, aData )); + + // parse data + bool bCategoriesUsed = false; + for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledData : aData ) + { + try + { + if( bHasCategories && ! bCategoriesUsed ) + { + xCategories = labeledData; + if( xCategories.is()) + SetRole( xCategories->getValues(), "categories"); + bCategoriesUsed = true; + } + else + { + aSequencesVec.push_back( labeledData ); + if( labeledData.is()) + SetRole( labeledData->getValues(), "values-y"); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + // create DataSeries + std::size_t nSeriesIndex = 0; + vector< rtl::Reference< DataSeries > > aSeriesVec; + aSeriesVec.reserve( aSequencesVec.size()); + + for (auto const& elem : aSequencesVec) + { + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewData { elem }; + rtl::Reference< DataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.size()) + xSeries = aSeriesToReUse[nSeriesIndex]; + else + xSeries = new DataSeries; + assert( xSeries.is() ); + xSeries->setData( aNewData ); + + aSeriesVec.push_back( xSeries ); + ++nSeriesIndex; + } + + return { { aSeriesVec }, xCategories }; +} + +InterpretedData DataInterpreter::reinterpretDataSeries( + const InterpretedData& aInterpretedData ) +{ + InterpretedData aResult( aInterpretedData ); + + sal_Int32 i=0; + std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + const sal_Int32 nCount = aSeries.size(); + for( ; i<nCount; ++i ) + { + try + { + std::vector< uno::Reference< data::XLabeledDataSequence > > aNewSequences; + + // values-y + uno::Reference< data::XLabeledDataSequence > xValuesY = + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-y" ); + // re-use values-... as values-y + if( ! xValuesY.is()) + { + xValuesY = + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values", true ); + if( xValuesY.is()) + SetRole( xValuesY->getValues(), "values-y"); + } + if( xValuesY.is()) + { + aNewSequences = { xValuesY }; + } + + const std::vector< uno::Reference< data::XLabeledDataSequence > > & aSeqs = aSeries[i]->getDataSequences2(); + if( aSeqs.size() != aNewSequences.size() ) + { +#ifdef DEBUG_CHART2_TEMPLATE + sal_Int32 j=0; + for( ; j<aSeqs.(); ++j ) + { + assert( aSeqs[j] == xValuesY && "All sequences should be used" ); + } +#endif + aSeries[i]->setData( aNewSequences ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +// criterion: all series must have exactly one data::XLabeledDataSequence +bool DataInterpreter::isDataCompatible( + const InterpretedData& aInterpretedData ) +{ + const std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( rtl::Reference< DataSeries > const & i : aSeries ) + { + try + { + if( i->getDataSequences2().size() != 1 ) + return false; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return true; +} + +namespace +{ + +struct lcl_LabeledSequenceEquals +{ + explicit lcl_LabeledSequenceEquals( const Reference< data::XLabeledDataSequence > & xLSeqToCmp ) : + m_bHasLabels ( false ), + m_bHasValues ( false ) + { + if( !xLSeqToCmp.is()) + return; + + Reference< data::XDataSequence > xSeq( xLSeqToCmp->getValues()); + if( xSeq.is()) + { + m_bHasValues = true; + m_aValuesRangeRep = xSeq->getSourceRangeRepresentation(); + } + + xSeq.set( xLSeqToCmp->getLabel()); + if( xSeq.is()) + { + m_bHasLabels = true; + m_aLabelRangeRep = xSeq->getSourceRangeRepresentation(); + } + } + + bool operator() ( const Reference< data::XLabeledDataSequence > & xSeq ) + { + if( ! xSeq.is()) + return false; + + Reference< data::XDataSequence > xSeqValues( xSeq->getValues() ); + Reference< data::XDataSequence > xSeqLabels( xSeq->getLabel() ); + bool bHasValues = xSeqValues.is(); + bool bHasLabels = xSeqLabels.is(); + + return ( ( (m_bHasValues == bHasValues) && + (!bHasValues || m_aValuesRangeRep == xSeqValues->getSourceRangeRepresentation()) ) && + ( (m_bHasLabels == bHasLabels) && + (!bHasLabels || m_aLabelRangeRep == xSeqLabels->getSourceRangeRepresentation()) ) + ); + } + +private: + bool m_bHasLabels; + bool m_bHasValues; + OUString m_aValuesRangeRep; + OUString m_aLabelRangeRep; +}; + +} // anonymous namespace + +rtl::Reference< DataSource > DataInterpreter::mergeInterpretedData( + const InterpretedData& aInterpretedData ) +{ + vector< Reference< data::XLabeledDataSequence > > aResultVec; + aResultVec.reserve( aInterpretedData.Series.size() + + 1 // categories + ); + + if( aInterpretedData.Categories.is()) + aResultVec.push_back( aInterpretedData.Categories ); + + const std::vector< rtl::Reference< DataSeries > > aSeries = FlattenSequence( aInterpretedData.Series ); + for( rtl::Reference< DataSeries > const & dataSeries : aSeries ) + { + try + { + // add all sequences of data series + for( uno::Reference< data::XLabeledDataSequence > const & xAdd : dataSeries->getDataSequences2() ) + { + // only add if sequence is not yet in the result + if( none_of( aResultVec.begin(), aResultVec.end(), + lcl_LabeledSequenceEquals( xAdd )) ) + { + aResultVec.push_back( xAdd ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return new DataSource(aResultVec); +} + +uno::Any DataInterpreter::getChartTypeSpecificData( + const OUString & ) +{ + return uno::Any(); +} + +// convenience methods + +OUString DataInterpreter::GetRole( const Reference< data::XDataSequence > & xSeq ) +{ + OUString aResult; + if( ! xSeq.is()) + return aResult; + + try + { + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); + xProp->getPropertyValue( "Role") >>= aResult; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return aResult; +} + +void DataInterpreter::SetRole( const Reference< data::XDataSequence > & xSeq, const OUString & rRole ) +{ + if( ! xSeq.is()) + return; + try + { + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); + xProp->setPropertyValue( "Role", uno::Any( rRole )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +uno::Any DataInterpreter::GetProperty( + const Sequence< beans::PropertyValue > & aArguments, + std::u16string_view rName ) +{ + for( sal_Int32 i=aArguments.getLength(); i--; ) + { + if( aArguments[i].Name == rName ) + return aArguments[i].Value; + } + return uno::Any(); +} + +bool DataInterpreter::HasCategories( + const Sequence< beans::PropertyValue > & rArguments, + const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & rData ) +{ + bool bHasCategories = false; + + if( rArguments.hasElements() ) + GetProperty( rArguments, u"HasCategories" ) >>= bHasCategories; + + for( std::size_t nLSeqIdx=0; ! bHasCategories && nLSeqIdx<rData.size(); ++nLSeqIdx ) + bHasCategories = ( rData[nLSeqIdx].is() && GetRole( rData[nLSeqIdx]->getValues() ) == "categories"); + + return bHasCategories; +} + +bool DataInterpreter::UseCategoriesAsX( const Sequence< beans::PropertyValue > & rArguments ) +{ + bool bUseCategoriesAsX = true; + if( rArguments.hasElements() ) + GetProperty( rArguments, u"UseCategoriesAsX" ) >>= bUseCategoriesAsX; + return bUseCategoriesAsX; +} + +OUString SAL_CALL DataInterpreter::getImplementationName() +{ + return "com.sun.star.comp.chart2.DataInterpreter"; +} + +sal_Bool SAL_CALL DataInterpreter::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL DataInterpreter::getSupportedServiceNames() +{ + return { "com.sun.star.chart2.DataInterpreter" }; +} + +std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > DataInterpreter::getDataSequences( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource) +{ + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData; + for (const Reference< data::XLabeledDataSequence > & rLDS : xSource->getDataSequences() ) + { + aData.push_back(rLDS); + } + return aData; +} + +} // namespace chart + +#ifdef DEBUG_CHART2_TEMPLATE +namespace +{ + +void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource ) +{ + if( ! xSource.is()) + return; + + SAL_INFO("chart2", "DataSource in DataInterpreter:" ); + Sequence< Reference< data::XLabeledDataSequence > > aSequences( xSource->getDataSequences()); + Reference< beans::XPropertySet > xProp; + OUString aId; + const sal_Int32 nMax = aSequences.getLength(); + for( sal_Int32 k = 0; k < nMax; ++k ) + { + if( aSequences[k].is()) + { + OUString aSourceRepr("<none>"); + if( aSequences[k]->getValues().is()) + aSourceRepr = aSequences[k]->getValues()->getSourceRangeRepresentation(); + xProp.set( aSequences[k]->getValues(), uno::UNO_QUERY ); + if( xProp.is() && + ( xProp->getPropertyValue( "Role") >>= aId )) + { + SAL_INFO("chart2", " <data sequence " << k << "> Role: " << aId << ", Source: "<< aSourceRepr); + } + else + { + SAL_INFO("chart2", " <data sequence " << k << "> unknown Role, Source: " << aSourceRepr ); + } + + aSourceRepr = "<none>"; + if( aSequences[k]->getLabel().is()) + aSourceRepr = aSequences[k]->getLabel()->getSourceRangeRepresentation(); + xProp.set( aSequences[k]->getLabel(), uno::UNO_QUERY ); + if( xProp.is() && + ( xProp->getPropertyValue( "Role") >>= aId )) + { + SAL_INFO("chart2", " <data sequence label " << k << "> Role: " << aId + << ", Source: " << aSourceRepr ); + } + else + { + SAL_INFO("chart2", " <data sequence label " << k << "> unknown Role, Source: " << aSourceRepr ); + } + } + } +} + +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/FilledNetChartType.cxx b/chart2/source/model/template/FilledNetChartType.cxx new file mode 100644 index 000000000..6ec39d983 --- /dev/null +++ b/chart2/source/model/template/FilledNetChartType.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "FilledNetChartType.hxx" +#include <servicenames_charttypes.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +FilledNetChartType::FilledNetChartType() +{} + +FilledNetChartType::FilledNetChartType( const FilledNetChartType & rOther ) : + NetChartType_Base( rOther ) +{ +} + +FilledNetChartType::~FilledNetChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL FilledNetChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new FilledNetChartType( *this )); +} + +rtl::Reference< ChartType > FilledNetChartType::cloneChartType() const +{ + return new FilledNetChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL FilledNetChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET; +} + +OUString SAL_CALL FilledNetChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.FilledNetChartType"; +} + +sal_Bool SAL_CALL FilledNetChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL FilledNetChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_FilledNetChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::FilledNetChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/FilledNetChartType.hxx b/chart2/source/model/template/FilledNetChartType.hxx new file mode 100644 index 000000000..b2d239aec --- /dev/null +++ b/chart2/source/model/template/FilledNetChartType.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include "NetChartType.hxx" + +namespace chart +{ +class FilledNetChartType final : public NetChartType_Base +{ +public: + explicit FilledNetChartType(); + virtual ~FilledNetChartType() override; + + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit FilledNetChartType(const FilledNetChartType& rOther); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + + // ____ XCloneable ____ + virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/LineChartType.cxx b/chart2/source/model/template/LineChartType.cxx new file mode 100644 index 000000000..e9d7cf808 --- /dev/null +++ b/chart2/source/model/template/LineChartType.cxx @@ -0,0 +1,183 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "LineChartType.hxx" +#include <PropertyHelper.hxx> +#include <servicenames_charttypes.hxx> +#include <unonames.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/CurveStyle.hpp> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +enum +{ + PROP_LINECHARTTYPE_CURVE_STYLE, + PROP_LINECHARTTYPE_CURVE_RESOLUTION, + PROP_LINECHARTTYPE_SPLINE_ORDER +}; + +::chart::tPropertyValueMap& StaticLineChartTypeDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + []() + { + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_LINECHARTTYPE_CURVE_STYLE, ::chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_CURVE_RESOLUTION, 20 ); + + // todo: check whether order 3 means polygons of order 3 or 2. (see + // http://www.people.nnov.ru/fractal/Splines/Basis.htm ) + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_SPLINE_ORDER, 3 ); + return aOutMap; + }(); + return aStaticDefaults; +} + +::cppu::OPropertyArrayHelper& StaticLineChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { CHART_UNONAME_CURVE_STYLE, + PROP_LINECHARTTYPE_CURVE_STYLE, + cppu::UnoType<chart2::CurveStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_CURVE_RESOLUTION, + PROP_LINECHARTTYPE_CURVE_RESOLUTION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_SPLINE_ORDER, + PROP_LINECHARTTYPE_SPLINE_ORDER, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT } }; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + }()); + return aPropHelper; +} + +uno::Reference< beans::XPropertySetInfo >& StaticLineChartTypeInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticLineChartTypeInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +LineChartType::LineChartType() +{ +} + +LineChartType::LineChartType( const LineChartType & rOther ) : + ChartType( rOther ) +{ +} + +LineChartType::~LineChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL LineChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new LineChartType( *this )); +} + +rtl::Reference< ChartType > LineChartType::cloneChartType() const +{ + return new LineChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL LineChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_LINE; +} + +// ____ OPropertySet ____ +void LineChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticLineChartTypeDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL LineChartType::getInfoHelper() +{ + return StaticLineChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL LineChartType::getPropertySetInfo() +{ + return StaticLineChartTypeInfo(); +} + +OUString SAL_CALL LineChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.LineChartType"; +} + +sal_Bool SAL_CALL LineChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL LineChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_LINE, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_LineChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::LineChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/LineChartType.hxx b/chart2/source/model/template/LineChartType.hxx new file mode 100644 index 000000000..4c44cca9c --- /dev/null +++ b/chart2/source/model/template/LineChartType.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class LineChartType final : public ChartType +{ +public: + explicit LineChartType(); + virtual ~LineChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit LineChartType( const LineChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/LineChartTypeTemplate.cxx b/chart2/source/model/template/LineChartTypeTemplate.cxx new file mode 100644 index 000000000..65ce8def4 --- /dev/null +++ b/chart2/source/model/template/LineChartTypeTemplate.cxx @@ -0,0 +1,329 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "LineChartTypeTemplate.hxx" +#include "LineChartType.hxx" +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <PropertyHelper.hxx> +#include <ChartType.hxx> +#include <unonames.hxx> + +#include <com/sun/star/chart2/CurveStyle.hpp> +#include <com/sun/star/chart2/SymbolStyle.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, + PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, + PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER + +}; + +::chart::tPropertyValueMap& StaticLineChartTypeTemplateDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + []() + { + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, 20 ); + + // todo: check whether order 3 means polygons of order 3 or 2. (see + // http://www.people.nnov.ru/fractal/Splines/Basis.htm ) + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, 3 ); + return aOutMap; + }(); + return aStaticDefaults; +} + +::cppu::OPropertyArrayHelper& StaticLineChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { CHART_UNONAME_CURVE_STYLE, + PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, + cppu::UnoType<chart2::CurveStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_CURVE_RESOLUTION, + PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_SPLINE_ORDER, + PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT } }; + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + }()); + return aPropHelper; +} + +uno::Reference< beans::XPropertySetInfo >& StaticLineChartTypeTemplateInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticLineChartTypeTemplateInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +LineChartTypeTemplate::LineChartTypeTemplate( + uno::Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + bool bSymbols, + bool bHasLines /* = true */, + sal_Int32 nDim /* = 2 */ ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ), + m_bHasSymbols( bSymbols ), + m_bHasLines( bHasLines ), + m_nDim( nDim ) +{ + if( nDim == 3 ) + m_bHasSymbols = false; +} + +LineChartTypeTemplate::~LineChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void LineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticLineChartTypeTemplateDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL LineChartTypeTemplate::getInfoHelper() +{ + return StaticLineChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL LineChartTypeTemplate::getPropertySetInfo() +{ + return StaticLineChartTypeTemplateInfo(); +} + +sal_Int32 LineChartTypeTemplate::getDimension() const +{ + return m_nDim; +} + +StackMode LineChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return m_eStackMode; +} + +// ____ ChartTypeTemplate ____ +bool LineChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties ); + + // check symbol-style and line-style + // for a template with symbols (or with lines) it is ok, if there is at least one series + // with symbols (or with lines) + if( bResult ) + { + bool bSymbolFound = false; + bool bLineFound = false; + + std::vector< rtl::Reference< DataSeries > > aSeriesVec = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + for (auto const& series : aSeriesVec) + { + try + { + chart2::Symbol aSymbProp; + drawing::LineStyle eLineStyle; + + bool bCurrentHasSymbol = (series->getPropertyValue( "Symbol") >>= aSymbProp) && + (aSymbProp.Style != chart2::SymbolStyle_NONE); + + if( bCurrentHasSymbol ) + bSymbolFound = true; + + if( bCurrentHasSymbol && (!m_bHasSymbols) ) + { + bResult = false; + break; + } + + bool bCurrentHasLine = (series->getPropertyValue( "LineStyle") >>= eLineStyle) && + ( eLineStyle != drawing::LineStyle_NONE ); + + if( bCurrentHasLine ) + bLineFound = true; + + if( bCurrentHasLine && (!m_bHasLines) ) + { + bResult = false; + break; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + if(bResult) + { + if( !bLineFound && m_bHasLines && bSymbolFound ) + bResult = false; + else if( !bSymbolFound && m_bHasSymbols && bLineFound ) + bResult = false; + else if( !bLineFound && !bSymbolFound ) + return m_bHasLines && m_bHasSymbols; + } + } + + // adapt curve style, spline order and resolution + if( bResult && bAdaptProperties ) + { + try + { + rtl::Reference< ChartType > xChartType = + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ); + setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, xChartType->getPropertyValue(CHART_UNONAME_CURVE_STYLE) ); + setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, xChartType->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) ); + setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, xChartType->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return bResult; +} + +rtl::Reference< ChartType > LineChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new LineChartType(); + + xResult->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE )); + xResult->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xResult->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< ChartType > LineChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new LineChartType(); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + + xResult->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE )); + xResult->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xResult->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +void LineChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + DataSeriesHelper::switchSymbolsOnOrOff( xSeries, m_bHasSymbols, nSeriesIndex ); + DataSeriesHelper::switchLinesOnOrOff( xSeries, m_bHasLines ); + DataSeriesHelper::makeLinesThickOrThin( xSeries, m_nDim==2 ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +IMPLEMENT_FORWARD_XINTERFACE2( LineChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( LineChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/LineChartTypeTemplate.hxx b/chart2/source/model/template/LineChartTypeTemplate.hxx new file mode 100644 index 000000000..88ad1a7da --- /dev/null +++ b/chart2/source/model/template/LineChartTypeTemplate.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <StackMode.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class LineChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + explicit LineChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + bool bSymbols, + bool bHasLines = true, + sal_Int32 nDim = 2 ); + virtual ~LineChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + +private: + StackMode m_eStackMode; + bool m_bHasSymbols; + bool m_bHasLines; + sal_Int32 m_nDim; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/NetChartType.cxx b/chart2/source/model/template/NetChartType.cxx new file mode 100644 index 000000000..cb4512c74 --- /dev/null +++ b/chart2/source/model/template/NetChartType.cxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "NetChartType.hxx" +#include <PolarCoordinateSystem.hxx> +#include <servicenames_charttypes.hxx> +#include <AxisIndexDefines.hxx> +#include <AxisHelper.hxx> +#include <Axis.hxx> + +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/chart2/AxisType.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +NetChartType_Base::NetChartType_Base() +{} + +NetChartType_Base::NetChartType_Base( const NetChartType_Base & rOther ) : + ChartType( rOther ) +{ +} + +NetChartType_Base::~NetChartType_Base() +{} + +rtl::Reference< ::chart::BaseCoordinateSystem > + NetChartType_Base::createCoordinateSystem2( sal_Int32 DimensionCount ) +{ + if( DimensionCount != 2 ) + throw lang::IllegalArgumentException( + "NetChart must be two-dimensional", + static_cast< ::cppu::OWeakObject* >( this ), 0 ); + + rtl::Reference< PolarCoordinateSystem > xResult = + new PolarCoordinateSystem( DimensionCount ); + + rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( 0, MAIN_AXIS_INDEX ); + if( xAxis.is() ) + { + ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Scaling = AxisHelper::createLinearScaling(); + aScaleData.AxisType = AxisType::CATEGORY; + aScaleData.Orientation = AxisOrientation_MATHEMATICAL; + xAxis->setScaleData( aScaleData ); + } + + xAxis = xResult->getAxisByDimension2( 1, MAIN_AXIS_INDEX ); + if( xAxis.is() ) + { + ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = AxisOrientation_MATHEMATICAL; + aScaleData.AxisType = AxisType::REALNUMBER; + xAxis->setScaleData( aScaleData ); + } + + return xResult; +} + +// ____ OPropertySet ____ +void NetChartType_Base::GetDefaultValue( sal_Int32 /*nHandle*/, uno::Any& rAny ) const +{ + rAny.clear(); +} + +namespace +{ + +::cppu::OPropertyArrayHelper& StaticNetChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper(Sequence< beans::Property >{}); + return aPropHelper; +} + +uno::Reference< beans::XPropertySetInfo >& StaticNetChartTypeInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticNetChartTypeInfoHelper() ) ); + return xPropertySetInfo; +} + +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL NetChartType_Base::getInfoHelper() +{ + return StaticNetChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL NetChartType_Base::getPropertySetInfo() +{ + return StaticNetChartTypeInfo(); +} + +NetChartType::NetChartType() +{} + +NetChartType::NetChartType( const NetChartType & rOther ) : + NetChartType_Base( rOther ) +{ +} + +NetChartType::~NetChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL NetChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new NetChartType( *this )); +} + +rtl::Reference< ChartType > NetChartType::cloneChartType() const +{ + return new NetChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL NetChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_NET; +} + +OUString SAL_CALL NetChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.NetChartType"; +} + +sal_Bool SAL_CALL NetChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL NetChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_NET, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_NetChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::NetChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/NetChartType.hxx b/chart2/source/model/template/NetChartType.hxx new file mode 100644 index 000000000..ae414a27c --- /dev/null +++ b/chart2/source/model/template/NetChartType.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class NetChartType_Base : public ChartType +{ +public: + explicit NetChartType_Base(); + virtual ~NetChartType_Base() override; + +protected: + explicit NetChartType_Base( const NetChartType_Base & rOther ); + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + virtual rtl::Reference< ::chart::BaseCoordinateSystem > + createCoordinateSystem2( sal_Int32 DimensionCount ) override; +}; + +class NetChartType final : public NetChartType_Base +{ +public: + explicit NetChartType(); + virtual ~NetChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit NetChartType( const NetChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/NetChartTypeTemplate.cxx b/chart2/source/model/template/NetChartTypeTemplate.cxx new file mode 100644 index 000000000..158bffe0b --- /dev/null +++ b/chart2/source/model/template/NetChartTypeTemplate.cxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "NetChartTypeTemplate.hxx" +#include "FilledNetChartType.hxx" +#include "NetChartType.hxx" +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <ChartType.hxx> +#include <com/sun/star/chart2/SymbolStyle.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +NetChartTypeTemplate::NetChartTypeTemplate( + Reference< uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + bool bSymbols, + bool bHasLines , + bool bHasFilledArea ) : + ChartTypeTemplate( xContext, rServiceName ), + m_eStackMode( eStackMode ), + m_bHasSymbols( bSymbols ), + m_bHasLines( bHasLines ), + m_bHasFilledArea( bHasFilledArea ) +{} + +NetChartTypeTemplate::~NetChartTypeTemplate() +{} + +StackMode NetChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return m_eStackMode; +} + +void NetChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + DataSeriesHelper::switchSymbolsOnOrOff( xSeries, m_bHasSymbols, nSeriesIndex ); + DataSeriesHelper::switchLinesOnOrOff( xSeries, m_bHasLines ); + DataSeriesHelper::makeLinesThickOrThin( xSeries, true ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ ChartTypeTemplate ____ +bool NetChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties ); + + if( bResult ) + { + //filled net chart?: + if( m_bHasFilledArea ) + return true; + + // check symbol-style + // for a template with symbols it is ok, if there is at least one series + // with symbols, otherwise an unknown template is too easy to achieve + bool bSymbolFound = false; + bool bLineFound = false; + + std::vector< rtl::Reference< DataSeries > > aSeriesVec = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + for (auto const& series : aSeriesVec) + { + try + { + chart2::Symbol aSymbProp; + drawing::LineStyle eLineStyle; + + bool bCurrentHasSymbol = (series->getPropertyValue( "Symbol") >>= aSymbProp) && + (aSymbProp.Style != chart2::SymbolStyle_NONE); + + if( bCurrentHasSymbol ) + bSymbolFound = true; + + if( bCurrentHasSymbol && (!m_bHasSymbols) ) + { + bResult = false; + break; + } + + bool bCurrentHasLine = (series->getPropertyValue( "LineStyle") >>= eLineStyle) && + ( eLineStyle != drawing::LineStyle_NONE ); + + if( bCurrentHasLine ) + bLineFound = true; + + if( bCurrentHasLine && (!m_bHasLines) ) + { + bResult = false; + break; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + if(bResult) + { + if( !bLineFound && m_bHasLines && bSymbolFound ) + bResult = false; + else if( !bSymbolFound && m_bHasSymbols && bLineFound ) + bResult = false; + else if( !bLineFound && !bSymbolFound ) + return m_bHasLines && m_bHasSymbols; + } + } + + return bResult; +} + +rtl::Reference< ChartType > NetChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + if( m_bHasFilledArea ) + return new FilledNetChartType(); + else + return new NetChartType(); +} + +rtl::Reference< ChartType > NetChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult( getChartTypeForIndex( 0 ) ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + return xResult; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/NetChartTypeTemplate.hxx b/chart2/source/model/template/NetChartTypeTemplate.hxx new file mode 100644 index 000000000..b1f5ac9db --- /dev/null +++ b/chart2/source/model/template/NetChartTypeTemplate.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <StackMode.hxx> + +namespace chart +{ + +class NetChartTypeTemplate : public ChartTypeTemplate +{ +public: + explicit NetChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + bool bSymbols, + bool bHasLines = true, + bool bHasFilledArea = false + ); + virtual ~NetChartTypeTemplate() override; + +protected: + // ____ ChartTypeTemplate ____ + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + +private: + StackMode m_eStackMode; + bool m_bHasSymbols; + bool m_bHasLines; + bool m_bHasFilledArea; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/PieChartType.cxx b/chart2/source/model/template/PieChartType.cxx new file mode 100644 index 000000000..fdbfc7ced --- /dev/null +++ b/chart2/source/model/template/PieChartType.cxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "PieChartType.hxx" +#include <PropertyHelper.hxx> +#include <PolarCoordinateSystem.hxx> +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <servicenames_charttypes.hxx> +#include <AxisIndexDefines.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/AxisType.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +enum +{ + PROP_PIECHARTTYPE_USE_RINGS, + PROP_PIECHARTTYPE_3DRELATIVEHEIGHT +}; + + +::chart::tPropertyValueMap& StaticPieChartTypeDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + []() + { + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_PIECHARTTYPE_USE_RINGS, false ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, 100 ); + return aOutMap; + }(); + return aStaticDefaults; +} + +::cppu::OPropertyArrayHelper& StaticPieChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { "UseRings", + PROP_PIECHARTTYPE_USE_RINGS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { "3DRelativeHeight", + PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::MAYBEVOID } + }; + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + }()); + return aPropHelper; +} + +uno::Reference< beans::XPropertySetInfo >& StaticPieChartTypeInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo( StaticPieChartTypeInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +PieChartType::PieChartType() +{ +} + +PieChartType::PieChartType( const PieChartType & rOther ) : + ChartType( rOther ) +{ +} + +PieChartType::~PieChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL PieChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new PieChartType( *this )); +} + +rtl::Reference< ChartType > PieChartType::cloneChartType() const +{ + return new PieChartType( *this ); +} + +// ____ XChartType ____ +OUString SAL_CALL PieChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_PIE; +} + +rtl::Reference< ::chart::BaseCoordinateSystem > + PieChartType::createCoordinateSystem2( sal_Int32 DimensionCount ) +{ + rtl::Reference< PolarCoordinateSystem > xResult = + new PolarCoordinateSystem( DimensionCount ); + + for( sal_Int32 i=0; i<DimensionCount; ++i ) + { + rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX ); + if( !xAxis.is() ) + { + OSL_FAIL("a created coordinate system should have an axis for each dimension"); + continue; + } + + //hhhh todo make axis invisible + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Scaling = AxisHelper::createLinearScaling(); + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + + if( i == 0 ) + aScaleData.Orientation = chart2::AxisOrientation_REVERSE; + else + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + + //remove explicit scalings from all axes + AxisHelper::removeExplicitScaling( aScaleData ); + + xAxis->setScaleData( aScaleData ); + } + + return xResult; +} + +uno::Sequence< OUString > PieChartType::getSupportedPropertyRoles() +{ + return { "FillColor", "BorderColor" }; +} + +// ____ OPropertySet ____ +void PieChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticPieChartTypeDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL PieChartType::getInfoHelper() +{ + return StaticPieChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL PieChartType::getPropertySetInfo() +{ + return StaticPieChartTypeInfo(); +} + +OUString SAL_CALL PieChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.PieChartType"; +} + +sal_Bool SAL_CALL PieChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL PieChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_PIE, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_PieChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::PieChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/PieChartType.hxx b/chart2/source/model/template/PieChartType.hxx new file mode 100644 index 000000000..5a1e46f43 --- /dev/null +++ b/chart2/source/model/template/PieChartType.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class PieChartType final: public ChartType +{ +public: + explicit PieChartType(); + virtual ~PieChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit PieChartType( const PieChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedPropertyRoles() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + virtual rtl::Reference< ::chart::BaseCoordinateSystem > + createCoordinateSystem2( sal_Int32 DimensionCount ) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/PieChartTypeTemplate.cxx b/chart2/source/model/template/PieChartTypeTemplate.cxx new file mode 100644 index 000000000..c8d82b761 --- /dev/null +++ b/chart2/source/model/template/PieChartTypeTemplate.cxx @@ -0,0 +1,567 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "PieChartTypeTemplate.hxx" +#include "PieChartType.hxx" +#include <BaseCoordinateSystem.hxx> +#include <CommonConverters.hxx> +#include <ChartType.hxx> +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <ThreeDHelper.hxx> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <officecfg/Office/Compatibility.hxx> +#include <tools/diagnose_ex.h> + +#include <rtl/math.hxx> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +enum +{ + PROP_PIE_TEMPLATE_DEFAULT_OFFSET, + PROP_PIE_TEMPLATE_OFFSET_MODE, + PROP_PIE_TEMPLATE_DIMENSION, + PROP_PIE_TEMPLATE_USE_RINGS +}; + +::chart::tPropertyValueMap& StaticPieChartTypeTemplateDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + []{ + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_PIE_TEMPLATE_OFFSET_MODE, chart2::PieChartOffsetMode_NONE ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( aOutMap, PROP_PIE_TEMPLATE_DEFAULT_OFFSET, 0.5 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_PIE_TEMPLATE_DIMENSION, 2 ); + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_PIE_TEMPLATE_USE_RINGS, false ); + return aOutMap; + }(); + return aStaticDefaults; +} + +::cppu::OPropertyArrayHelper& StaticPieChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { "OffsetMode", + PROP_PIE_TEMPLATE_OFFSET_MODE, + cppu::UnoType<chart2::PieChartOffsetMode>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { "DefaultOffset", + PROP_PIE_TEMPLATE_DEFAULT_OFFSET, + cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { "Dimension", + PROP_PIE_TEMPLATE_DIMENSION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { "UseRings", + PROP_PIE_TEMPLATE_USE_RINGS, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT } }; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + }() ); + return aPropHelper; +} + +uno::Reference< beans::XPropertySetInfo >& StaticPieChartTypeTemplateInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticPieChartTypeTemplateInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +PieChartTypeTemplate::PieChartTypeTemplate( + uno::Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + chart2::PieChartOffsetMode eMode, + bool bRings /* = false */, + sal_Int32 nDim /* = 2 */ ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ) +{ + setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_OFFSET_MODE, uno::Any( eMode )); + setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_DIMENSION, uno::Any( nDim )); + setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_USE_RINGS, uno::Any( bRings )); +} + +PieChartTypeTemplate::~PieChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void PieChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticPieChartTypeTemplateDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL PieChartTypeTemplate::getInfoHelper() +{ + return StaticPieChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL PieChartTypeTemplate::getPropertySetInfo() +{ + return StaticPieChartTypeTemplateInfo(); +} + +// ____ ChartTypeTemplate ____ +sal_Int32 PieChartTypeTemplate::getDimension() const +{ + sal_Int32 nDim = 2; + try + { + // note: UNO-methods are never const + const_cast< PieChartTypeTemplate * >( this )-> + getFastPropertyValue( PROP_PIE_TEMPLATE_DIMENSION ) >>= nDim; + } + catch( const beans::UnknownPropertyException & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return nDim; +} + +sal_Int32 PieChartTypeTemplate::getAxisCountByDimension( sal_Int32 /*nDimension*/ ) +{ + return 0; +} + +void PieChartTypeTemplate::adaptAxes( + const std::vector< rtl::Reference< BaseCoordinateSystem > > & /*rCoordSys*/ ) +{ + // hide existing axes + //hhhh todo +} + +void PieChartTypeTemplate::adaptScales( + const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq, + const Reference< chart2::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 ) + ) +{ + ChartTypeTemplate::adaptScales( aCooSysSeq, xCategories ); + + //remove explicit scalings from radius axis + //and ensure correct orientation of scales for donuts + + for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq ) + { + try + { + rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 1 /*nDimensionIndex*/,0 /*nAxisIndex*/ + , coords ); + if( xAxis.is() ) + { + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + AxisHelper::removeExplicitScaling( aScaleData ); + // tdf#108059 Create new pie/donut charts with clockwise orientation + if (!officecfg::Office::Compatibility::View::ClockwisePieChartDirection::get()) + { + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + } + else + { + aScaleData.Orientation = chart2::AxisOrientation_REVERSE; + } + xAxis->setScaleData( aScaleData ); + } + + xAxis = AxisHelper::getAxis( 0 /*nDimensionIndex*/,0 /*nAxisIndex*/ + , coords ); + if( xAxis.is() ) + { + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + + //tdf#123218 Don't reverse the orientation in OOXML-heavy environments + if( officecfg::Office::Compatibility::View::ReverseXAxisOrientationDoughnutChart::get() ) + aScaleData.Orientation = chart2::AxisOrientation_REVERSE; + else + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + xAxis->setScaleData( aScaleData ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } +} + +void PieChartTypeTemplate::createChartTypes( + const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq, + const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > >& /* aOldChartTypesSeq */ ) +{ + if( rCoordSys.empty() ) + return; + + try + { + rtl::Reference< ChartType > xCT = new PieChartType(); + xCT->setPropertyValue( + "UseRings", getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); + rCoordSys[0]->setChartTypes( std::vector{xCT} ); + + if( !aSeriesSeq.empty() ) + { + std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq = FlattenSequence( aSeriesSeq ); + xCT->setDataSeries( aFlatSeriesSeq ); + + DataSeriesHelper::setStackModeAtSeries( + aFlatSeriesSeq, rCoordSys[0], getStackMode( 0 )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XChartTypeTemplate ____ +bool PieChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties ); + + bool bTemplateUsesRings = false; + getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS ) >>= bTemplateUsesRings; + chart2::PieChartOffsetMode ePieOffsetMode; + getFastPropertyValue( PROP_PIE_TEMPLATE_OFFSET_MODE ) >>= ePieOffsetMode; + + //check offset-mode + if( bResult ) + { + try + { + double fOffset=0.0; + bool bAllOffsetsEqual = true; + sal_Int32 nOuterSeriesIndex = 0; + + std::vector< rtl::Reference< DataSeries > > aSeriesVec = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + //tdf#108067 The outer series is the last series in OOXML-heavy environments + if( !officecfg::Office::Compatibility::View::ReverseXAxisOrientationDoughnutChart::get() ) + nOuterSeriesIndex = aSeriesVec.size() - 1; + + //check offset of outer series + if( !aSeriesVec.empty() ) + { + //@todo in future this will depend on Orientation of the radius axis scale + rtl::Reference< DataSeries > xSeries( aSeriesVec[nOuterSeriesIndex] ); + xSeries->getPropertyValue( "Offset") >>= fOffset; + + //get AttributedDataPoints + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeries->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList ) + { + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + { + uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); + if(xPointProp.is()) + { + double fPointOffset=0.0; + if( xSeries->getPropertyValue( "Offset") >>= fPointOffset ) + { + if( ! ::rtl::math::approxEqual( fPointOffset, fOffset ) ) + { + bAllOffsetsEqual = false; + break; + } + } + } + } + } + } + + chart2::PieChartOffsetMode eOffsetMode = chart2::PieChartOffsetMode_NONE; + if( bAllOffsetsEqual && fOffset > 0.0 ) + { + eOffsetMode = chart2::PieChartOffsetMode_ALL_EXPLODED; + if( bAdaptProperties ) + setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_DEFAULT_OFFSET, uno::Any( fOffset )); + } + + bResult = ( eOffsetMode == ePieOffsetMode ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + bResult = false; + } + } + + //check UseRings + if( bResult ) + { + rtl::Reference< ChartType > xCTProp = + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ); + bool bUseRings = false; + if( xCTProp->getPropertyValue( "UseRings") >>= bUseRings ) + { + bResult = ( bTemplateUsesRings == bUseRings ); + } + } + + return bResult; +} + +rtl::Reference< ChartType > PieChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new PieChartType(); + xResult->setPropertyValue( + "UseRings", getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< ChartType > PieChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new PieChartType(); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + xResult->setPropertyValue( + "UseRings", getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +void PieChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + bool bTemplateUsesRings = false; + sal_Int32 nOuterSeriesIndex = 0; + getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS ) >>= bTemplateUsesRings; + + //tdf#108067 The outer series is the last series in OOXML-heavy environments + if( !officecfg::Office::Compatibility::View::ReverseXAxisOrientationDoughnutChart::get() ) + nOuterSeriesIndex = nSeriesCount - 1; + + if( nSeriesIndex == nOuterSeriesIndex ) //@todo in future this will depend on Orientation of the radius axis scale + { + static const OUStringLiteral aOffsetPropName( u"Offset" ); + // get offset mode + chart2::PieChartOffsetMode ePieOffsetMode; + getFastPropertyValue( PROP_PIE_TEMPLATE_OFFSET_MODE ) >>= ePieOffsetMode; + + // get default offset + double fDefaultOffset = 0.5; + getFastPropertyValue( PROP_PIE_TEMPLATE_DEFAULT_OFFSET ) >>= fDefaultOffset; + double fOffsetToSet = fDefaultOffset; + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + xSeries->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList; + + // determine whether to set the new offset + bool bSetOffset = ( ePieOffsetMode == chart2::PieChartOffsetMode_ALL_EXPLODED ); + if( !bSetOffset && + (ePieOffsetMode == chart2::PieChartOffsetMode_NONE) ) + { + // set offset to 0 if the offset was exactly "all exploded" + // before (individual offsets are kept) + double fOffset = 0.0; + if( (xSeries->getPropertyValue( aOffsetPropName ) >>= fOffset) && + ::rtl::math::approxEqual( fOffset, fDefaultOffset )) + { + fOffsetToSet = 0.0; + bSetOffset = true; + for( auto const & pointIndex : std::as_const(aAttributedDataPointIndexList) ) + { + uno::Reference< beans::XPropertySet > xPointProp( + xSeries->getDataPointByIndex( pointIndex )); + uno::Reference< beans::XPropertyState > xPointState( xPointProp, uno::UNO_QUERY ); + double fPointOffset = 0.0; + if( xPointState.is() && + (xPointState->getPropertyState( aOffsetPropName ) == beans::PropertyState_DIRECT_VALUE) && + xPointProp.is() && + (xPointProp->getPropertyValue( aOffsetPropName ) >>= fPointOffset ) && + ! ::rtl::math::approxEqual( fPointOffset, fDefaultOffset ) ) + { + bSetOffset = false; + break; + } + } + } + } + + if( bSetOffset ) + { + // set the offset to the series and to the attributed data points + xSeries->setPropertyValue( aOffsetPropName, uno::Any( fOffsetToSet )); + + // remove hard attributes from data points + for( auto const & pointIndex : std::as_const(aAttributedDataPointIndexList) ) + { + uno::Reference< beans::XPropertyState > xPointState( + xSeries->getDataPointByIndex( pointIndex ), uno::UNO_QUERY ); + if( xPointState.is()) + xPointState->setPropertyToDefault( aOffsetPropName ); + } + } + } + + // line style + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); + + // vary colors by point + xSeries->setPropertyValue( "VaryColorsByPoint", uno::Any( true )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void PieChartTypeTemplate::resetStyles2( const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + // reset axes and grids + if( xDiagram.is()) + { + const std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysSeq( xDiagram->getBaseCoordinateSystems()); + ChartTypeTemplate::createAxes( aCooSysSeq ); + + //reset scale orientation + for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq ) + { + try + { + rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 0 /*nDimensionIndex*/,0 /*nAxisIndex*/ + , coords ); + if( xAxis.is() ) + { + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + xAxis->setScaleData( aScaleData ); + } + + xAxis = AxisHelper::getAxis( 1, 0, coords ); + if( xAxis.is() ) + { + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + xAxis->setScaleData( aScaleData ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + ChartTypeTemplate::resetStyles2( xDiagram ); + + // vary colors by point, + // line style + std::vector< rtl::Reference< DataSeries > > aSeriesVec = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + uno::Any aLineStyleAny( drawing::LineStyle_NONE ); + for (auto const& series : aSeriesVec) + { + series->setPropertyToDefault( "VaryColorsByPoint"); + if( series->getPropertyValue( "BorderStyle") == aLineStyleAny ) + { + series->setPropertyToDefault( "BorderStyle"); + } + } + + //reset scene properties + ThreeDHelper::setDefaultRotation( xDiagram, false ); +} + +// ____ XChartTypeTemplate ____ +void PieChartTypeTemplate::adaptDiagram( const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + if( !xDiagram.is() ) + return; + + //different default for scene geometry: + ThreeDHelper::setDefaultRotation( xDiagram, true ); +} + +IMPLEMENT_FORWARD_XINTERFACE2( PieChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( PieChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/PieChartTypeTemplate.hxx b/chart2/source/model/template/PieChartTypeTemplate.hxx new file mode 100644 index 000000000..06e80bbb3 --- /dev/null +++ b/chart2/source/model/template/PieChartTypeTemplate.hxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +#include <ChartTypeTemplate.hxx> +#include <com/sun/star/chart2/PieChartOffsetMode.hpp> + +namespace chart +{ + +class PieChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + PieChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + css::chart2::PieChartOffsetMode eMode, + bool bRings, + sal_Int32 nDim = 2 ); + virtual ~PieChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void resetStyles2( + const rtl::Reference< ::chart::Diagram >& xDiagram ) override; + + // ____ ChartTypeTemplate ____ + virtual sal_Int32 getDimension() const override; + + virtual void adaptDiagram( + const rtl::Reference< ::chart::Diagram > & xDiagram ) override; + + virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension ) override; + + virtual void adaptAxes( + const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & rCoordSys ) override; + + virtual void adaptScales( + const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & aCooSysSeq, + const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories ) override; + + virtual void createChartTypes( + const std::vector< + std::vector< + rtl::Reference< + ::chart::DataSeries > > >& aSeriesSeq, + const std::vector< + rtl::Reference< + ::chart::BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq + ) override; + + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ScatterChartType.cxx b/chart2/source/model/template/ScatterChartType.cxx new file mode 100644 index 000000000..cee026913 --- /dev/null +++ b/chart2/source/model/template/ScatterChartType.cxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ScatterChartType.hxx" +#include <PropertyHelper.hxx> +#include <servicenames_charttypes.hxx> +#include <CartesianCoordinateSystem.hxx> +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <AxisIndexDefines.hxx> +#include <unonames.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/CurveStyle.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +enum +{ + PROP_SCATTERCHARTTYPE_CURVE_STYLE, + PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION, + PROP_SCATTERCHARTTYPE_SPLINE_ORDER +}; + +::chart::tPropertyValueMap& StaticScatterChartTypeDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + []() + { + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_SCATTERCHARTTYPE_CURVE_STYLE, chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION, 20 ); + + // todo: check whether order 3 means polygons of order 3 or 2. (see + // http://www.people.nnov.ru/fractal/Splines/Basis.htm ) + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_SPLINE_ORDER, 3 ); + return aOutMap; + }(); + return aStaticDefaults; +} + +::cppu::OPropertyArrayHelper& StaticScatterChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { CHART_UNONAME_CURVE_STYLE, + PROP_SCATTERCHARTTYPE_CURVE_STYLE, + cppu::UnoType<chart2::CurveStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_CURVE_RESOLUTION, + PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_SPLINE_ORDER, + PROP_SCATTERCHARTTYPE_SPLINE_ORDER, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT } }; + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + return comphelper::containerToSequence( aProperties ); + }() ); + return aPropHelper; +} + +const uno::Reference< beans::XPropertySetInfo >& StaticScatterChartTypeInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticScatterChartTypeInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +ScatterChartType::ScatterChartType() +{ +} + +ScatterChartType::ScatterChartType( const ScatterChartType & rOther ) : + ChartType( rOther ) +{ +} + +ScatterChartType::~ScatterChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL ScatterChartType::createClone() +{ + return uno::Reference< util::XCloneable >( new ScatterChartType( *this )); +} + +rtl::Reference< ChartType > ScatterChartType::cloneChartType() const +{ + return new ScatterChartType( *this ); +} + +// ____ XChartType ____ +rtl::Reference< ::chart::BaseCoordinateSystem > + ScatterChartType::createCoordinateSystem2( sal_Int32 DimensionCount ) +{ + rtl::Reference< CartesianCoordinateSystem > xResult = + new CartesianCoordinateSystem( DimensionCount ); + + for( sal_Int32 i=0; i<DimensionCount; ++i ) + { + rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX ); + if( !xAxis.is() ) + { + OSL_FAIL("a created coordinate system should have an axis for each dimension"); + continue; + } + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + + if( i == 2 ) + aScaleData.AxisType = chart2::AxisType::SERIES; + else + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + + xAxis->setScaleData( aScaleData ); + } + + return xResult; +} + +OUString SAL_CALL ScatterChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_SCATTER; +} + +uno::Sequence< OUString > SAL_CALL ScatterChartType::getSupportedMandatoryRoles() +{ + return { "label", "values-x", "values-y" }; +} + +// ____ OPropertySet ____ +void ScatterChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticScatterChartTypeDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL ScatterChartType::getInfoHelper() +{ + return StaticScatterChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScatterChartType::getPropertySetInfo() +{ + return StaticScatterChartTypeInfo(); +} + +OUString SAL_CALL ScatterChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.ScatterChartType"; +} + +sal_Bool SAL_CALL ScatterChartType::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL ScatterChartType::getSupportedServiceNames() +{ + return { + CHART2_SERVICE_NAME_CHARTTYPE_SCATTER, + "com.sun.star.chart2.ChartType", + "com.sun.star.beans.PropertySet" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_ScatterChartType_get_implementation(css::uno::XComponentContext * /*context*/, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::ScatterChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ScatterChartType.hxx b/chart2/source/model/template/ScatterChartType.hxx new file mode 100644 index 000000000..f490c108c --- /dev/null +++ b/chart2/source/model/template/ScatterChartType.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ + +class ScatterChartType final : public ChartType +{ +public: + ScatterChartType(); + virtual ~ScatterChartType() override; + + virtual OUString SAL_CALL + getImplementationName() override; + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +private: + explicit ScatterChartType( const ScatterChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedMandatoryRoles() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override; + + virtual rtl::Reference< ::chart::BaseCoordinateSystem > + createCoordinateSystem2( sal_Int32 DimensionCount ) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ScatterChartTypeTemplate.cxx b/chart2/source/model/template/ScatterChartTypeTemplate.cxx new file mode 100644 index 000000000..91fe7bba5 --- /dev/null +++ b/chart2/source/model/template/ScatterChartTypeTemplate.cxx @@ -0,0 +1,345 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ScatterChartTypeTemplate.hxx" +#include "ScatterChartType.hxx" +#include "XYDataInterpreter.hxx" +#include <ChartType.hxx> +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <PropertyHelper.hxx> +#include <unonames.hxx> + +#include <com/sun/star/chart2/CurveStyle.hpp> +#include <com/sun/star/chart2/SymbolStyle.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, + PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, + PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER + +}; + +const ::chart::tPropertyValueMap& StaticScatterChartTypeTemplateDefaults() +{ + static const ::chart::tPropertyValueMap aStaticDefaults = + []() + { + ::chart::tPropertyValueMap aOutMap; + ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, 20 ); + + // todo: check whether order 3 means polygons of order 3 or 2. (see + // http://www.people.nnov.ru/fractal/Splines/Basis.htm ) + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, 3 ); + return aOutMap; + }(); + return aStaticDefaults; +} + + +::cppu::OPropertyArrayHelper& StaticScatterChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper( + []() + { + std::vector< css::beans::Property > aProperties { + { CHART_UNONAME_CURVE_STYLE, + PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, + cppu::UnoType<chart2::CurveStyle>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_CURVE_RESOLUTION, + PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT }, + { CHART_UNONAME_SPLINE_ORDER, + PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT } }; + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + return comphelper::containerToSequence( aProperties ); + }() ); + return aPropHelper; +} + +const uno::Reference< beans::XPropertySetInfo >& StaticScatterChartTypeTemplateInfo() +{ + static const uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticScatterChartTypeTemplateInfoHelper() ) ); + return xPropertySetInfo; +} + +} // anonymous namespace + +namespace chart +{ + +ScatterChartTypeTemplate::ScatterChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + bool bSymbols, + bool bHasLines /* = true */, + sal_Int32 nDim /* = 2 */ ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_bHasSymbols( bSymbols ), + m_bHasLines( bHasLines ), + m_nDim( nDim ) +{ + if( nDim == 3 ) + m_bHasSymbols = false; +} + +ScatterChartTypeTemplate::~ScatterChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void ScatterChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticScatterChartTypeTemplateDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL ScatterChartTypeTemplate::getInfoHelper() +{ + return StaticScatterChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScatterChartTypeTemplate::getPropertySetInfo() +{ + return StaticScatterChartTypeTemplateInfo(); +} + +sal_Int32 ScatterChartTypeTemplate::getDimension() const +{ + return m_nDim; +} + +StackMode ScatterChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + if( m_nDim == 3 ) + return StackMode::ZStacked; + return StackMode::NONE; +} + +void ScatterChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + DataSeriesHelper::switchSymbolsOnOrOff( xSeries, m_bHasSymbols, nSeriesIndex ); + DataSeriesHelper::switchLinesOnOrOff( xSeries, m_bHasLines ); + DataSeriesHelper::makeLinesThickOrThin( xSeries, m_nDim==2 ); + if( m_nDim==3 ) + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL ScatterChartTypeTemplate::supportsCategories() +{ + return false; +} + +bool ScatterChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties ); + + // check symbol-style and line-style + // for a template with symbols (or with lines) it is ok, if there is at least one series + // with symbols (or with lines) + if( bResult ) + { + bool bSymbolFound = false; + bool bLineFound = false; + + std::vector< rtl::Reference< DataSeries > > aSeriesVec = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + for (auto const& series : aSeriesVec) + { + try + { + chart2::Symbol aSymbProp; + drawing::LineStyle eLineStyle; + + bool bCurrentHasSymbol = (series->getPropertyValue( "Symbol") >>= aSymbProp) && + (aSymbProp.Style != chart2::SymbolStyle_NONE); + + if( bCurrentHasSymbol ) + bSymbolFound = true; + + if( bCurrentHasSymbol && (!m_bHasSymbols) ) + { + bResult = false; + break; + } + + bool bCurrentHasLine = (series->getPropertyValue( "LineStyle") >>= eLineStyle) && + ( eLineStyle != drawing::LineStyle_NONE ); + + if( bCurrentHasLine ) + bLineFound = true; + + if( bCurrentHasLine && (!m_bHasLines) ) + { + bResult = false; + break; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + if(bResult) + { + if( !bLineFound && m_bHasLines && bSymbolFound ) + bResult = false; + else if( !bSymbolFound && m_bHasSymbols && bLineFound ) + bResult = false; + else if( !bLineFound && !bSymbolFound ) + return m_bHasLines && m_bHasSymbols; + } + } + + // adapt curve style, spline order and resolution + if( bResult && bAdaptProperties ) + { + try + { + rtl::Reference< ChartType > xChartTypeProp = + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ); + setFastPropertyValue_NoBroadcast( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, xChartTypeProp->getPropertyValue(CHART_UNONAME_CURVE_STYLE) ); + setFastPropertyValue_NoBroadcast( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, xChartTypeProp->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) ); + setFastPropertyValue_NoBroadcast( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, xChartTypeProp->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return bResult; +} + +rtl::Reference< ChartType > ScatterChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new ScatterChartType(); + + xResult->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE )); + xResult->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xResult->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< ChartType > ScatterChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new ScatterChartType(); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + + xResult->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE )); + xResult->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xResult->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< DataInterpreter > ScatterChartTypeTemplate::getDataInterpreter2() +{ + if( ! m_xDataInterpreter.is()) + m_xDataInterpreter.set( new XYDataInterpreter ); + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2( ScatterChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScatterChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ScatterChartTypeTemplate.hxx b/chart2/source/model/template/ScatterChartTypeTemplate.hxx new file mode 100644 index 000000000..88441b844 --- /dev/null +++ b/chart2/source/model/template/ScatterChartTypeTemplate.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class ScatterChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + explicit ScatterChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + bool bSymbols, + bool bHasLines = true, + sal_Int32 nDim = 2 ); + virtual ~ScatterChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual sal_Bool SAL_CALL supportsCategories() override; + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + +private: + bool m_bHasSymbols; + bool m_bHasLines; + sal_Int32 m_nDim; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/StockChartTypeTemplate.cxx b/chart2/source/model/template/StockChartTypeTemplate.cxx new file mode 100644 index 000000000..bd14ac3c4 --- /dev/null +++ b/chart2/source/model/template/StockChartTypeTemplate.cxx @@ -0,0 +1,435 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "StockChartTypeTemplate.hxx" +#include "ColumnChartType.hxx" +#include "CandleStickChartType.hxx" +#include "LineChartType.hxx" +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include "StockDataInterpreter.hxx" +#include <DiagramHelper.hxx> +#include <Diagram.hxx> +#include <BaseCoordinateSystem.hxx> +#include <servicenames_charttypes.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <tools/diagnose_ex.h> + +#include <algorithm> +#include <cstddef> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +enum +{ + PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME, + PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, + PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH, + PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "Volume", + PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Open", + PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "LowHigh", + PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Japanese", + PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +::chart::tPropertyValueMap& GetStaticStockChartTypeTemplateDefaults() +{ + static ::chart::tPropertyValueMap aStaticDefaults = + [](){ + ::chart::tPropertyValueMap aTmp; + ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, false ); + ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH, true ); + ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE, false ); + return aTmp; + }(); + return aStaticDefaults; +}; + +::cppu::OPropertyArrayHelper& GetStaticStockChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = + [](){ + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + }(); + return aPropHelper; +}; + + +uno::Reference< beans::XPropertySetInfo >& GetStaticStockChartTypeTemplateInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(GetStaticStockChartTypeTemplateInfoHelper() ) ); + return xPropertySetInfo; +}; + +} // anonymous namespace + +namespace chart +{ + +StockChartTypeTemplate::StockChartTypeTemplate( + uno::Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StockVariant eVariant, + bool bJapaneseStyle ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStockVariant( eVariant ) +{ + setFastPropertyValue_NoBroadcast( + PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, + uno::Any( ( eVariant == StockVariant::Open || + eVariant == StockVariant::VolumeOpen ))); + setFastPropertyValue_NoBroadcast( + PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME, + uno::Any( ( eVariant == StockVariant::Volume || + eVariant == StockVariant::VolumeOpen ))); + setFastPropertyValue_NoBroadcast( + PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE, + uno::Any( bJapaneseStyle )); +} + +StockChartTypeTemplate::~StockChartTypeTemplate() +{} + +// ____ OPropertySet ____ +void StockChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const +{ + const tPropertyValueMap& rStaticDefaults = GetStaticStockChartTypeTemplateDefaults(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL StockChartTypeTemplate::getInfoHelper() +{ + return GetStaticStockChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL StockChartTypeTemplate::getPropertySetInfo() +{ + return GetStaticStockChartTypeTemplateInfo(); +} + +sal_Int32 StockChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension ) +{ + // one x-axis + if( nDimension <= 0 ) + return 1; + // no further axes + if( nDimension >= 2 ) + return 0; + + // one or two y-axes depending on volume + OSL_ASSERT( nDimension == 1 ); + bool bHasVolume = false; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + return bHasVolume ? 2 : 1; +} + +void StockChartTypeTemplate::applyStyle2( + const rtl::Reference< DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + try + { + sal_Int32 nNewAxisIndex = 0; + + bool bHasVolume = false; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + if( bHasVolume && nChartTypeIndex != 0 ) + nNewAxisIndex = 1; + + xSeries->setPropertyValue( "AttachedAxisIndex", uno::Any( nNewAxisIndex ) ); + + if( bHasVolume && nChartTypeIndex==0 ) + { + //switch lines off for volume bars + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); + } + else + { + //ensure that lines are on + drawing::LineStyle eStyle = drawing::LineStyle_NONE; + xSeries->getPropertyValue( "LineStyle" ) >>= eStyle; + if( eStyle == drawing::LineStyle_NONE ) + xSeries->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID )); + } + + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void StockChartTypeTemplate::resetStyles2( + const rtl::Reference< ::chart::Diagram >& xDiagram ) +{ + ChartTypeTemplate::resetStyles2( xDiagram ); + if( getDimension() == 3 ) + { + std::vector< rtl::Reference< DataSeries > > aSeriesVec = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + for (auto const& series : aSeriesVec) + { + series->setPropertyValue( "AttachedAxisIndex", uno::Any( sal_Int32(0) ) ); + } + } + + DiagramHelper::setVertical( xDiagram, false ); +} + +rtl::Reference< ChartType > StockChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex ) +{ + rtl::Reference< ChartType > xCT; + bool bHasVolume = false; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + if( bHasVolume ) + { + if( nChartTypeIndex == 0 ) + xCT = new ColumnChartType(); + else if( nChartTypeIndex == 1 ) + xCT = new CandleStickChartType(); + else + xCT = new LineChartType(); + } + else + { + if( nChartTypeIndex == 0 ) + xCT = new CandleStickChartType(); + else + xCT = new LineChartType(); + } + return xCT; +} + +void StockChartTypeTemplate::createChartTypes( + const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq, + const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > >& /* aOldChartTypesSeq */ ) +{ + if( rCoordSys.empty() ) + return; + + try + { + bool bHasVolume = false; + bool bShowFirst = false; + bool bJapaneseStyle = false; + bool bShowHighLow = true; + + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_OPEN ) >>= bShowFirst; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE ) >>= bJapaneseStyle; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH ) >>= bShowHighLow; + + std::size_t nSeriesIndex = 0; + + std::vector< rtl::Reference< ChartType > > aChartTypeVec; + // Bars (Volume) + if( bHasVolume ) + { + // chart type + rtl::Reference< ChartType > xCT = new ColumnChartType(); + aChartTypeVec.push_back( xCT ); + + if( aSeriesSeq.size() > nSeriesIndex && + !aSeriesSeq[nSeriesIndex].empty() ) + { + xCT->setDataSeries( aSeriesSeq[ nSeriesIndex ] ); + } + ++nSeriesIndex; + } + + rtl::Reference< ChartType > xCT = new CandleStickChartType(); + aChartTypeVec.push_back( xCT ); + + xCT->setPropertyValue( "Japanese", uno::Any( bJapaneseStyle )); + xCT->setPropertyValue( "ShowFirst", uno::Any( bShowFirst )); + xCT->setPropertyValue( "ShowHighLow", uno::Any( bShowHighLow )); + + if( aSeriesSeq.size() > nSeriesIndex && + !aSeriesSeq[ nSeriesIndex ].empty() ) + { + xCT->setDataSeries( aSeriesSeq[ nSeriesIndex ] ); + } + ++nSeriesIndex; + + // Lines (remaining series) + if( aSeriesSeq.size() > nSeriesIndex && + !aSeriesSeq[ nSeriesIndex ].empty() ) + { + xCT = new LineChartType(); + aChartTypeVec.push_back( xCT ); + + xCT->setDataSeries( aSeriesSeq[ nSeriesIndex ] ); + } + + rCoordSys[ 0 ]->setChartTypes( aChartTypeVec ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ ChartTypeTemplate ____ +bool StockChartTypeTemplate::matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool /* bAdaptProperties */ ) +{ + bool bResult = false; + + if( ! xDiagram.is()) + return bResult; + + try + { + bool bHasVolume = false, bHasOpenValue = false, bHasJapaneseStyle = false; + + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_OPEN ) >>= bHasOpenValue; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE ) >>= bHasJapaneseStyle; + + rtl::Reference< ChartType > xVolumeChartType; + rtl::Reference< ChartType > xCandleStickChartType; + rtl::Reference< ChartType > xLineChartType; + sal_Int32 nNumberOfChartTypes = 0; + + for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() ) + { + for( rtl::Reference< ChartType > const & chartType : coords->getChartTypes2() ) + { + ++nNumberOfChartTypes; + if( nNumberOfChartTypes > 3 ) + break; + OUString aCTService = chartType->getChartType(); + if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) + xVolumeChartType = chartType; + else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + xCandleStickChartType = chartType; + else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_LINE ) + xLineChartType = chartType; + } + if( nNumberOfChartTypes > 3 ) + break; + } + + if (xCandleStickChartType.is() && bHasVolume == xVolumeChartType.is()) + { + bResult = true; + + // check for japanese style + bool bJapaneseProp = false; + xCandleStickChartType->getPropertyValue( "Japanese") >>= bJapaneseProp; + bResult = bResult && ( bHasJapaneseStyle == bJapaneseProp ); + + // in old chart japanese == showFirst + bool bShowFirstProp = false; + xCandleStickChartType->getPropertyValue( "ShowFirst") >>= bShowFirstProp; + bResult = bResult && ( bHasOpenValue == bShowFirstProp ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return bResult; +} + +rtl::Reference< ChartType > StockChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes ) +{ + rtl::Reference< ChartType > xResult; + + try + { + xResult = new LineChartType(); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +rtl::Reference< DataInterpreter > StockChartTypeTemplate::getDataInterpreter2() +{ + if( ! m_xDataInterpreter.is()) + m_xDataInterpreter.set( new StockDataInterpreter( m_eStockVariant ) ); + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2( StockChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( StockChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/StockChartTypeTemplate.hxx b/chart2/source/model/template/StockChartTypeTemplate.hxx new file mode 100644 index 000000000..78d6c02e1 --- /dev/null +++ b/chart2/source/model/template/StockChartTypeTemplate.hxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <ChartTypeTemplate.hxx> +#include <OPropertySet.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class StockChartTypeTemplate : + public cppu::BaseMutex, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + enum class StockVariant + { + NONE, + Open, + Volume, + VolumeOpen + }; + + /** CTOR + + @param bJapaneseStyle + If true, the candlesticks are drawn as solid white or black boxes + depending on rising or falling stock-values. Otherwise the + open-value will be drawn as a small line at the left side of a + straight vertical line, and the close-value on the right hand side. + */ + explicit StockChartTypeTemplate( + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StockVariant eVariant, + bool bJapaneseStyle ); + virtual ~StockChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual bool matchesTemplate2( + const rtl::Reference< ::chart::Diagram >& xDiagram, + bool bAdaptProperties ) override; + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForNewSeries2( const std::vector< + rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override; + virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override; + virtual void applyStyle2( + const rtl::Reference< ::chart::DataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void resetStyles2( + const rtl::Reference< ::chart::Diagram >& xDiagram ) override; + + // ChartTypeTemplate + virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension ) override; + + // ____ ChartTypeTemplate ____ + virtual void createChartTypes( + const std::vector< + std::vector< + rtl::Reference< + ::chart::DataSeries > > >& aSeriesSeq, + const std::vector< + rtl::Reference< + ::chart::BaseCoordinateSystem > > & rCoordSys, + const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq + ) override; + + virtual rtl::Reference< ::chart::ChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + +private: + // todo: deprecate this variable + StockVariant m_eStockVariant; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/StockDataInterpreter.cxx b/chart2/source/model/template/StockDataInterpreter.cxx new file mode 100644 index 000000000..24072f718 --- /dev/null +++ b/chart2/source/model/template/StockDataInterpreter.cxx @@ -0,0 +1,342 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cstddef> + +#include "StockDataInterpreter.hxx" +#include "StockChartTypeTemplate.hxx" +#include <DataSeries.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +// explicit +StockDataInterpreter::StockDataInterpreter( + StockChartTypeTemplate::StockVariant eVariant ) : + m_eStockVariant( eVariant ) +{} + +StockDataInterpreter::~StockDataInterpreter() +{} + +// ____ XDataInterpreter ____ +InterpretedData StockDataInterpreter::interpretDataSource( + const Reference< data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& rArguments, + const std::vector< rtl::Reference< ::chart::DataSeries > >& rSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + + uno::Reference< chart2::data::XLabeledDataSequence > xCategories; + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = DataInterpreter::getDataSequences(xSource); + const sal_Int32 nDataCount( aData.size()); + + // sub-type properties + const StockChartTypeTemplate::StockVariant eVar( GetStockVariant()); + const bool bHasOpenValues (( eVar == StockChartTypeTemplate::StockVariant::Open ) || + ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen )); + const bool bHasVolume (( eVar == StockChartTypeTemplate::StockVariant::Volume ) || + ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen )); + const bool bHasCategories( HasCategories( rArguments, aData )); + + // necessary roles for "full series" + // low/high/close + sal_Int32 nNumberOfNecessarySequences( 3 ); + if( bHasOpenValues ) + ++nNumberOfNecessarySequences; + if( bHasVolume ) + ++nNumberOfNecessarySequences; + + // calculate number of full series (nNumOfFullSeries) and the number of remaining + // sequences used for additional "incomplete series" (nRemaining) + sal_Int32 nNumOfFullSeries( 0 ); + sal_Int32 nRemaining( 0 ); + { + sal_Int32 nAvailableSequences( nDataCount ); + if( bHasCategories ) + --nAvailableSequences; + nNumOfFullSeries = nAvailableSequences / nNumberOfNecessarySequences; + nRemaining = nAvailableSequences % nNumberOfNecessarySequences; + } + sal_Int32 nCandleStickSeries = nNumOfFullSeries; + sal_Int32 nVolumeSeries = nNumOfFullSeries; + + sal_Int32 nNumberOfGroups( bHasVolume ? 2 : 1 ); + // sequences of data::XLabeledDataSequence per series per group + std::vector< std::vector< std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > > > aSequences( nNumberOfGroups ); + const sal_Int32 nBarGroupIndex( 0 ); + const sal_Int32 nCandleStickGroupIndex( nNumberOfGroups - 1 ); + + // allocate space for labeled sequences + if( nRemaining > 0 ) + ++nCandleStickSeries; + aSequences[nCandleStickGroupIndex].resize( nCandleStickSeries ); + auto & pCandleStickGroup = aSequences[nCandleStickGroupIndex]; + if( bHasVolume ) + { + // if there are remaining sequences, the first one is taken for + // additional close values, the second one is taken as volume, if volume + // is used + if( nRemaining > 1 ) + ++nVolumeSeries; + aSequences[nBarGroupIndex].resize( nVolumeSeries ); + } + auto & pBarGroup = aSequences[nBarGroupIndex]; + + // create data + sal_Int32 nSourceIndex = 0; // index into aData sequence + + // 1. categories + if( bHasCategories ) + { + xCategories = aData[nSourceIndex]; + ++nSourceIndex; + } + + // 2. create "full" series + for( sal_Int32 nLabeledSeqIdx=0; nLabeledSeqIdx<nNumOfFullSeries; ++nLabeledSeqIdx ) + { + // bar + if( bHasVolume ) + { + pBarGroup[nLabeledSeqIdx].resize( 1 ); + pBarGroup[nLabeledSeqIdx][0] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-y"); + ++nSourceIndex; + } + + sal_Int32 nSeqIdx = 0; + if( bHasOpenValues ) + { + pCandleStickGroup[nLabeledSeqIdx].resize( 4 ); + pCandleStickGroup[nLabeledSeqIdx][nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-first"); + ++nSourceIndex; + ++nSeqIdx; + } + else + pCandleStickGroup[nLabeledSeqIdx].resize( 3 ); + auto & pLabeledSeq = pCandleStickGroup[nLabeledSeqIdx]; + + pLabeledSeq[nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-min"); + ++nSourceIndex; + ++nSeqIdx; + + pLabeledSeq[nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-max"); + ++nSourceIndex; + ++nSeqIdx; + + pLabeledSeq[nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-last"); + ++nSourceIndex; + ++nSeqIdx; + } + + // 3. create series with remaining sequences + if( bHasVolume && nRemaining > 1 ) + { + OSL_ASSERT( nVolumeSeries > nNumOfFullSeries ); + pBarGroup[nVolumeSeries - 1].resize( 1 ); + OSL_ASSERT( nDataCount > nSourceIndex ); + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-y"); + pBarGroup[nVolumeSeries - 1][0] = aData[nSourceIndex]; + ++nSourceIndex; + --nRemaining; + OSL_ENSURE( nRemaining, "additional bar should only be used if there is at least one more sequence for a candle stick" ); + } + + // candle-stick + if( nRemaining > 0 ) + { + OSL_ASSERT( nCandleStickSeries > nNumOfFullSeries ); + const sal_Int32 nSeriesIndex = nCandleStickSeries - 1; + pCandleStickGroup[nSeriesIndex].resize( nRemaining ); + auto & pLabeledSeq = pCandleStickGroup[nSeriesIndex]; + OSL_ASSERT( nDataCount > nSourceIndex ); + + // 1. low + sal_Int32 nSeqIdx( 0 ); + pLabeledSeq[nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-min"); + ++nSourceIndex; + ++nSeqIdx; + + // 2. high + if( nSeqIdx < nRemaining ) + { + pLabeledSeq[nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-max"); + ++nSourceIndex; + ++nSeqIdx; + } + + // 3. close + OSL_ENSURE( bHasOpenValues || nSeqIdx >= nRemaining, "could have created full series" ); + if( nSeqIdx < nRemaining ) + { + pLabeledSeq[nSeqIdx] = aData[nSourceIndex]; + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-last"); + ++nSourceIndex; + ++nSeqIdx; + } + + // 4. open + OSL_ENSURE( nSeqIdx >= nRemaining, "could have created full series" ); + } + + // create DataSeries + std::vector< std::vector< rtl::Reference< DataSeries > > > aResultSeries( nNumberOfGroups ); + sal_Int32 nGroupIndex; + std::size_t nReUsedSeriesIdx = 0; + for( nGroupIndex=0; nGroupIndex<nNumberOfGroups; ++nGroupIndex ) + { + const sal_Int32 nNumSeriesData = aSequences[nGroupIndex].size(); + aResultSeries[nGroupIndex].resize( nNumSeriesData ); + auto & pResultSerie = aResultSeries[nGroupIndex]; + for( sal_Int32 nSeriesIdx = 0; nSeriesIdx < nNumSeriesData; ++nSeriesIdx, ++nReUsedSeriesIdx ) + { + try + { + rtl::Reference< DataSeries > xSeries; + if( nReUsedSeriesIdx < rSeriesToReUse.size()) + xSeries = rSeriesToReUse[nReUsedSeriesIdx]; + else + xSeries = new DataSeries; + assert( xSeries.is() ); + xSeries->setData( aSequences[nGroupIndex][nSeriesIdx] ); + pResultSerie[nSeriesIdx] = xSeries; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + return { aResultSeries, xCategories }; +} + +// criterion: there must be two groups for stock-charts with volume and all +// series must have the correct number of data::XLabeledDataSequences + +// todo: skip first criterion? (to allow easy switch from stock-chart without +// volume to one with volume) +bool StockDataInterpreter::isDataCompatible( + const InterpretedData& aInterpretedData ) +{ + // high/low/close + std::size_t nNumberOfNecessarySequences = 3; + // open + StockChartTypeTemplate::StockVariant eVar( GetStockVariant()); + if( ( eVar == StockChartTypeTemplate::StockVariant::Open ) || + ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen )) + ++nNumberOfNecessarySequences; + // volume + bool bHasVolume = (( eVar == StockChartTypeTemplate::StockVariant::Volume ) || + ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen )); + + // 1. correct number of sub-types + if( aInterpretedData.Series.size() < (bHasVolume ? 2U : 1U )) + return false; + + // 2. a. volume -- use default check + if( bHasVolume ) + { + if( ! DataInterpreter::isDataCompatible( + { std::vector< std::vector< rtl::Reference< DataSeries > > >{ + aInterpretedData.Series[0] }, + aInterpretedData.Categories })) + return false; + } + + // 2. b. candlestick + { + OSL_ASSERT( aInterpretedData.Series.size() > (bHasVolume ? 1U : 0U)); + const std::vector< rtl::Reference< DataSeries > > & aSeries = aInterpretedData.Series[(bHasVolume ? 1 : 0)]; + if(aSeries.empty()) + return false; + for( rtl::Reference< DataSeries > const & dataSeries : aSeries ) + { + try + { + if( dataSeries->getDataSequences2().size() != nNumberOfNecessarySequences ) + return false; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + // 2. c. additional series + // ignore + + return true; +} + +InterpretedData StockDataInterpreter::reinterpretDataSeries( + const InterpretedData& aInterpretedData ) +{ + // prerequisite: StockDataInterpreter::isDataCompatible() returned true + return aInterpretedData; +} + +uno::Any StockDataInterpreter::getChartTypeSpecificData( + const OUString& sKey ) +{ + if( sKey == "stock variant" ) + { + StockChartTypeTemplate::StockVariant eStockVariant( GetStockVariant()); + std::map< StockChartTypeTemplate::StockVariant, sal_Int32 > aTranslation { + { StockChartTypeTemplate::StockVariant::NONE, 0 }, + { StockChartTypeTemplate::StockVariant::Open, 1 }, + { StockChartTypeTemplate::StockVariant::Volume, 2 }, + { StockChartTypeTemplate::StockVariant::VolumeOpen, 3 } + }; + return uno::Any( aTranslation[eStockVariant] ); + } + return uno::Any(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/StockDataInterpreter.hxx b/chart2/source/model/template/StockDataInterpreter.hxx new file mode 100644 index 000000000..4617da597 --- /dev/null +++ b/chart2/source/model/template/StockDataInterpreter.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <DataInterpreter.hxx> + +#include "StockChartTypeTemplate.hxx" + +namespace chart +{ + +class StockDataInterpreter : public DataInterpreter +{ +public: + explicit StockDataInterpreter( + StockChartTypeTemplate::StockVariant eVariant ); + virtual ~StockDataInterpreter() override; + +protected: + // ____ XDataInterpreter ____ + virtual InterpretedData interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse ) override; + virtual bool isDataCompatible( + const InterpretedData& aInterpretedData ) override; + virtual InterpretedData reinterpretDataSeries( + const InterpretedData& aInterpretedData ) override; + virtual css::uno::Any getChartTypeSpecificData( + const OUString& sKey ) override; + +private: + StockChartTypeTemplate::StockVariant m_eStockVariant; + + StockChartTypeTemplate::StockVariant GetStockVariant() const { return m_eStockVariant;} +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/XYDataInterpreter.cxx b/chart2/source/model/template/XYDataInterpreter.cxx new file mode 100644 index 000000000..d77a3df39 --- /dev/null +++ b/chart2/source/model/template/XYDataInterpreter.cxx @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cstddef> + +#include "XYDataInterpreter.hxx" +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <CommonConverters.hxx> +#include <com/sun/star/util/XCloneable.hpp> +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +XYDataInterpreter::XYDataInterpreter() +{ +} + +XYDataInterpreter::~XYDataInterpreter() +{ +} + +// ____ XDataInterpreter ____ +InterpretedData XYDataInterpreter::interpretDataSource( + const Reference< chart2::data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = DataInterpreter::getDataSequences(xSource); + + uno::Reference< chart2::data::XLabeledDataSequence > xValuesX; + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequencesVec; + + uno::Reference< chart2::data::XLabeledDataSequence > xCategories; + bool bHasCategories = HasCategories( aArguments, aData ); + bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); + + // parse data + bool bCategoriesUsed = false; + bool bSetXValues = aData.size()>1; + for( uno::Reference< chart2::data::XLabeledDataSequence > const & labelData : aData ) + { + try + { + if( bHasCategories && ! bCategoriesUsed ) + { + xCategories = labelData; + if( xCategories.is()) + { + SetRole( xCategories->getValues(), "categories"); + if( bUseCategoriesAsX ) + bSetXValues = false; + } + bCategoriesUsed = true; + } + else if( !xValuesX.is() && bSetXValues ) + { + xValuesX = labelData; + if( xValuesX.is()) + SetRole( xValuesX->getValues(), "values-x"); + } + else + { + aSequencesVec.push_back( labelData ); + if( labelData.is()) + SetRole( labelData->getValues(), "values-y"); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + // create DataSeries + vector< rtl::Reference< DataSeries > > aSeriesVec; + aSeriesVec.reserve( aSequencesVec.size()); + + Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; + Reference< util::XCloneable > xCloneable( xValuesX, uno::UNO_QUERY ); + + std::size_t nSeriesIndex = 0; + for (auto const& elem : aSequencesVec) + { + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewData; + + if( nSeriesIndex && xCloneable.is() ) + xClonedXValues.set( xCloneable->createClone(), uno::UNO_QUERY ); + if( xValuesX.is() ) + aNewData.push_back( xClonedXValues ); + + aNewData.push_back(elem); + + rtl::Reference< DataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.size()) + xSeries = aSeriesToReUse[nSeriesIndex]; + else + xSeries = new DataSeries; + assert( xSeries.is() ); + xSeries->setData( aNewData ); + + aSeriesVec.push_back( xSeries ); + ++nSeriesIndex; + } + + return { { aSeriesVec }, xCategories }; +} + +InterpretedData XYDataInterpreter::reinterpretDataSeries( + const InterpretedData& aInterpretedData ) +{ + InterpretedData aResult( aInterpretedData ); + + sal_Int32 i=0; + std::vector< rtl::Reference< DataSeries > > aSeries = FlattenSequence( aInterpretedData.Series ); + const sal_Int32 nCount = aSeries.size(); + for( ; i<nCount; ++i ) + { + try + { + std::vector< uno::Reference< data::XLabeledDataSequence > > aNewSequences; + + // values-y + uno::Reference< chart2::data::XLabeledDataSequence > xValuesY( + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-y" )); + uno::Reference< chart2::data::XLabeledDataSequence > xValuesX( + DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-x" )); + // re-use values-... as values-x/values-y + if( ! xValuesX.is() || + ! xValuesY.is()) + { + vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValueSeqVec( + DataSeriesHelper::getAllDataSequencesByRole( + aSeries[i]->getDataSequences2(), "values" )); + if( xValuesX.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX )); + if( xValuesY.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY )); + + size_t nIndex = 0; + if( ! xValuesY.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesY = aValueSeqVec[nIndex++]; + if( xValuesY.is()) + SetRole( xValuesY->getValues(), "values-y"); + } + + if( ! xValuesX.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesX = aValueSeqVec[nIndex++]; + if( xValuesX.is()) + SetRole( xValuesY->getValues(), "values-x"); + } + } + if( xValuesY.is()) + { + if( xValuesX.is()) + { + aNewSequences = { xValuesX, xValuesY }; + } + else + { + aNewSequences = { xValuesY }; + } + } + + const std::vector< uno::Reference< data::XLabeledDataSequence > > & aSeqs = aSeries[i]->getDataSequences2(); + if( aSeqs.size() != aNewSequences.size() ) + { +#ifdef DBG_UTIL + for( auto const & j : aSeqs ) + { + SAL_WARN_IF((j == xValuesY || j == xValuesX), "chart2.template", "All sequences should be used" ); + } +#endif + aSeries[i]->setData( aNewSequences ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +// criterion: all series must have exactly two data::XLabeledDataSequences +bool XYDataInterpreter::isDataCompatible( + const InterpretedData& aInterpretedData ) +{ + const std::vector< rtl::Reference< DataSeries > > aSeries = FlattenSequence( aInterpretedData.Series ); + for( rtl::Reference< DataSeries > const & dataSeries : aSeries ) + { + try + { + if( dataSeries->getDataSequences2().size() != 2 ) + return false; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return true; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/XYDataInterpreter.hxx b/chart2/source/model/template/XYDataInterpreter.hxx new file mode 100644 index 000000000..56343013d --- /dev/null +++ b/chart2/source/model/template/XYDataInterpreter.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <DataInterpreter.hxx> + +namespace chart +{ + +class XYDataInterpreter : public DataInterpreter +{ +public: + explicit XYDataInterpreter(); + virtual ~XYDataInterpreter() override; + +protected: + // ____ DataInterpreter ____ + virtual InterpretedData interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse ) override; + virtual InterpretedData reinterpretDataSeries( + const InterpretedData& aInterpretedData ) override; + virtual bool isDataCompatible( + const InterpretedData& aInterpretedData ) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |