summaryrefslogtreecommitdiffstats
path: root/chart2/source/model/main
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /chart2/source/model/main
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/source/model/main')
-rw-r--r--chart2/source/model/main/Axis.cxx601
-rw-r--r--chart2/source/model/main/BaseCoordinateSystem.cxx387
-rw-r--r--chart2/source/model/main/CartesianCoordinateSystem.cxx160
-rw-r--r--chart2/source/model/main/ChartModel.cxx1339
-rw-r--r--chart2/source/model/main/ChartModel_Persistence.cxx802
-rw-r--r--chart2/source/model/main/DataPoint.cxx255
-rw-r--r--chart2/source/model/main/DataPoint.hxx109
-rw-r--r--chart2/source/model/main/DataPointProperties.cxx544
-rw-r--r--chart2/source/model/main/DataPointProperties.hxx103
-rw-r--r--chart2/source/model/main/DataSeries.cxx733
-rw-r--r--chart2/source/model/main/DataSeriesProperties.cxx99
-rw-r--r--chart2/source/model/main/DataTable.cxx209
-rw-r--r--chart2/source/model/main/Diagram.cxx2288
-rw-r--r--chart2/source/model/main/FormattedString.cxx276
-rw-r--r--chart2/source/model/main/GridProperties.cxx201
-rw-r--r--chart2/source/model/main/Legend.cxx275
-rw-r--r--chart2/source/model/main/PageBackground.cxx198
-rw-r--r--chart2/source/model/main/PageBackground.hxx100
-rw-r--r--chart2/source/model/main/PolarCoordinateSystem.cxx158
-rw-r--r--chart2/source/model/main/StockBar.cxx173
-rw-r--r--chart2/source/model/main/Title.cxx343
-rw-r--r--chart2/source/model/main/UndoManager.cxx350
-rw-r--r--chart2/source/model/main/UndoManager.hxx92
-rw-r--r--chart2/source/model/main/Wall.cxx155
-rw-r--r--chart2/source/model/main/Wall.hxx95
25 files changed, 10045 insertions, 0 deletions
diff --git a/chart2/source/model/main/Axis.cxx b/chart2/source/model/main/Axis.cxx
new file mode 100644
index 0000000000..26a6d48368
--- /dev/null
+++ b/chart2/source/model/main/Axis.cxx
@@ -0,0 +1,601 @@
+/* -*- 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 <Title.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 <comphelper/diagnose_ex.hxx>
+#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 );
+
+}
+} // namespace
+
+namespace chart
+{
+const ::chart::tPropertyValueMap & StaticAxisDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::CharacterProperties::AddDefaultsToMap( aMap );
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aMap );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_SHOW, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_CROSSOVER_POSITION, css::chart::ChartAxisPosition_ZERO );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_DISPLAY_LABELS, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_LABEL_POSITION, css::chart::ChartAxisLabelPosition_NEAR_AXIS );
+ ::chart::PropertyHelper::setPropertyValueDefault< double >( aMap, PROP_AXIS_TEXT_ROTATION, 0.0 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_BREAK, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_OVERLAP, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_STACKED, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_ARRANGE_ORDER, css::chart::ChartAxisArrangeOrderType_AUTO );
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_AXIS_MAJOR_TICKMARKS, 2 /* CHAXIS_MARK_OUTER */ );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_AXIS_MINOR_TICKMARKS, 0 /* CHAXIS_MARK_NONE */ );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_MARK_POSITION, css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_DISPLAY_UNITS, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TRY_STAGGERING_FIRST, false );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+::cppu::OPropertyArrayHelper& StaticAxisInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+std::vector< rtl::Reference< ::chart::GridProperties > > lcl_CloneSubGrids(
+ const std::vector< rtl::Reference< ::chart::GridProperties > > & rSource )
+{
+ std::vector< rtl::Reference< ::chart::GridProperties > > aDestination;
+ aDestination.reserve( rSource.size());
+ for( rtl::Reference< ::chart::GridProperties > const & i : rSource )
+ {
+ aDestination.push_back(new ::chart::GridProperties(*i));
+ }
+ return aDestination;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Axis::Axis() :
+ 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_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_aScaleData( rOther.m_aScaleData )
+{
+ if (rOther.m_xGrid)
+ m_xGrid = new ::chart::GridProperties(*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.empty() )
+ m_aSubGridProperties = lcl_CloneSubGrids( rOther.m_aSubGridProperties );
+ ModifyListenerHelper::addListenerToAllElements( m_aSubGridProperties, m_xModifyEventForwarder );
+
+ if ( rOther.m_xTitle )
+ m_xTitle = new Title( *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::removeListenerFromAllElements( 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.clear();
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ m_aSubGridProperties.clear();
+ m_xGrid = nullptr;
+ m_xTitle = nullptr;
+}
+
+void Axis::AllocateSubGrids()
+{
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ Reference< lang::XEventListener > xEventListener;
+ std::vector< rtl::Reference< GridProperties > > aOldBroadcasters;
+ std::vector< rtl::Reference< GridProperties > > aNewBroadcasters;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ xEventListener = this;
+
+ sal_Int32 nNewSubIncCount = m_aScaleData.IncrementData.SubIncrements.getLength();
+ sal_Int32 nOldSubIncCount = m_aSubGridProperties.size();
+
+ if( nOldSubIncCount > nNewSubIncCount )
+ {
+ // remove superfluous entries
+ for( sal_Int32 i = nNewSubIncCount; i < nOldSubIncCount; ++i )
+ aOldBroadcasters.push_back( m_aSubGridProperties[ i ] );
+ m_aSubGridProperties.resize( nNewSubIncCount );
+ }
+ else if( nOldSubIncCount < nNewSubIncCount )
+ {
+ m_aSubGridProperties.resize( nNewSubIncCount );
+
+ // allocate new entries
+ for( sal_Int32 i = nOldSubIncCount; i < nNewSubIncCount; ++i )
+ {
+ m_aSubGridProperties[ 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;
+}
+rtl::Reference< ::chart::GridProperties > Axis::getGridProperties2()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xGrid;
+}
+Sequence< Reference< beans::XPropertySet > > SAL_CALL Axis::getSubGridProperties()
+{
+ MutexGuard aGuard( m_aMutex );
+ return comphelper::containerToSequence<Reference< beans::XPropertySet >>(m_aSubGridProperties);
+}
+
+std::vector< rtl::Reference< GridProperties > > Axis::getSubGridProperties2()
+{
+ 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;
+}
+
+rtl::Reference< Title > Axis::getTitleObject2() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xTitle;
+}
+
+void SAL_CALL Axis::setTitleObject( const Reference< chart2::XTitle >& xNewTitle )
+{
+ rtl::Reference<Title> xTitle = dynamic_cast<Title*>(xNewTitle.get());
+ assert(!xNewTitle || xTitle);
+ setTitleObject(xTitle);
+}
+
+void Axis::setTitleObject( const rtl::Reference< Title >& xNewTitle )
+{
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ rtl::Reference< Title > 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();
+ 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();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL Axis::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticAxisInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+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 0000000000..8af32fa096
--- /dev/null
+++ b/chart2/source/model/main/BaseCoordinateSystem.cxx
@@ -0,0 +1,387 @@
+/* -*- 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 <comphelper/diagnose_ex.hxx>
+
+#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 );
+}
+
+const ::chart::tPropertyValueMap & StaticCooSysDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_COORDINATESYSTEM_SWAPXANDYAXIS, false );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticCooSysInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+BaseCoordinateSystem::BaseCoordinateSystem(
+ sal_Int32 nDimensionCount /* = 2 */ ) :
+ 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_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();
+ 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();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL BaseCoordinateSystem::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticCooSysInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+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 0000000000..1f1320d8ae
--- /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 OUString CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME = u"com.sun.star.chart2.CoordinateSystems.Cartesian"_ustr;
+
+}
+
+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 0000000000..19fccff373
--- /dev/null
+++ b/chart2/source/model/main/ChartModel.cxx
@@ -0,0 +1,1339 @@
+/* -*- 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 <RangeHighlighter.hxx>
+#include <Diagram.hxx>
+#include <comphelper/dumpxmltostring.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 <utility>
+#include <comphelper/diagnose_ex.hxx>
+#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 OUString lcl_aGDIMetaFileMIMEType(
+ u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr);
+constexpr OUString lcl_aGDIMetaFileMIMETypeHighContrast(
+ u"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr);
+
+} // anonymous namespace
+
+// ChartModel Constructor and Destructor
+
+namespace chart
+{
+
+ChartModel::ChartModel(uno::Reference<uno::XComponentContext > 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(std::move( 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;
+ rtl::Reference< Title > xNewTitle;
+ if ( rOther.m_xTitle )
+ xNewTitle = new Title(*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()
+{
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aCloseListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
+ m_aLifeTimeManager.m_aCloseListeners.notifyEach(aGuard, &util::XCloseListener::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();
+
+ if (m_xRangeHighlighter)
+ {
+ m_xRangeHighlighter->dispose();
+ m_xRangeHighlighter.clear();
+ }
+ 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;
+
+ if (m_xRangeHighlighter)
+ {
+ m_xRangeHighlighter->dispose();
+ m_xRangeHighlighter.clear();
+ }
+ 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();
+ m_xTitle.clear();
+ 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();
+
+ if (m_xRangeHighlighter)
+ {
+ m_xRangeHighlighter->dispose();
+ m_xRangeHighlighter.clear();
+ }
+ 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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aEventListeners.addInterface( aGuard, 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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aEventListeners.removeInterface( aGuard, 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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aCloseListeners.removeInterface( aGuard, 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 = new RangeHighlighter( 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;
+}
+
+rtl::Reference< Title > ChartModel::getTitleObject2() const
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xTitle;
+}
+
+void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& xNewTitle )
+{
+ rtl::Reference<Title> xTitle = dynamic_cast<Title*>(xNewTitle.get());
+ assert(!xNewTitle || xTitle);
+ setTitleObject(xTitle);
+}
+
+void ChartModel::setTitleObject( const rtl::Reference< Title >& 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(OUString const & kind)
+{
+ if (kind.isEmpty()) {
+ return comphelper::dumpXmlToString([this](auto writer) { return dumpAsXml(writer); });
+ }
+
+ // kind == "shapes":
+ uno::Reference< qa::XDumper > xDumper(
+ createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
+ if (xDumper.is())
+ return xDumper->dump(kind);
+
+ 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 0000000000..03824aab5c
--- /dev/null
+++ b/chart2/source/model/main/ChartModel_Persistence.cxx
@@ -0,0 +1,802 @@
+/* -*- 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 <unotools/tempfile.hxx>
+#include <utility>
+#include <vcl/cvtgrf.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#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( OUString aStrToCompareWith ) :
+ m_aStr(std::move( aStrToCompareWith ))
+ {}
+ 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 )
+ {
+ rtl::Reference< utl::TempFileFastService > xStream = new utl::TempFileFastService;
+ 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 );
+
+ xStream->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 ));
+ xDiagram->setScheme( 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 );
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aModifyListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
+ m_aLifeTimeManager.m_aModifyListeners.notifyEach(aGuard, &util::XModifyListener::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 )
+ {
+ if (bModified)
+ m_bUpdateNotificationsPending = true; // Maybe !bModified should reset it?
+ 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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aModifyListeners.addInterface( aGuard, 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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aModifyListeners.removeInterface( aGuard, 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());
+
+ Diagram::tTemplateWithServiceName aTemplateAndService = xDiagram->getTemplate(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()
+{
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aStorageChangeListeners.getLength(aGuard) )
+ {
+ m_aLifeTimeManager.m_aStorageChangeListeners.forEach(aGuard,
+ [this](const uno::Reference<document::XStorageChangeListener>& l)
+ {
+ l->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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aStorageChangeListeners.addInterface( aGuard, 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
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aStorageChangeListeners.removeInterface(aGuard, 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 0000000000..d6c8a9e2ac
--- /dev/null
+++ b/chart2/source/model/main/DataPoint.cxx
@@ -0,0 +1,255 @@
+/* -*- 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 <comphelper/diagnose_ex.hxx>
+
+#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
+{
+
+::cppu::OPropertyArrayHelper& StaticDataPointInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+DataPoint::DataPoint( const uno::Reference< beans::XPropertySet > & rParentProperties ) :
+ m_xParentProperties( rParentProperties ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_bNoParentPropAllowed( false )
+{
+ SetNewValuesExplicitlyEvenIfTheyEqualDefault();
+}
+
+DataPoint::DataPoint( const DataPoint & rOther ) :
+ impl::DataPoint_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL DataPoint::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataPointInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ 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 0000000000..ba94449fff
--- /dev/null
+++ b/chart2/source/model/main/DataPoint.hxx
@@ -0,0 +1,109 @@
+/* -*- 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 <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 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 0000000000..819336edd9
--- /dev/null
+++ b/chart2/source/model/main/DataPointProperties.cxx
@@ -0,0 +1,544 @@
+/* -*- 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>
+
+#include <tools/color.hxx>
+
+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( rOutMap, PROP_DATAPOINT_COLOR, Color(0x99, 0xcc, 0xff) ); // blue 8
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TRANSPARENCY, sal_Int16(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( rOutMap, PROP_DATAPOINT_BORDER_COLOR, COL_BLACK );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_STYLE, drawing::LineStyle_SOLID ); // drawing::LineStyle_NONE
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_WIDTH, sal_Int32(0) );
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_DASH_NAME );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_TRANSPARENCY, sal_Int16(0) );
+
+ //line
+ PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_SOLID );
+ PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_WIDTH, sal_Int32(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( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, drawing::RectanglePoint_MIDDLE_MIDDLE );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, true );
+
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, sal_Int32(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, sal_Int32(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 = sal_Int32(COL_BLACK);
+ aSymbProp.FillColor = 0xee4000; // OrangeRed2
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_SYMBOL_PROP, aSymbProp );
+
+ PropertyHelper::setPropertyValueDefault( 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( rOutMap, PROP_DATAPOINT_PERCENT_DIAGONAL, sal_Int16(0) );
+
+ PropertyHelper::setPropertyValueDefault( 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( rOutMap, PROP_DATAPOINT_LABEL_SEPARATOR, OUString(" ") );
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_STYLE, 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(rOutMap, PROP_DATAPOINT_LABEL_BORDER_WIDTH, sal_Int32(0));
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH, drawing::LineDash());
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH_NAME);
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_TRANS, sal_Int16(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 0000000000..ada7907b88
--- /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 0000000000..38f2c474b4
--- /dev/null
+++ b/chart2/source/model/main/DataSeries.cxx
@@ -0,0 +1,733 @@
+/* -*- 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/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.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 chart
+{
+const ::chart::tPropertyValueMap & StaticDataSeriesDefaults()
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::DataSeriesProperties::AddDefaultsToMap( aMap );
+ ::chart::CharacterProperties::AddDefaultsToMap( aMap );
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticDataSeriesInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper oHelper = []()
+ {
+ 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 );
+ }();
+ return oHelper;
+};
+
+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() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+DataSeries::DataSeries( const DataSeries & rOther ) :
+ impl::DataSeries_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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();
+ 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();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper() );
+ return xPropSetInfo;
+}
+
+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" };
+}
+
+static Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > & rDataSequences )
+{
+ Reference< chart2::data::XLabeledDataSequence > xResult;
+
+ for( auto const & labeledData : rDataSequences )
+ {
+ OSL_ENSURE( labeledData.is(), "empty LabeledDataSequence" );
+ // no values are set but a label exists
+ if( labeledData.is() &&
+ ( ! labeledData->getValues().is() &&
+ labeledData->getLabel().is()))
+ {
+ xResult.set( labeledData );
+ break;
+ }
+ }
+
+ return xResult;
+}
+
+static OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence )
+{
+ OUString aResult;
+
+ Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY );
+ if( xTextSeq.is())
+ {
+ Sequence< OUString > aSeq( xTextSeq->getTextualData());
+
+ const sal_Int32 nMax = aSeq.getLength() - 1;
+ OUStringBuffer aBuf;
+
+ for( sal_Int32 i = 0; i <= nMax; ++i )
+ {
+ aBuf.append( aSeq[i] );
+ if( i < nMax )
+ aBuf.append( ' ');
+ }
+ aResult = aBuf.makeStringAndClear();
+ }
+ else if( xSequence.is())
+ {
+ Sequence< uno::Any > aSeq( xSequence->getData());
+
+ const sal_Int32 nMax = aSeq.getLength() - 1;
+ OUString aVal;
+ OUStringBuffer aBuf;
+ double fNum = 0;
+
+ for( sal_Int32 i = 0; i <= nMax; ++i )
+ {
+ if( aSeq[i] >>= aVal )
+ {
+ aBuf.append( aVal );
+ if( i < nMax )
+ aBuf.append( ' ');
+ }
+ else if( aSeq[ i ] >>= fNum )
+ {
+ aBuf.append( fNum );
+ if( i < nMax )
+ aBuf.append( ' ');
+ }
+ }
+ aResult = aBuf.makeStringAndClear();
+ }
+
+ return aResult;
+}
+
+static OUString getLabelForLabeledDataSequence(
+ const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq )
+{
+ OUString aResult;
+ if( xLabeledSeq.is())
+ {
+ Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
+ if( xSeq.is() )
+ aResult = lcl_getDataSequenceLabel( xSeq );
+ if( !xSeq.is() || aResult.isEmpty() )
+ {
+ // no label set or label content is empty -> use auto-generated one
+ Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
+ if( xValueSeq.is() )
+ {
+ Sequence< OUString > aLabels( xValueSeq->generateLabel(
+ chart2::data::LabelOrigin_SHORT_SIDE ) );
+ // no labels returned is interpreted as: auto-generation not
+ // supported by sequence
+ if( aLabels.hasElements() )
+ aResult=aLabels[0];
+ else
+ {
+ //todo?: maybe use the index of the series as name
+ //but as the index may change it would be better to have such a name persistent
+ //what is not possible at the moment
+ //--> maybe use the identifier as part of the name ...
+ aResult = lcl_getDataSequenceLabel( xValueSeq );
+ }
+ }
+ }
+ }
+ return aResult;
+}
+
+OUString DataSeries::getLabelForRole( const OUString & rLabelSequenceRole )
+{
+ OUString aResult;
+
+ Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
+ ::chart::DataSeriesHelper::getDataSequenceByRole( this, rLabelSequenceRole ));
+ if( xLabeledSeq.is())
+ aResult = getLabelForLabeledDataSequence( xLabeledSeq );
+ else
+ {
+ // special case: labeled data series with only a label and no values may
+ // serve as label
+ xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( getDataSequences() ));
+ if( xLabeledSeq.is())
+ {
+ Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
+ if( xSeq.is())
+ aResult = lcl_getDataSequenceLabel( xSeq );
+ }
+ }
+
+ return aResult;
+}
+
+static bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
+{
+ if (!xDataSequence.is())
+ return false;
+ uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ uno::Sequence< sal_Int32 > aHiddenValues;
+ try
+ {
+ xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenValues;
+ if( !aHiddenValues.hasElements() )
+ return true;
+ }
+ catch( const uno::Exception& )
+ {
+ return true;
+ }
+ }
+ return xDataSequence->getData().hasElements();
+}
+
+bool DataSeries::hasUnhiddenData()
+{
+ MutexGuard aGuard( m_aMutex );
+
+ for(uno::Reference< chart2::data::XLabeledDataSequence > const & rDataSequence : m_aDataSequences)
+ {
+ if( !rDataSequence.is() )
+ continue;
+ if( lcl_SequenceHasUnhiddenData( rDataSequence->getValues() ) )
+ return true;
+ }
+ return false;
+}
+
+
+} // 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 0000000000..e6d40feb5a
--- /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( rOutMap, PROP_DATASERIES_ATTACHED_AXIS_INDEX, sal_Int32(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/DataTable.cxx b/chart2/source/model/main/DataTable.cxx
new file mode 100644
index 0000000000..6cec190615
--- /dev/null
+++ b/chart2/source/model/main/DataTable.cxx
@@ -0,0 +1,209 @@
+/* -*- 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/.
+ */
+
+#include <DataTable.hxx>
+
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <CharacterProperties.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+
+#include <algorithm>
+
+using namespace css;
+
+namespace
+{
+/** DataTable Properties */
+enum
+{
+ DataTableProperty_HorizontalBorder,
+ DataTableProperty_VerticalBorder,
+ DataTableProperty_Outilne,
+ DataTableProperty_Keys,
+};
+
+void lcl_AddPropertiesToVector(std::vector<beans::Property>& rProps)
+{
+ auto const nBound = beans::PropertyAttribute::BOUND;
+ auto const nMaybeDefault = beans::PropertyAttribute::MAYBEDEFAULT;
+
+ rProps.emplace_back("HBorder", DataTableProperty_HorizontalBorder, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+ rProps.emplace_back("VBorder", DataTableProperty_VerticalBorder, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+ rProps.emplace_back("Outline", DataTableProperty_Outilne, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+ rProps.emplace_back("Keys", DataTableProperty_Keys, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+}
+
+const ::chart::tPropertyValueMap& StaticDataTableDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []() {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap(aMap);
+ ::chart::FillProperties::AddDefaultsToMap(aMap);
+ ::chart::CharacterProperties::AddDefaultsToMap(aMap);
+
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_HorizontalBorder,
+ false);
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_VerticalBorder,
+ false);
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_Outilne, false);
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_Keys, false);
+
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::LinePropertiesHelper::PROP_LINE_WIDTH, uno::Any(sal_Int32(1)));
+
+ ::chart::PropertyHelper::setPropertyValueDefault(
+ aMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE);
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight);
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight);
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight);
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+
+cppu::OPropertyArrayHelper& StaticDataTableInfoHelper()
+{
+ static cppu::OPropertyArrayHelper aPropHelper = []() {
+ std::vector<beans::Property> aProperties;
+ lcl_AddPropertiesToVector(aProperties);
+ ::chart::LinePropertiesHelper::AddPropertiesToVector(aProperties);
+ ::chart::FillProperties::AddPropertiesToVector(aProperties);
+ ::chart::CharacterProperties::AddPropertiesToVector(aProperties);
+ std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess());
+
+ return comphelper::containerToSequence(aProperties);
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+DataTable::DataTable()
+ : m_xModifyEventForwarder(new ModifyEventForwarder())
+{
+}
+
+DataTable::DataTable(const DataTable& rOther)
+ : DataTable_Base(rOther)
+ , ::property::OPropertySet(rOther)
+ , m_xModifyEventForwarder(new ModifyEventForwarder())
+{
+}
+
+DataTable::~DataTable() = default;
+
+// ____ XCloneable ____
+uno::Reference<util::XCloneable> SAL_CALL DataTable::createClone()
+{
+ return uno::Reference<util::XCloneable>(new DataTable(*this));
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL DataTable::addModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ m_xModifyEventForwarder->addModifyListener(aListener);
+}
+
+void SAL_CALL
+DataTable::removeModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ m_xModifyEventForwarder->removeModifyListener(aListener);
+}
+
+// ____ XModifyListener ____
+void SAL_CALL DataTable::modified(const lang::EventObject& aEvent)
+{
+ m_xModifyEventForwarder->modified(aEvent);
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL DataTable::disposing(const lang::EventObject& /* Source */)
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void DataTable::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified(lang::EventObject(static_cast<uno::XWeak*>(this)));
+}
+
+// ____ OPropertySet ____
+void DataTable::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticDataTableDefaults();
+ auto aFound = rStaticDefaults.find(nHandle);
+ if (aFound == rStaticDefaults.end())
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper& SAL_CALL DataTable::getInfoHelper()
+{
+ return StaticDataTableInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference<beans::XPropertySetInfo> SAL_CALL DataTable::getPropertySetInfo()
+{
+ static uno::Reference<beans::XPropertySetInfo> xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataTableInfoHelper()));
+ return xPropertySetInfo;
+}
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL DataTable::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.DataTable";
+}
+
+sal_Bool SAL_CALL DataTable::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL DataTable::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.DataTable", "com.sun.star.beans.PropertySet",
+ "com.sun.star.drawing.FillProperties", "com.sun.star.drawing.LineProperties",
+ "com.sun.star.style.CharacterProperties" };
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(DataTable, DataTable_Base, ::property::OPropertySet)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(DataTable, DataTable_Base, ::property::OPropertySet)
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_comp_chart2_DataTable_get_implementation(
+ css::uno::XComponentContext* /*pComponentContext*/, uno::Sequence<uno::Any> const& /*rAny*/)
+{
+ return cppu::acquire(new ::chart::DataTable);
+}
+
+/* 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 0000000000..db7be686b0
--- /dev/null
+++ b/chart2/source/model/main/Diagram.cxx
@@ -0,0 +1,2288 @@
+/* -*- 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 <AxisHelper.hxx>
+#include <BaseGFXHelper.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartType.hxx>
+#include <DataSeriesHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.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 <Axis.hxx>
+#include <DataTable.hxx>
+#include <servicenames_charttypes.hxx>
+#include <defines.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <editeng/unoprnms.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/math.hxx>
+#include <tools/helpers.hxx>
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans::PropertyAttribute;
+using namespace ::chart::SceneProperties;
+
+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( "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< 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 > xContext ) :
+ m_xContext(std::move( 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(
+ PROP_SCENE_CAMERA_GEOMETRY, uno::Any(
+ ThreeDHelper::getDefaultCameraGeometry()));
+}
+
+Diagram::Diagram( const Diagram & rOther ) :
+ impl::Diagram_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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 (rOther.m_xDataTable)
+ m_xDataTable = new DataTable(*rOther.m_xDataTable);
+
+ 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;
+}
+
+rtl::Reference< ::chart::Legend > Diagram::getLegend2() const
+{
+ 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 );
+ Diagram::tTemplateWithServiceName aTemplateAndService = getTemplate( 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()
+{
+ setPropertyToDefault( "D3DSceneDistance");
+ setPropertyToDefault( "D3DSceneFocalLength");
+ setDefaultRotation();
+ setDefaultIllumination();
+}
+
+void SAL_CALL Diagram::setDefaultRotation()
+{
+ bool bPieOrDonut( isPieOrDonutChart() );
+ setDefaultRotation( bPieOrDonut );
+}
+
+static ::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( Diagram& rDiagram )
+{
+ ::basegfx::B3DHomMatrix aCompleteRotation;
+ double fXAngleRad=0.0;
+ double fYAngleRad=0.0;
+ double fZAngleRad=0.0;
+ rDiagram.getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
+ return aCompleteRotation;
+}
+static void lcl_RotateLightSource( Diagram& rDiagram
+ , int nLightSourceDirectionProp
+ , int nLightSourceOnProp
+ , const ::basegfx::B3DHomMatrix& rRotationMatrix )
+{
+ bool bLightOn = false;
+ if( !(rDiagram.getFastPropertyValue( nLightSourceOnProp ) >>= bLightOn) )
+ return;
+
+ if( bLightOn )
+ {
+ drawing::Direction3D aLight;
+ if( rDiagram.getFastPropertyValue( nLightSourceDirectionProp ) >>= aLight )
+ {
+ ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) );
+ aLightVector = rRotationMatrix*aLightVector;
+
+ rDiagram.setFastPropertyValue( nLightSourceDirectionProp
+ , uno::Any( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) );
+ }
+ }
+}
+
+static void lcl_setLightsForScheme( Diagram& rDiagram, const ThreeDLookScheme& rScheme )
+{
+ if( rScheme == ThreeDLookScheme::ThreeDLookScheme_Unknown)
+ return;
+
+ // "D3DSceneLightOn2" / UNO_NAME_3D_SCENE_LIGHTON_2
+ rDiagram.setFastPropertyValue( PROP_SCENE_LIGHT_ON_2, uno::Any( true ) );
+
+ rtl::Reference< ChartType > xChartType( rDiagram.getChartTypeByIndex( 0 ) );
+ uno::Any aADirection( rScheme == ThreeDLookScheme::ThreeDLookScheme_Simple
+ ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType)
+ : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) );
+
+ // "D3DSceneLightDirection2" / UNO_NAME_3D_SCENE_LIGHTDIRECTION_2
+ rDiagram.setFastPropertyValue( PROP_SCENE_LIGHT_DIRECTION_2, aADirection );
+ //rotate light direction when right angled axes are off but supported
+ {
+ bool bRightAngledAxes = false;
+ rDiagram.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes; // "RightAngledAxes"
+ if(!bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) )
+ {
+ ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( rDiagram ) );
+ BaseGFXHelper::ReduceToRotationMatrix( aRotation );
+ // "D3DSceneLightDirection2", "D3DSceneLightOn2"
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_2, PROP_SCENE_LIGHT_ON_2, aRotation );
+ }
+ }
+ }
+
+ sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor(
+ rScheme == ThreeDLookScheme::ThreeDLookScheme_Simple, xChartType);
+ // "D3DSceneLightColor2" / UNO_NAME_3D_SCENE_LIGHTCOLOR_2
+ rDiagram.setFastPropertyValue( PROP_SCENE_LIGHT_COLOR_2, uno::Any( nColor ) );
+
+ sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor(
+ rScheme == ThreeDLookScheme::ThreeDLookScheme_Simple, xChartType);
+ // "D3DSceneAmbientColor" / UNO_NAME_3D_SCENE_AMBIENTCOLOR
+ rDiagram.setFastPropertyValue( PROP_SCENE_AMBIENT_COLOR, uno::Any( nAmbientColor ) );
+}
+
+void SAL_CALL Diagram::setDefaultIllumination()
+{
+ drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
+ try
+ {
+ // "D3DSceneShadeMode"
+ getFastPropertyValue( PROP_SCENE_SHADE_MODE )>>= aShadeMode;
+ // "D3DSceneLightOn1" / UNO_NAME_3D_SCENE_LIGHTON_1
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_1, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_3, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_4, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_5, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_6, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_7, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_8, uno::Any( false ) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ ThreeDLookScheme aScheme = (aShadeMode == drawing::ShadeMode_FLAT)
+ ? ThreeDLookScheme::ThreeDLookScheme_Simple
+ : ThreeDLookScheme::ThreeDLookScheme_Realistic;
+ lcl_setLightsForScheme( *this, aScheme );
+}
+
+// ____ 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 );
+}
+
+Diagram::tCoordinateSystemContainerType Diagram::getBaseCoordinateSystems() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return 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_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ //special treatment for some 3D properties
+ if( nHandle == PROP_DIAGRAM_PERSPECTIVE )
+ {
+ sal_Int32 fPerspective = 20;
+ if( rValue >>=fPerspective )
+ setCameraDistance( 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;
+ getRotation( nHorizontal, nVertical );
+ if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL )
+ nHorizontal = nNewAngleDegree;
+ else
+ nVertical = nNewAngleDegree;
+ setRotation( nHorizontal, nVertical );
+ }
+ }
+ else
+ ::property::OPropertySet::setFastPropertyValue_NoBroadcast( 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(
+ const_cast< Diagram* >( this )->getCameraDistance() ) );
+ rValue <<= nPerspective;
+ }
+ else if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL
+ || nHandle == PROP_DIAGRAM_ROTATION_VERTICAL )
+ {
+ sal_Int32 nHorizontal, nVertical;
+ const_cast< Diagram* >( this )->getRotation( 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 );
+}
+
+uno::Reference<chart2::XDataTable> SAL_CALL Diagram::getDataTable()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xDataTable;
+}
+
+rtl::Reference<::chart::DataTable> Diagram::getDataTableRef() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xDataTable;
+}
+
+void SAL_CALL Diagram::setDataTable(const uno::Reference<chart2::XDataTable>& xDataTable)
+{
+ auto* pDataTable = dynamic_cast<DataTable*>(xDataTable.get());
+ assert(!xDataTable || pDataTable);
+ setDataTable(rtl::Reference<DataTable>(pDataTable));
+}
+
+void Diagram::setDataTable(const rtl::Reference<DataTable>& xNewDataTable)
+{
+ rtl::Reference<DataTable> xOldDataTable;
+ {
+ MutexGuard aGuard(m_aMutex);
+ if (m_xDataTable == xNewDataTable)
+ return;
+ xOldDataTable = m_xDataTable;
+ m_xDataTable = xNewDataTable;
+ }
+ if (xOldDataTable.is())
+ ModifyListenerHelper::removeListener(xOldDataTable, m_xModifyEventForwarder);
+ if (xNewDataTable.is())
+ ModifyListenerHelper::addListener(xNewDataTable, m_xModifyEventForwarder);
+ fireModifyEvent();
+}
+
+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" };
+}
+
+DiagramPositioningMode Diagram::getDiagramPositioningMode()
+{
+ DiagramPositioningMode eMode = DiagramPositioningMode::Auto;
+ chart2::RelativePosition aRelPos;
+ chart2::RelativeSize aRelSize;
+ if( (getFastPropertyValue(PROP_DIAGRAM_REL_POS) >>= aRelPos ) &&
+ (getFastPropertyValue(PROP_DIAGRAM_REL_SIZE) >>= aRelSize ) )
+ {
+ bool bPosSizeExcludeAxes=false;
+ getFastPropertyValue(PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS) >>= bPosSizeExcludeAxes;
+ if( bPosSizeExcludeAxes )
+ eMode = DiagramPositioningMode::Excluding;
+ else
+ eMode = DiagramPositioningMode::Including;
+ }
+ return eMode;
+}
+
+
+sal_Int32 Diagram::getCorrectedMissingValueTreatment(
+ const rtl::Reference< ChartType >& xChartType )
+{
+ sal_Int32 nResult = css::chart::MissingValueTreatment::LEAVE_GAP;
+ const uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments(
+ ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
+
+ if( getFastPropertyValue( PROP_DIAGRAM_MISSING_VALUE_TREATMENT ) >>= nResult )
+ {
+ //ensure that the set value is supported by this charttype
+ for( sal_Int32 n : aAvailableMissingValueTreatments )
+ if( n == nResult )
+ return nResult; //ok
+ }
+
+ //otherwise use the first supported one
+ if( aAvailableMissingValueTreatments.hasElements() )
+ {
+ nResult = aAvailableMissingValueTreatments[0];
+ return nResult;
+ }
+
+ return nResult;
+}
+
+void Diagram::setGeometry3D( sal_Int32 nNewGeometry )
+{
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ getDataSeries();
+
+ for (auto const& series : aSeriesVec)
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
+ series, "Geometry3D", uno::Any( nNewGeometry ));
+ }
+}
+
+sal_Int32 Diagram::getGeometry3D( bool& rbFound, bool& rbAmbiguous )
+{
+ sal_Int32 nCommonGeom( css::chart2::DataPointGeometry3D::CUBOID );
+ rbFound = false;
+ rbAmbiguous = false;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec = getDataSeries();
+
+ if( aSeriesVec.empty())
+ rbAmbiguous = true;
+
+ for (auto const& series : aSeriesVec)
+ {
+ try
+ {
+ sal_Int32 nGeom = 0;
+ if( series->getPropertyValue( "Geometry3D") >>= nGeom )
+ {
+ if( ! rbFound )
+ {
+ // first series
+ nCommonGeom = nGeom;
+ rbFound = true;
+ }
+ // further series: compare for uniqueness
+ else if( nCommonGeom != nGeom )
+ {
+ rbAmbiguous = true;
+ break;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return nCommonGeom;
+}
+
+bool Diagram::isPieOrDonutChart()
+{
+ rtl::Reference< ChartType > xChartType = getChartTypeByIndex( 0 );
+
+ if( xChartType .is() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ return true;
+ }
+ return false;
+}
+
+bool Diagram::isSupportingFloorAndWall()
+{
+ //pies and donuts currently do not support this because of wrong files from older versions
+ //todo: allow this in future again, if fileversion is available for OLE objects (metastream)
+ //thus the wrong bottom can be removed on import
+
+ const std::vector< rtl::Reference< ChartType > > aTypes = getChartTypes();
+ for( rtl::Reference< ChartType > const & xType : aTypes )
+ {
+ OUString sChartType = xType->getChartType();
+ if( sChartType.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ if( sChartType.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( sChartType.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ return false;
+ }
+ return true;
+}
+
+ /**
+ * This method implements the logic of checking if a series can be moved
+ * forward/backward. Depending on the "bDoMove" parameter the series will
+ * be moved (bDoMove = true) or the function just will test if the
+ * series can be moved without doing the move (bDoMove = false).
+ *
+ * @param xDiagram
+ * Reference to the diagram that contains the series.
+ *
+ * @param xGivenDataSeries
+ * Reference to the series that should moved or tested for moving.
+ *
+ * @param bForward
+ * Direction in which the series should be moved or tested for moving.
+ *
+ * @param bDoMove
+ * Should this function really move the series (true) or just test if it is
+ * possible (false).
+ *
+ *
+ * @returns
+ * in case of bDoMove == true
+ * - True : if the move was done
+ * - False : the move failed
+ * in case of bDoMove == false
+ * - True : the series can be moved
+ * - False : the series can not be moved
+ *
+ */
+static bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
+ Diagram& rDiagram,
+ const rtl::Reference< DataSeries >& xGivenDataSeries,
+ bool bForward,
+ bool bDoMove )
+{
+ bool bMovedOrMoveAllowed = false;
+
+ try
+ {
+ if( !xGivenDataSeries.is() )
+ return false;
+
+ //find position of series.
+ bool bFound = false;
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysList( rDiagram.getBaseCoordinateSystems() );
+
+ for( std::size_t nCS = 0; !bFound && nCS < aCooSysList.size(); ++nCS )
+ {
+ const rtl::Reference< BaseCoordinateSystem > & xCooSys( aCooSysList[nCS] );
+
+ //iterate through all chart types in the current coordinate system
+ std::vector< rtl::Reference< ChartType > > aChartTypeList( xCooSys->getChartTypes2() );
+ rtl::Reference< ChartType > xFormerChartType;
+
+ for( std::size_t nT = 0; !bFound && nT < aChartTypeList.size(); ++nT )
+ {
+ rtl::Reference< ChartType > xCurrentChartType( aChartTypeList[nT] );
+
+ //iterate through all series in this chart type
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesList = xCurrentChartType->getDataSeries2();
+
+ for( std::size_t nS = 0; !bFound && nS < aSeriesList.size(); ++nS )
+ {
+
+ // We found the series we are interested in!
+ if( xGivenDataSeries==aSeriesList[nS] )
+ {
+ std::size_t nOldSeriesIndex = nS;
+ bFound = true;
+
+ try
+ {
+ sal_Int32 nNewSeriesIndex = nS;
+
+ // tdf#34517 Bringing forward means increasing, backwards means decreasing series position
+ if( !bForward )
+ nNewSeriesIndex--;
+ else
+ nNewSeriesIndex++;
+
+ if( nNewSeriesIndex >= 0 && o3tl::make_unsigned(nNewSeriesIndex) < aSeriesList.size() )
+ {
+ //move series in the same charttype
+ bMovedOrMoveAllowed = true;
+ if( bDoMove )
+ {
+ aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ];
+ aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries;
+ xCurrentChartType->setDataSeries( aSeriesList );
+ }
+ }
+ else if( nNewSeriesIndex<0 )
+ {
+ //exchange series with former charttype
+ if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) )
+ {
+ bMovedOrMoveAllowed = true;
+ if( bDoMove )
+ {
+ std::vector< rtl::Reference< DataSeries > > aOtherSeriesList = xFormerChartType->getDataSeries2();
+ sal_Int32 nOtherSeriesIndex = aOtherSeriesList.size()-1;
+ if( nOtherSeriesIndex >= 0 && o3tl::make_unsigned(nOtherSeriesIndex) < aOtherSeriesList.size() )
+ {
+ rtl::Reference< DataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
+ aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
+ xFormerChartType->setDataSeries(aOtherSeriesList);
+
+ aSeriesList[nOldSeriesIndex]=xExchangeSeries;
+ xCurrentChartType->setDataSeries(aSeriesList);
+ }
+ }
+ }
+ }
+ else if( nT+1 < aChartTypeList.size() )
+ {
+ //exchange series with next charttype
+ rtl::Reference< ChartType > xOtherChartType( aChartTypeList[nT+1] );
+ if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) )
+ {
+ bMovedOrMoveAllowed = true;
+ if( bDoMove )
+ {
+ std::vector< rtl::Reference< DataSeries > > aOtherSeriesList = xOtherChartType->getDataSeries2();
+ if( !aOtherSeriesList.empty() )
+ {
+ rtl::Reference< DataSeries > xExchangeSeries( aOtherSeriesList[0] );
+ aOtherSeriesList[0] = xGivenDataSeries;
+ xOtherChartType->setDataSeries(aOtherSeriesList);
+
+ aSeriesList[nOldSeriesIndex]=xExchangeSeries;
+ xCurrentChartType->setDataSeries(aSeriesList);
+ }
+ }
+ }
+ }
+ }
+ catch( const util::CloseVetoException& )
+ {
+ }
+ catch( const uno::RuntimeException& )
+ {
+ }
+ }
+ }
+ xFormerChartType = xCurrentChartType;
+ }
+ }
+ }
+ catch( const util::CloseVetoException& )
+ {
+ }
+ catch( const uno::RuntimeException& )
+ {
+ }
+ return bMovedOrMoveAllowed;
+}
+
+bool Diagram::isSeriesMoveable(
+ const rtl::Reference< DataSeries >& xGivenDataSeries,
+ bool bForward )
+{
+ const bool bDoMove = false;
+
+ bool bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed(
+ *this, xGivenDataSeries, bForward, bDoMove );
+
+ return bIsMoveable;
+}
+
+bool Diagram::moveSeries( const rtl::Reference< DataSeries >& xGivenDataSeries, bool bForward )
+{
+ const bool bDoMove = true;
+
+ bool bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed(
+ *this, xGivenDataSeries, bForward, bDoMove );
+
+ return bMoved;
+}
+
+std::vector< rtl::Reference< ChartType > > Diagram::getChartTypes()
+{
+ std::vector< rtl::Reference< ChartType > > aResult;
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeSeq( coords->getChartTypes2());
+ aResult.insert( aResult.end(), aChartTypeSeq.begin(), aChartTypeSeq.end() );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+rtl::Reference< ChartType > Diagram::getChartTypeByIndex( sal_Int32 nIndex )
+{
+ rtl::Reference< ChartType > xChartType;
+
+ //iterate through all coordinate systems
+ sal_Int32 nTypesSoFar = 0;
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeList( coords->getChartTypes2() );
+ if( nIndex >= 0 && o3tl::make_unsigned(nIndex) < nTypesSoFar + aChartTypeList.size() )
+ {
+ xChartType = aChartTypeList[nIndex - nTypesSoFar];
+ break;
+ }
+ nTypesSoFar += aChartTypeList.size();
+ }
+
+ return xChartType;
+}
+
+bool Diagram::isSupportingDateAxis()
+{
+ return ::chart::ChartTypeHelper::isSupportingDateAxis( getChartTypeByIndex( 0 ), 0 );
+}
+
+static std::vector< rtl::Reference< Axis > > lcl_getAxisHoldingCategoriesFromDiagram(
+ Diagram& rDiagram )
+{
+ std::vector< rtl::Reference< Axis > > aRet;
+
+ // return first x-axis as fall-back
+ rtl::Reference< Axis > xFallBack;
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : rDiagram.getBaseCoordinateSystems() )
+ {
+ OSL_ASSERT( xCooSys.is());
+ for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
+ {
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
+ for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( nN,nI );
+ OSL_ASSERT( xAxis.is());
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( aScaleData.Categories.is() || (aScaleData.AxisType == chart2::AxisType::CATEGORY) )
+ {
+ aRet.push_back(xAxis);
+ }
+ if( (nN == 0) && !xFallBack.is())
+ xFallBack = xAxis;
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+
+ if( aRet.empty() )
+ aRet.push_back(xFallBack);
+
+ return aRet;
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > Diagram::getCategories()
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xResult;
+
+ try
+ {
+ std::vector< rtl::Reference< Axis > > aCatAxes(
+ lcl_getAxisHoldingCategoriesFromDiagram( *this ));
+ //search for first categories
+ if (aCatAxes.empty())
+ return xResult;
+
+ rtl::Reference< Axis > xCatAxis(aCatAxes[0]);
+ if( !xCatAxis.is())
+ return xResult;
+
+ chart2::ScaleData aScaleData( xCatAxis->getScaleData());
+ if( !aScaleData.Categories.is() )
+ return xResult;
+
+ xResult = aScaleData.Categories;
+ uno::Reference<beans::XPropertySet> xProp(xResult->getValues(), uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ xProp->setPropertyValue( "Role", uno::Any( OUString("categories") ) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+void Diagram::setCategories(
+ const uno::Reference< chart2::data::XLabeledDataSequence >& xCategories,
+ bool bSetAxisType /* = false */,
+ bool bCategoryAxis /* = true */ )
+{
+ std::vector< rtl::Reference< Axis > > aCatAxes(
+ lcl_getAxisHoldingCategoriesFromDiagram( *this ));
+
+ for (const rtl::Reference< Axis >& xCatAxis : aCatAxes)
+ {
+ if( xCatAxis.is())
+ {
+ chart2::ScaleData aScaleData( xCatAxis->getScaleData());
+ aScaleData.Categories = xCategories;
+ if( bSetAxisType )
+ {
+ if( bCategoryAxis )
+ aScaleData.AxisType = chart2::AxisType::CATEGORY;
+ else if( aScaleData.AxisType == chart2::AxisType::CATEGORY || aScaleData.AxisType == chart2::AxisType::DATE )
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ }
+ xCatAxis->setScaleData( aScaleData );
+ }
+ }
+}
+
+bool Diagram::isCategory()
+{
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
+ {
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
+ for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( nN,nI );
+ OSL_ASSERT( xAxis.is());
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( aScaleData.AxisType == chart2::AxisType::CATEGORY || aScaleData.AxisType == chart2::AxisType::DATE )
+ return true;
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return false;
+}
+
+std::vector< std::vector< rtl::Reference< DataSeries > > >
+Diagram::getDataSeriesGroups()
+{
+ std::vector< std::vector< rtl::Reference< DataSeries > > > aResult;
+
+ //iterate through all coordinate systems
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ for( rtl::Reference< ChartType > const & chartType : coords->getChartTypes2() )
+ {
+ aResult.push_back( chartType->getDataSeries2() );
+ }
+ }
+ return aResult;
+}
+
+std::vector< rtl::Reference< ::chart::DataSeries > >
+ Diagram::getDataSeries()
+{
+ std::vector< rtl::Reference< DataSeries > > aResult;
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ for( rtl::Reference< ChartType> const & chartType : coords->getChartTypes2() )
+ {
+ const std::vector< rtl::Reference< DataSeries > > aSeriesSeq( chartType->getDataSeries2() );
+ aResult.insert( aResult.end(), aSeriesSeq.begin(), aSeriesSeq.end() );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+rtl::Reference< ChartType > Diagram::getChartTypeOfSeries(
+ const rtl::Reference< DataSeries >& xGivenDataSeries )
+{
+ if( !xGivenDataSeries.is() )
+ return nullptr;
+
+ //iterate through the model to find the given xSeries
+ //the found parent indicates the charttype
+
+ //iterate through all coordinate systems
+
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeList( xCooSys->getChartTypes2() );
+ for( rtl::Reference< ChartType > const & xChartType : aChartTypeList )
+ {
+ //iterate through all series in this chart type
+ for( rtl::Reference< DataSeries > const & dataSeries : xChartType->getDataSeries2() )
+ {
+ if( xGivenDataSeries==dataSeries )
+ return xChartType;
+ }
+ }
+ }
+ return nullptr;
+}
+
+rtl::Reference< Axis > Diagram::getAttachedAxis(
+ const rtl::Reference< DataSeries >& xSeries )
+{
+ return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), this );
+}
+
+bool Diagram::attachSeriesToAxis( bool bAttachToMainAxis
+ , const rtl::Reference< DataSeries >& xDataSeries
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , bool bAdaptAxes )
+{
+ bool bChanged = false;
+
+ //set property at axis
+
+ sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1;
+ sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ rtl::Reference< Axis > xOldAxis = getAttachedAxis( xDataSeries );
+
+ if( nOldAxisIndex != nNewAxisIndex )
+ {
+ try
+ {
+ xDataSeries->setPropertyValue( "AttachedAxisIndex", uno::Any( nNewAxisIndex ) );
+ bChanged = true;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if( bChanged )
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 1, bAttachToMainAxis, this );
+ if(!xAxis.is()) //create an axis if necessary
+ xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, this, xContext );
+ if( bAdaptAxes )
+ {
+ AxisHelper::makeAxisVisible( xAxis );
+ AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, this );
+ }
+ }
+
+ return bChanged;
+}
+
+void Diagram::replaceCoordinateSystem(
+ const rtl::Reference< BaseCoordinateSystem > & xCooSysToReplace,
+ const rtl::Reference< BaseCoordinateSystem > & xReplacement )
+{
+ // update the coordinate-system container
+ try
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories = getCategories();
+
+ // move chart types of xCooSysToReplace to xReplacement
+ xReplacement->setChartTypes( xCooSysToReplace->getChartTypes());
+
+ removeCoordinateSystem( xCooSysToReplace );
+ addCoordinateSystem( xReplacement );
+
+ if( xCategories.is() )
+ setCategories( xCategories );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+sal_Int32 Diagram::getDimension()
+{
+ // -1: not yet set
+ sal_Int32 nResult = -1;
+
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ if(xCooSys.is())
+ {
+ nResult = xCooSys->getDimension();
+ break;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nResult;
+}
+
+void Diagram::setDimension( sal_Int32 nNewDimensionCount )
+{
+ if( getDimension() == nNewDimensionCount )
+ return;
+
+ try
+ {
+ bool rbFound = false;
+ bool rbAmbiguous = true;
+ StackMode eStackMode = getStackMode( rbFound, rbAmbiguous );
+ bool bIsSupportingOnlyDeepStackingFor3D=false;
+
+ //change all coordinate systems:
+ auto aCoordSystems = getBaseCoordinateSystems();
+ for( rtl::Reference<BaseCoordinateSystem> const & xOldCooSys : aCoordSystems )
+ {
+ rtl::Reference< BaseCoordinateSystem > xNewCooSys;
+
+ const std::vector< rtl::Reference< ChartType > > aChartTypeList( xOldCooSys->getChartTypes2() );
+ for( rtl::Reference< ChartType > const & xChartType : aChartTypeList )
+ {
+ bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType );
+ if(!xNewCooSys.is())
+ {
+ xNewCooSys = dynamic_cast<BaseCoordinateSystem*>(xChartType->createCoordinateSystem( nNewDimensionCount ).get());
+ assert(xNewCooSys);
+ break;
+ }
+ //@todo make sure that all following charttypes are also capable of the new dimension
+ //otherwise separate them in a different group
+ //BM: might be done in replaceCoordinateSystem()
+ }
+
+ // replace the old coordinate system at all places where it was used
+ replaceCoordinateSystem( xOldCooSys, xNewCooSys );
+ }
+
+ //correct stack mode if necessary
+ if( nNewDimensionCount==3 && eStackMode != StackMode::ZStacked && bIsSupportingOnlyDeepStackingFor3D )
+ setStackMode( StackMode::ZStacked );
+ else if( nNewDimensionCount==2 && eStackMode == StackMode::ZStacked )
+ setStackMode( StackMode::NONE );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void Diagram::setStackMode( StackMode eStackMode )
+{
+ try
+ {
+ bool bValueFound = false;
+ bool bIsAmbiguous = false;
+ StackMode eOldStackMode = getStackMode( bValueFound, bIsAmbiguous );
+
+ if( eStackMode == eOldStackMode && !bIsAmbiguous )
+ return;
+
+ chart2::StackingDirection eNewDirection = chart2::StackingDirection_NO_STACKING;
+ if( eStackMode == StackMode::YStacked || eStackMode == StackMode::YStackedPercent )
+ eNewDirection = chart2::StackingDirection_Y_STACKING;
+ else if( eStackMode == StackMode::ZStacked )
+ eNewDirection = chart2::StackingDirection_Z_STACKING;
+
+ uno::Any aNewDirection( eNewDirection );
+
+ bool bPercent = false;
+ if( eStackMode == StackMode::YStackedPercent )
+ bPercent = true;
+
+ //iterate through all coordinate systems
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ //set correct percent stacking
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1);
+ for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1,nI );
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( (aScaleData.AxisType==chart2::AxisType::PERCENT) != bPercent )
+ {
+ if( bPercent )
+ aScaleData.AxisType = chart2::AxisType::PERCENT;
+ else
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ xAxis->setScaleData( aScaleData );
+ }
+ }
+ }
+ //iterate through all chart types in the current coordinate system
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeList( xCooSys->getChartTypes2() );
+ if (aChartTypeList.empty())
+ continue;
+
+ rtl::Reference< ChartType > xChartType( aChartTypeList[0] );
+
+ //iterate through all series in this chart type
+ for( rtl::Reference< DataSeries > const & dataSeries : xChartType->getDataSeries2() )
+ {
+ dataSeries->setPropertyValue( "StackingDirection", aNewDirection );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+StackMode Diagram::getStackMode( bool& rbFound, bool& rbAmbiguous )
+{
+ rbFound=false;
+ rbAmbiguous=false;
+
+ StackMode eGlobalStackMode = StackMode::NONE;
+
+ //iterate through all coordinate systems
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ std::vector< rtl::Reference< ChartType > > aChartTypeList( xCooSys->getChartTypes2() );
+ for( std::size_t nT = 0; nT < aChartTypeList.size(); ++nT )
+ {
+ rtl::Reference< ChartType > xChartType( aChartTypeList[nT] );
+
+ StackMode eLocalStackMode = DiagramHelper::getStackModeFromChartType(
+ xChartType, rbFound, rbAmbiguous, xCooSys );
+
+ if( rbFound && eLocalStackMode != eGlobalStackMode && nT>0 )
+ {
+ rbAmbiguous = true;
+ return eGlobalStackMode;
+ }
+
+ eGlobalStackMode = eLocalStackMode;
+ }
+ }
+
+ return eGlobalStackMode;
+}
+
+void Diagram::setVertical( bool bVertical /* = true */ )
+{
+ try
+ {
+ uno::Any aValue;
+ aValue <<= bVertical;
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ bool bChanged = false;
+ bool bOldSwap = false;
+ if( !(xCooSys->getPropertyValue("SwapXAndYAxis") >>= bOldSwap)
+ || bVertical != bOldSwap )
+ bChanged = true;
+
+ if( bChanged )
+ xCooSys->setPropertyValue("SwapXAndYAxis", aValue);
+
+ const sal_Int32 nDimensionCount = xCooSys->getDimension();
+ sal_Int32 nDimIndex = 0;
+ for (nDimIndex=0; nDimIndex < nDimensionCount; ++nDimIndex)
+ {
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
+ for (sal_Int32 nI = 0; nI <= nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimIndex,nI);
+ if (!xAxis.is())
+ continue;
+
+ //adapt title rotation only when axis swapping has changed
+ if (!bChanged)
+ continue;
+
+ Reference< beans::XPropertySet > xTitleProps( xAxis->getTitleObject(), uno::UNO_QUERY );
+ if (!xTitleProps.is())
+ continue;
+
+ double fAngleDegree = 0.0;
+ xTitleProps->getPropertyValue("TextRotation") >>= fAngleDegree;
+ if (fAngleDegree != 0.0 &&
+ !rtl::math::approxEqual(fAngleDegree, 90.0))
+ continue;
+
+ double fNewAngleDegree = 0.0;
+ if( !bVertical && nDimIndex == 1 )
+ fNewAngleDegree = 90.0;
+ else if( bVertical && nDimIndex == 0 )
+ fNewAngleDegree = 90.0;
+
+ xTitleProps->setPropertyValue("TextRotation", uno::Any(fNewAngleDegree));
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+bool Diagram::getVertical( bool& rbFound, bool& rbAmbiguous )
+{
+ bool bValue = false;
+ rbFound = false;
+ rbAmbiguous = false;
+
+ for (rtl::Reference<BaseCoordinateSystem> const & coords : getBaseCoordinateSystems())
+ {
+ bool bCurrent = false;
+ if (coords->getPropertyValue("SwapXAndYAxis") >>= bCurrent)
+ {
+ if (!rbFound)
+ {
+ bValue = bCurrent;
+ rbFound = true;
+ }
+ else if (bCurrent != bValue)
+ {
+ // ambiguous -> choose always first found
+ rbAmbiguous = true;
+ }
+ }
+ }
+ return bValue;
+}
+
+Diagram::tTemplateWithServiceName
+ Diagram::getTemplate(
+ const rtl::Reference< ::chart::ChartTypeManager > & xChartTypeManager )
+{
+ tTemplateWithServiceName aResult;
+
+ if( !xChartTypeManager )
+ return aResult;
+
+ Sequence< OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames());
+ const sal_Int32 nLength = aServiceNames.getLength();
+
+ bool bTemplateFound = false;
+
+ for( sal_Int32 i = 0; ! bTemplateFound && i < nLength; ++i )
+ {
+ try
+ {
+ rtl::Reference< ::chart::ChartTypeTemplate > xTempl =
+ xChartTypeManager->createTemplate( aServiceNames[ i ] );
+
+ if (xTempl.is() && xTempl->matchesTemplate2(this, true))
+ {
+ aResult.xChartTypeTemplate = xTempl;
+ aResult.sServiceName = aServiceNames[ i ];
+ bTemplateFound = true;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+std::vector< rtl::Reference< RegressionCurveModel > >
+ Diagram::getAllRegressionCurvesNotMeanValueLine()
+{
+ std::vector< rtl::Reference< RegressionCurveModel > > aResult;
+ std::vector< rtl::Reference< DataSeries > > aSeries( getDataSeries());
+ for (auto const& elem : aSeries)
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : elem->getRegressionCurves2() )
+ {
+ if( ! RegressionCurveHelper::isMeanValueLine( curve ))
+ aResult.push_back( curve );
+ }
+ }
+
+ return aResult;
+}
+
+double Diagram::getCameraDistance()
+{
+ double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+
+ try
+ {
+ drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
+ getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY ) >>= aCG;
+ ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
+ fCameraDistance = aVRP.getLength();
+
+ ThreeDHelper::ensureCameraDistanceRange( fCameraDistance );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return fCameraDistance;
+}
+
+void Diagram::setCameraDistance(double fCameraDistance )
+{
+ try
+ {
+ if( fCameraDistance <= 0 )
+ fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+
+ drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
+ getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY ) >>= aCG;
+ ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
+ if( ::basegfx::fTools::equalZero( aVRP.getLength() ) )
+ aVRP = ::basegfx::B3DVector(0,0,1);
+ aVRP.setLength(fCameraDistance);
+ aCG.vrp = BaseGFXHelper::B3DVectorToPosition3D( aVRP );
+
+ setFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY, uno::Any( aCG ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+static bool lcl_isRightAngledAxesSetAndSupported( Diagram& rDiagram )
+{
+ bool bRightAngledAxes = false;
+ rDiagram.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes; // "RightAngledAxes"
+ if(bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ rDiagram.getChartTypeByIndex( 0 ) ) )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Diagram::getRotation( sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree )
+{
+ double fXAngle, fYAngle, fZAngle;
+ getRotationAngle( fXAngle, fYAngle, fZAngle );
+
+ if( !lcl_isRightAngledAxesSetAndSupported( *this ) )
+ {
+ ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
+ rnHorizontalAngleDegree, rnVerticalAngleDegree, fXAngle, fYAngle, fZAngle);
+ rnVerticalAngleDegree*=-1;
+ }
+ else
+ {
+ rnHorizontalAngleDegree = basegfx::fround(basegfx::rad2deg(fXAngle));
+ rnVerticalAngleDegree = basegfx::fround(-1.0 * basegfx::rad2deg(fYAngle));
+ // nZRotation = basegfx::fround(-1.0 * basegfx::rad2deg(fZAngle));
+ }
+
+ rnHorizontalAngleDegree = NormAngle180(rnHorizontalAngleDegree);
+ rnVerticalAngleDegree = NormAngle180(rnVerticalAngleDegree);
+}
+
+void Diagram::setRotation( sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree )
+{
+ //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false
+ double fXAngle = basegfx::deg2rad(nHorizontalAngleDegree);
+ double fYAngle = basegfx::deg2rad(-1 * nVerticalYAngleDegree);
+ double fZAngle = 0.0;
+
+ if( !lcl_isRightAngledAxesSetAndSupported( *this ) )
+ ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
+ nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle );
+
+ setRotationAngle( fXAngle, fYAngle, fZAngle );
+}
+
+static ::basegfx::B3DHomMatrix lcl_getCameraMatrix( Diagram& rDiagram )
+{
+ drawing::HomogenMatrix aCameraMatrix;
+
+ drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
+ rDiagram.getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY ) >>= aCG; // "D3DCameraGeometry"
+
+ ::basegfx::B3DVector aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG.vpn ) );
+ ::basegfx::B3DVector aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG.vup ) );
+
+ //normalize vectors:
+ aVPN.normalize();
+ aVUP.normalize();
+
+ ::basegfx::B3DVector aCross = ::basegfx::cross( aVUP, aVPN );
+
+ //first line is VUP x VPN
+ aCameraMatrix.Line1.Column1 = aCross[0];
+ aCameraMatrix.Line1.Column2 = aCross[1];
+ aCameraMatrix.Line1.Column3 = aCross[2];
+ aCameraMatrix.Line1.Column4 = 0.0;
+
+ //second line is VUP
+ aCameraMatrix.Line2.Column1 = aVUP[0];
+ aCameraMatrix.Line2.Column2 = aVUP[1];
+ aCameraMatrix.Line2.Column3 = aVUP[2];
+ aCameraMatrix.Line2.Column4 = 0.0;
+
+ //third line is VPN
+ aCameraMatrix.Line3.Column1 = aVPN[0];
+ aCameraMatrix.Line3.Column2 = aVPN[1];
+ aCameraMatrix.Line3.Column3 = aVPN[2];
+ aCameraMatrix.Line3.Column4 = 0.0;
+
+ //fourth line is 0 0 0 1
+ aCameraMatrix.Line4.Column1 = 0.0;
+ aCameraMatrix.Line4.Column2 = 0.0;
+ aCameraMatrix.Line4.Column3 = 0.0;
+ aCameraMatrix.Line4.Column4 = 1.0;
+
+ return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix );
+}
+
+static double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad )
+{
+ //valid range: ]-Pi,Pi]
+ while( fAngleRad<=-M_PI )
+ fAngleRad+=(2*M_PI);
+ while( fAngleRad>M_PI )
+ fAngleRad-=(2*M_PI);
+ return fAngleRad;
+}
+
+void Diagram::getRotationAngle( double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad )
+{
+ //takes the camera and the transformation matrix into account
+
+ rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0;
+
+ //get camera rotation
+ ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( *this ) );
+ BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix );
+
+ //get scene rotation
+ ::basegfx::B3DHomMatrix aSceneRotation;
+ {
+ drawing::HomogenMatrix aHomMatrix;
+ // "D3DTransformMatrix"
+ if( getFastPropertyValue( PROP_SCENE_TRANSF_MATRIX ) >>= aHomMatrix )
+ {
+ aSceneRotation = BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix );
+ BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
+ }
+ }
+
+ ::basegfx::B3DHomMatrix aResultRotation = aFixCameraRotationMatrix * aSceneRotation;
+ ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation ) );
+
+ rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getX());
+ rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getY());
+ rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getZ());
+
+ if(rfZAngleRad<-M_PI_2 || rfZAngleRad>M_PI_2)
+ {
+ rfZAngleRad-=M_PI;
+ rfXAngleRad-=M_PI;
+ rfYAngleRad=(M_PI-rfYAngleRad);
+
+ rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad);
+ rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad);
+ rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad);
+ }
+}
+
+static ::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( Diagram& rDiagram )
+{
+ ::basegfx::B3DHomMatrix aInverseRotation;
+ double fXAngleRad=0.0;
+ double fYAngleRad=0.0;
+ double fZAngleRad=0.0;
+ rDiagram.getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ aInverseRotation.rotate( 0.0, 0.0, -fZAngleRad );
+ aInverseRotation.rotate( 0.0, -fYAngleRad, 0.0 );
+ aInverseRotation.rotate( -fXAngleRad, 0.0, 0.0 );
+ return aInverseRotation;
+}
+
+static void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRotation, Diagram& rDiagram )
+{
+ ::basegfx::B3DHomMatrix aLightRotation( rLightRotation );
+ BaseGFXHelper::ReduceToRotationMatrix( aLightRotation );
+
+ // "D3DSceneLightDirection1","D3DSceneLightOn1",
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_1, PROP_SCENE_LIGHT_ON_1, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_2, PROP_SCENE_LIGHT_ON_2, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_3, PROP_SCENE_LIGHT_ON_3, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_4, PROP_SCENE_LIGHT_ON_4, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_5, PROP_SCENE_LIGHT_ON_5, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_6, PROP_SCENE_LIGHT_ON_6, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_7, PROP_SCENE_LIGHT_ON_7, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_8, PROP_SCENE_LIGHT_ON_8, aLightRotation );
+}
+
+void Diagram::setRotationAngle(
+ double fXAngleRad, double fYAngleRad, double fZAngleRad )
+{
+ //the rotation of the camera is not touched but taken into account
+ //the rotation difference is applied to the transformation matrix
+
+ //the light sources will be adapted also
+
+ try
+ {
+ //remind old rotation for adaptation of light directions
+ ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( *this ) );
+
+ ::basegfx::B3DHomMatrix aInverseCameraRotation;
+ {
+ ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix(
+ lcl_getCameraMatrix( *this ) ) );
+ aInverseCameraRotation.rotate( 0.0, 0.0, -aR.getZ() );
+ aInverseCameraRotation.rotate( 0.0, -aR.getY(), 0.0 );
+ aInverseCameraRotation.rotate( -aR.getX(), 0.0, 0.0 );
+ }
+
+ ::basegfx::B3DHomMatrix aCumulatedRotation;
+ aCumulatedRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
+
+ //calculate new scene matrix
+ ::basegfx::B3DHomMatrix aSceneRotation = aInverseCameraRotation*aCumulatedRotation;
+ BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
+
+ //set new rotation to transformation matrix ("D3DTransformMatrix")
+ setFastPropertyValue(
+ PROP_SCENE_TRANSF_MATRIX, uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
+
+ //rotate lights if RightAngledAxes are not set or not supported
+ bool bRightAngledAxes = false;
+ getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes;
+ if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes(
+ getChartTypeByIndex( 0 ) ) )
+ {
+ ::basegfx::B3DHomMatrix aNewRotation;
+ aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
+ lcl_rotateLights( aNewRotation*aInverseOldRotation, *this );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+static bool lcl_isEqual( const drawing::Direction3D& rA, const drawing::Direction3D& rB )
+{
+ return ::rtl::math::approxEqual(rA.DirectionX, rB.DirectionX)
+ && ::rtl::math::approxEqual(rA.DirectionY, rB.DirectionY)
+ && ::rtl::math::approxEqual(rA.DirectionZ, rB.DirectionZ);
+}
+static bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode
+ , sal_Int32 nRoundedEdges
+ , sal_Int32 nObjectLines
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ if(aShadeMode!=drawing::ShadeMode_FLAT)
+ return false;
+ if(nRoundedEdges!=0)
+ return false;
+ if(nObjectLines==0)
+ {
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ return ChartTypeHelper::noBordersForSimpleScheme( xChartType );
+ }
+ if(nObjectLines!=1)
+ return false;
+ return true;
+}
+static bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode
+ , sal_Int32 nRoundedEdges
+ , sal_Int32 nObjectLines )
+{
+ if(aShadeMode!=drawing::ShadeMode_SMOOTH)
+ return false;
+ if(nRoundedEdges!=5)
+ return false;
+ if(nObjectLines!=0)
+ return false;
+ return true;
+}
+static bool lcl_isLightScheme( Diagram& rDiagram, bool bRealistic )
+{
+ bool bIsOn = false;
+ // "D3DSceneLightOn2" / UNO_NAME_3D_SCENE_LIGHTON_2
+ rDiagram.getFastPropertyValue( PROP_SCENE_LIGHT_ON_2 ) >>= bIsOn;
+ if(!bIsOn)
+ return false;
+
+ rtl::Reference< ChartType > xChartType( rDiagram.getChartTypeByIndex( 0 ) );
+
+ sal_Int32 nColor = 0;
+ // "D3DSceneLightColor2" / UNO_NAME_3D_SCENE_LIGHTCOLOR_2
+ rDiagram.getFastPropertyValue( PROP_SCENE_LIGHT_COLOR_2 ) >>= nColor;
+ if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) )
+ return false;
+
+ sal_Int32 nAmbientColor = 0;
+ // "D3DSceneAmbientColor" / UNO_NAME_3D_SCENE_AMBIENTCOLOR
+ rDiagram.getFastPropertyValue( PROP_SCENE_AMBIENT_COLOR ) >>= nAmbientColor;
+ if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) )
+ return false;
+
+ drawing::Direction3D aDirection(0,0,0);
+ // "D3DSceneLightDirection2" / UNO_NAME_3D_SCENE_LIGHTDIRECTION_2
+ rDiagram.getFastPropertyValue( PROP_SCENE_LIGHT_DIRECTION_2 ) >>= aDirection;
+
+ drawing::Direction3D aDefaultDirection( bRealistic
+ ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType)
+ : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) );
+
+ //rotate default light direction when right angled axes are off but supported
+ {
+ bool bRightAngledAxes = false;
+ rDiagram.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes; // "RightAngledAxes"
+ if(!bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ rDiagram.getChartTypeByIndex( 0 ) ) )
+ {
+ ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( rDiagram ) );
+ BaseGFXHelper::ReduceToRotationMatrix( aRotation );
+ ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) );
+ aLightVector = aRotation*aLightVector;
+ aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector );
+ }
+ }
+ }
+
+ return lcl_isEqual( aDirection, aDefaultDirection );
+}
+static bool lcl_isRealisticLightScheme( Diagram& rDiagram )
+{
+ return lcl_isLightScheme( rDiagram, true /*bRealistic*/ );
+}
+static bool lcl_isSimpleLightScheme( Diagram& rDiagram )
+{
+ return lcl_isLightScheme( rDiagram, false /*bRealistic*/ );
+}
+
+ThreeDLookScheme Diagram::detectScheme()
+{
+ ThreeDLookScheme aScheme = ThreeDLookScheme::ThreeDLookScheme_Unknown;
+
+ sal_Int32 nRoundedEdges;
+ sal_Int32 nObjectLines;
+ ThreeDHelper::getRoundedEdgesAndObjectLines( this, nRoundedEdges, nObjectLines );
+
+ //get shade mode and light settings:
+ drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
+ try
+ {
+ getFastPropertyValue( PROP_SCENE_SHADE_MODE )>>= aShadeMode; // "D3DSceneShadeMode"
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, this ) )
+ {
+ if( lcl_isSimpleLightScheme(*this) )
+ aScheme = ThreeDLookScheme::ThreeDLookScheme_Simple;
+ }
+ else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) )
+ {
+ if( lcl_isRealisticLightScheme(*this) )
+ aScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+ }
+
+ return aScheme;
+}
+
+static void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode
+ , sal_Int32& rnRoundedEdges
+ , sal_Int32& rnObjectLines )
+{
+ rShadeMode = drawing::ShadeMode_SMOOTH;
+ rnRoundedEdges = 5;
+ rnObjectLines = 0;
+}
+
+static void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode
+ , sal_Int32& rnRoundedEdges
+ , sal_Int32& rnObjectLines
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ rShadeMode = drawing::ShadeMode_FLAT;
+ rnRoundedEdges = 0;
+
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1;
+}
+void Diagram::setScheme( ThreeDLookScheme aScheme )
+{
+ if( aScheme == ThreeDLookScheme::ThreeDLookScheme_Unknown )
+ return;
+
+ drawing::ShadeMode aShadeMode;
+ sal_Int32 nRoundedEdges;
+ sal_Int32 nObjectLines;
+
+ if( aScheme == ThreeDLookScheme::ThreeDLookScheme_Simple )
+ lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,this);
+ else
+ lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines);
+
+ try
+ {
+ ThreeDHelper::setRoundedEdgesAndObjectLines( this, nRoundedEdges, nObjectLines );
+
+ drawing::ShadeMode aOldShadeMode;
+ if( ! (getFastPropertyValue( PROP_SCENE_SHADE_MODE)>>=aOldShadeMode) ||
+ aOldShadeMode != aShadeMode )
+ {
+ setFastPropertyValue( PROP_SCENE_SHADE_MODE, uno::Any( aShadeMode )); // "D3DSceneShadeMode"
+ }
+
+ lcl_setLightsForScheme( *this, aScheme );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+}
+
+void Diagram::setDefaultRotation( bool bPieOrDonut )
+{
+ drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) );
+ // "D3DCameraGeometry"
+ setFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY, uno::Any( aCameraGeo ));
+
+ ::basegfx::B3DHomMatrix aSceneRotation;
+ if( bPieOrDonut )
+ aSceneRotation.rotate( -M_PI/3.0, 0, 0 );
+ // "D3DTransformMatrix"
+ setFastPropertyValue( PROP_SCENE_TRANSF_MATRIX,
+ uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
+}
+
+void Diagram::switchRightAngledAxes( bool bRightAngledAxes )
+{
+ try
+ {
+ bool bOldRightAngledAxes = false;
+ getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bOldRightAngledAxes; // "RightAngledAxes"
+ if( bOldRightAngledAxes!=bRightAngledAxes)
+ {
+ setFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES, uno::Any( bRightAngledAxes ));
+ if(bRightAngledAxes)
+ {
+ ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( *this ) );
+ lcl_rotateLights( aInverseRotation, *this );
+ }
+ else
+ {
+ ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( *this ) );
+ lcl_rotateLights( aCompleteRotation, *this );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // 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 0000000000..dbd5876b97
--- /dev/null
+++ b/chart2/source/model/main/FormattedString.cxx
@@ -0,0 +1,276 @@
+/* -*- 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 chart
+{
+const ::chart::tPropertyValueMap & StaticFormattedStringDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::CharacterProperties::AddDefaultsToMap( aMap );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticFormattedStringInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+FormattedString::FormattedString() :
+ 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_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();
+ 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();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL FormattedString::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticFormattedStringInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+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/GridProperties.cxx b/chart2/source/model/main/GridProperties.cxx
new file mode 100644
index 0000000000..a495f631f7
--- /dev/null
+++ b/chart2/source/model/main/GridProperties.cxx
@@ -0,0 +1,201 @@
+/* -*- 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 );
+}
+
+const ::chart::tPropertyValueMap & StaticGridDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_GRID_SHOW, false );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue< sal_Int32 >(
+ aTmp, ::chart::LinePropertiesHelper::PROP_LINE_COLOR, 0xb3b3b3 ); // gray30
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticGridInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+GridProperties::GridProperties() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+GridProperties::GridProperties( const GridProperties & rOther ) :
+ impl::GridProperties_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+GridProperties::~GridProperties()
+{}
+
+// ____ OPropertySet ____
+void GridProperties::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticGridDefaults();
+ 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();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL GridProperties::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticGridInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ 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/Legend.cxx b/chart2/source/model/main/Legend.cxx
new file mode 100644
index 0000000000..f72868b58c
--- /dev/null
+++ b/chart2/source/model/main/Legend.cxx
@@ -0,0 +1,275 @@
+/* -*- 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 );
+
+}
+
+} // namespace
+
+namespace chart
+{
+const ::chart::tPropertyValueMap& StaticLegendDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+ ::chart::CharacterProperties::AddDefaultsToMap( aTmp );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_ANCHOR_POSITION, chart2::LegendPosition_LINE_END );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_EXPANSION, css::chart::ChartLegendExpansion_HIGH );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_SHOW, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_OVERLAY, false );
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+::cppu::OPropertyArrayHelper& StaticLegendInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Legend::Legend() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+Legend::Legend( const Legend & rOther ) :
+ impl::Legend_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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();
+ 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();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL Legend::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticLegendInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// 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 0000000000..c866bdbb3f
--- /dev/null
+++ b/chart2/source/model/main/PageBackground.cxx
@@ -0,0 +1,198 @@
+/* -*- 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 <svtools/colorcfg.hxx>
+#include <sfx2/viewsh.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
+{
+
+const ::chart::tPropertyValueMap& StaticPageBackgroundDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // override other defaults
+ Color aDocColor = COL_WHITE;
+ if (SfxViewShell::Current()) {
+ aDocColor = SfxViewShell::Current()->GetColorConfigColor(svtools::DOCCOLOR);
+ } else {
+ SAL_WARN("chart2", "SfxViewShell::Current() returned nullptr");
+ }
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::FillProperties::PROP_FILL_COLOR, aDocColor );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticPageBackgroundInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+PageBackground::PageBackground() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+PageBackground::PageBackground( const PageBackground & rOther ) :
+ impl::PageBackground_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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();
+ 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();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL PageBackground::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticPageBackgroundInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ 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 0000000000..2aef8bd45e
--- /dev/null
+++ b/chart2/source/model/main/PageBackground.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 <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <OPropertySet.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 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 0000000000..0807415dac
--- /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 OUString CHART2_COOSYSTEM_POLAR_SERVICE_NAME
+ = u"com.sun.star.chart2.CoordinateSystems.Polar"_ustr;
+
+}
+
+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 0000000000..e8c72059bc
--- /dev/null
+++ b/chart2/source/model/main/StockBar.cxx
@@ -0,0 +1,173 @@
+/* -*- 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
+{
+
+::cppu::OPropertyArrayHelper& StaticStockBarInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+const ::chart::tPropertyValueMap & StaticStockBarDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( aTmp, ::chart::FillProperties::PROP_FILL_COLOR, 0xffffff ); // white
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+StockBar::StockBar( bool bRisingCourse ) :
+ 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_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();
+ 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();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL StockBar::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticStockBarInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ 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 0000000000..6833684e9b
--- /dev/null
+++ b/chart2/source/model/main/Title.cxx
@@ -0,0 +1,343 @@
+/* -*- 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 );
+}
+
+const ::chart::tPropertyValueMap& StaticTitleDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // ParagraphProperties
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_PARA_ADJUST,
+ css::style::ParagraphAdjust_CENTER );
+ // PROP_TITLE_PARA_LAST_LINE_ADJUST
+
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_LEFT_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_RIGHT_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_TOP_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_BOTTOM_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_PARA_IS_HYPHENATION, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_VISIBLE, true );
+
+ // own properties
+ ::chart::PropertyHelper::setPropertyValueDefault< double >( aTmp, PROP_TITLE_TEXT_ROTATION, 0.0 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_TEXT_STACKED, false );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticTitleInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Title::Title() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+Title::Title( const Title & rOther ) :
+ impl::Title_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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();
+ 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();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL Title::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticTitleInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ 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 0000000000..a756e7440a
--- /dev/null
+++ b/chart2/source/model/main/UndoManager.cxx
@@ -0,0 +1,350 @@
+/* -*- 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 <ChartModel.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, ::chart::ChartModel& 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
+ ::chart::ChartModel& 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;
+ ::chart::ChartModel& 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( ::chart::ChartModel& 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( &m_pImpl->getParent() );
+ }
+
+ void SAL_CALL UndoManager::redo( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().redo( aGuard );
+
+ ChartViewHelper::setViewToDirtyState( &m_pImpl->getParent() );
+ }
+
+ 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 0000000000..c20dcef664
--- /dev/null
+++ b/chart2/source/model/main/UndoManager.hxx
@@ -0,0 +1,92 @@
+/* -*- 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
+{
+class ChartModel;
+
+ namespace impl
+ {
+ class UndoManager_Impl;
+ typedef ::cppu::ImplHelper2 < css::document::XUndoManager
+ , css::util::XModifyBroadcaster
+ > UndoManager_Base;
+ }
+
+ class UndoManager : public impl::UndoManager_Base
+ {
+ public:
+ UndoManager( ::chart::ChartModel& 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 0000000000..1bbe133de9
--- /dev/null
+++ b/chart2/source/model/main/Wall.cxx
@@ -0,0 +1,155 @@
+/* -*- 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
+{
+
+::cppu::OPropertyArrayHelper& StaticWallInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ 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 );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Wall::Wall() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+Wall::Wall( const Wall & rOther ) :
+ impl::Wall_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ 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
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL Wall::getInfoHelper()
+{
+ return StaticWallInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL Wall::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticWallInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ 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 0000000000..6cae798959
--- /dev/null
+++ b/chart2/source/model/main/Wall.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 <com/sun/star/util/XCloneable.hpp>
+#include <OPropertySet.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 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: */