summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chart2/qa/extras/chart2export.cxx23
-rw-r--r--chart2/qa/extras/data/docx/MSO_axis_position.docxbin0 -> 41444 bytes
-rw-r--r--chart2/source/controller/chartapiwrapper/AxisWrapper.cxx10
-rw-r--r--chart2/source/model/main/Axis.cxx11
-rw-r--r--include/xmloff/xmltoken.hxx1
-rw-r--r--offapi/com/sun/star/chart2/Axis.idl6
-rw-r--r--schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng9
-rw-r--r--xmloff/source/chart/PropertyMap.hxx1
-rw-r--r--xmloff/source/chart/SchXMLAxisContext.cxx43
-rw-r--r--xmloff/source/chart/SchXMLExport.cxx29
-rw-r--r--xmloff/source/core/xmltoken.cxx1
-rw-r--r--xmloff/source/token/tokens.txt1
12 files changed, 104 insertions, 31 deletions
diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx
index 589225e8cd2e..8e2e1a84bcf9 100644
--- a/chart2/qa/extras/chart2export.cxx
+++ b/chart2/qa/extras/chart2export.cxx
@@ -133,7 +133,7 @@ public:
void testCrossBetweenODS();
void testAxisTitleRotationXLSX();
void testAxisTitlePositionDOCX();
- void testAxisCrossBetweenXSLX();
+ void testAxisCrossBetweenDOCX();
void testPieChartDataPointExplosionXLSX();
void testCustomDataLabel();
void testCustomPositionofDataLabel();
@@ -161,6 +161,7 @@ public:
void testTdf130225();
void testTdf126076();
void testTdf75330();
+ void testTdf127792();
CPPUNIT_TEST_SUITE(Chart2ExportTest);
CPPUNIT_TEST(testErrorBarXLSX);
@@ -257,7 +258,7 @@ public:
CPPUNIT_TEST(testCrossBetweenODS);
CPPUNIT_TEST(testAxisTitleRotationXLSX);
CPPUNIT_TEST(testAxisTitlePositionDOCX);
- CPPUNIT_TEST(testAxisCrossBetweenXSLX);
+ CPPUNIT_TEST(testAxisCrossBetweenDOCX);
CPPUNIT_TEST(testPieChartDataPointExplosionXLSX);
CPPUNIT_TEST(testCustomDataLabel);
CPPUNIT_TEST(testCustomPositionofDataLabel);
@@ -285,6 +286,7 @@ public:
CPPUNIT_TEST(testTdf130225);
CPPUNIT_TEST(testTdf126076);
CPPUNIT_TEST(testTdf75330);
+ CPPUNIT_TEST(testTdf127792);
CPPUNIT_TEST_SUITE_END();
@@ -2105,7 +2107,7 @@ void Chart2ExportTest::testAxisTitlePositionDOCX()
CPPUNIT_ASSERT_DOUBLES_EQUAL(0.384070199122511, nY, 1e-2);
}
-void Chart2ExportTest::testAxisCrossBetweenXSLX()
+void Chart2ExportTest::testAxisCrossBetweenDOCX()
{
load("/chart2/qa/extras/data/odt/", "axis-position.odt");
xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
@@ -2634,6 +2636,21 @@ void Chart2ExportTest::testTdf75330()
}
}
+void Chart2ExportTest::testTdf127792()
+{
+ load("/chart2/qa/extras/data/docx/", "MSO_axis_position.docx");
+ {
+ xmlDocPtr pXmlDoc = parseExport("word/charts/chart1", "Office Open XML Text");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between");
+ }
+ {
+ xmlDocPtr pXmlDoc = parseExport("word/charts/chart2", "Office Open XML Text");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "midCat");
+ }
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ExportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/chart2/qa/extras/data/docx/MSO_axis_position.docx b/chart2/qa/extras/data/docx/MSO_axis_position.docx
new file mode 100644
index 000000000000..a9955b7b1ad7
--- /dev/null
+++ b/chart2/qa/extras/data/docx/MSO_axis_position.docx
Binary files differ
diff --git a/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx b/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx
index 3516d7a29ba2..b0a1d5f85746 100644
--- a/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx
+++ b/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx
@@ -96,7 +96,8 @@ enum
PROP_AXIS_GAP_WIDTH,
PROP_AXIS_DISPLAY_UNITS,
PROP_AXIS_BUILTINUNIT,
- PROP_AXIS_TRY_STAGGERING_FIRST
+ PROP_AXIS_TRY_STAGGERING_FIRST,
+ PROP_AXIS_MAJOR_ORIGIN
};
void lcl_AddPropertiesToVector(
@@ -323,6 +324,12 @@ void lcl_AddPropertiesToVector(
cppu::UnoType<bool>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MajorOrigin",
+ PROP_AXIS_MAJOR_ORIGIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
}
struct StaticAxisWrapperPropertyArray_Initializer
@@ -616,6 +623,7 @@ std::vector< std::unique_ptr<WrappedProperty> > AxisWrapper::createWrappedProper
aWrappedProperties.emplace_back( new WrappedLinkNumberFormatProperty );
aWrappedProperties.emplace_back( new WrappedProperty("StackedText","StackCharacters") );
aWrappedProperties.emplace_back( new WrappedDirectStateProperty("CrossoverPosition","CrossoverPosition") );
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("MajorOrigin","MajorOrigin") );
{
WrappedGapwidthProperty* pWrappedGapwidthProperty( new WrappedGapwidthProperty( m_spChart2ModelContact ) );
WrappedBarOverlapProperty* pWrappedBarOverlapProperty( new WrappedBarOverlapProperty( m_spChart2ModelContact ) );
diff --git a/chart2/source/model/main/Axis.cxx b/chart2/source/model/main/Axis.cxx
index b7e19a49e548..ff42899d0c18 100644
--- a/chart2/source/model/main/Axis.cxx
+++ b/chart2/source/model/main/Axis.cxx
@@ -75,7 +75,8 @@ enum
PROP_AXIS_DISPLAY_UNITS,
PROP_AXIS_BUILTINUNIT,
- PROP_AXIS_TRY_STAGGERING_FIRST
+ PROP_AXIS_TRY_STAGGERING_FIRST,
+ PROP_AXIS_MAJOR_ORIGIN
};
void lcl_AddPropertiesToVector(
@@ -161,11 +162,13 @@ void lcl_AddPropertiesToVector(
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(),
@@ -193,6 +196,12 @@ void lcl_AddPropertiesToVector(
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "MajorOrigin",
+ PROP_AXIS_MAJOR_ORIGIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
}
struct StaticAxisDefaults_Initializer
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 5892f1e50e03..4b4e416a882f 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1180,6 +1180,7 @@ namespace xmloff { namespace token {
XML_MACTION,
XML_MAIN_ENTRY_STYLE_NAME,
XML_MAJOR,
+ XML_MAJOR_ORIGIN,
XML_MALIGNGROUP,
XML_MALIGNMARK,
XML_MANUAL,
diff --git a/offapi/com/sun/star/chart2/Axis.idl b/offapi/com/sun/star/chart2/Axis.idl
index fc3a0f564c54..678d9a9a56a1 100644
--- a/offapi/com/sun/star/chart2/Axis.idl
+++ b/offapi/com/sun/star/chart2/Axis.idl
@@ -141,6 +141,12 @@ service Axis
*/
[optional, property] boolean TryStaggeringFirst;
+ /** This attribute specifies the shift of the first major tick from the origin.
+
+ @since LibreOffice 7.0
+ */
+ [optional, property] long MajorOrigin;
+
};
} ; // chart2
diff --git a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
index 05607e00f571..7491e0ec1c8d 100644
--- a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
+++ b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
@@ -2439,4 +2439,13 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
</rng:optional>
</rng:define>
+ <!-- https://issues.oasis-open.org/browse/OFFICE-3936 -->
+ <rng:define name="style-chart-properties-attlist" combine="interleave">
+ <rng:optional>
+ <rng:attribute name="loext:major-origin">
+ <rng:ref name="double"/>
+ </rng:attribute>
+ </rng:optional>
+ </rng:define>
+
</rng:grammar>
diff --git a/xmloff/source/chart/PropertyMap.hxx b/xmloff/source/chart/PropertyMap.hxx
index aa132990bc3b..0b8d52c93bce 100644
--- a/xmloff/source/chart/PropertyMap.hxx
+++ b/xmloff/source/chart/PropertyMap.hxx
@@ -184,6 +184,7 @@ const XMLPropertyMapEntry aXMLChartPropMap[] =
MAP_SPECIAL( "NumberFormat", STYLE, XML_DATA_STYLE_NAME, XML_TYPE_NUMBER, XML_SCH_CONTEXT_SPECIAL_NUMBER_FORMAT ),
MAP_ENTRY( "LinkNumberFormatToSource", CHART, XML_LINK_DATA_STYLE_TO_SOURCE, XML_TYPE_BOOL ),
MAP_ENTRY( "Visible", CHART, XML_VISIBLE, XML_TYPE_BOOL ),
+ MAP_ENTRY_ODF_EXT( "MajorOrigin", LO_EXT, XML_MAJOR_ORIGIN, XML_TYPE_DOUBLE ),
MAP_FULL( "CrossoverPosition", CHART, XML_AXIS_POSITION, XML_SCH_TYPE_AXIS_POSITION|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0, SvtSaveOptions::ODFVER_012 ),
MAP_FULL( "CrossoverValue", CHART, XML_AXIS_POSITION, XML_SCH_TYPE_AXIS_POSITION_VALUE|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0, SvtSaveOptions::ODFVER_012 ),
diff --git a/xmloff/source/chart/SchXMLAxisContext.cxx b/xmloff/source/chart/SchXMLAxisContext.cxx
index 962fec96e6df..577d87b1ac49 100644
--- a/xmloff/source/chart/SchXMLAxisContext.cxx
+++ b/xmloff/source/chart/SchXMLAxisContext.cxx
@@ -465,25 +465,6 @@ void SchXMLAxisContext::CreateAxis()
if( m_bAxisTypeImported )
m_xAxisProps->setPropertyValue("AxisType", uno::makeAny(m_nAxisType) );
- if( m_aCurrentAxis.eDimension == SCH_XML_AXIS_X )
- {
- bool bIs3DChart = false;
- if( (xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart) && bIs3DChart )
- {
- OUString sChartType = m_xDiagram->getDiagramType();
- if( sChartType == "com.sun.star.chart.BarDiagram" || sChartType == "com.sun.star.chart.StockDiagram" )
- {
- Reference< chart2::XAxis > xAxis(lcl_getAxis(GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex));
- if( xAxis.is() )
- {
- chart2::ScaleData aScaleData(xAxis->getScaleData());
- aScaleData.ShiftedCategoryPosition = true;
- xAxis->setScaleData(aScaleData);
- }
- }
- }
- }
-
if( !m_aAutoStyleName.isEmpty())
{
const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext();
@@ -579,6 +560,30 @@ void SchXMLAxisContext::CreateAxis()
}
}
}
+
+ if (m_aCurrentAxis.eDimension == SCH_XML_AXIS_X)
+ {
+ Reference<chart2::XAxis> xAxis(lcl_getAxis(GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex));
+ if (xAxis.is())
+ {
+ chart2::ScaleData aScaleData(xAxis->getScaleData());
+ bool bIs3DChart = false;
+ double fMajorOrigin = -1;
+ OUString sChartType = m_xDiagram->getDiagramType();
+ if ((xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart) && bIs3DChart
+ && (sChartType == "com.sun.star.chart.BarDiagram" || sChartType == "com.sun.star.chart.StockDiagram"))
+ {
+ aScaleData.ShiftedCategoryPosition = true;
+ xAxis->setScaleData(aScaleData);
+ }
+ else if ((m_xAxisProps->getPropertyValue("MajorOrigin") >>= fMajorOrigin)
+ && (rtl::math::approxEqual(fMajorOrigin, 0.0) || rtl::math::approxEqual(fMajorOrigin, 0.5)))
+ {
+ aScaleData.ShiftedCategoryPosition = rtl::math::approxEqual(fMajorOrigin, 0.5);
+ xAxis->setScaleData(aScaleData);
+ }
+ }
+ }
}
}
diff --git a/xmloff/source/chart/SchXMLExport.cxx b/xmloff/source/chart/SchXMLExport.cxx
index 07226e89cda2..5566c0b2dfd3 100644
--- a/xmloff/source/chart/SchXMLExport.cxx
+++ b/xmloff/source/chart/SchXMLExport.cxx
@@ -201,7 +201,7 @@ public:
void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
const Reference< beans::XPropertySet >& rAxisProps, const Reference< chart2::XAxis >& rChart2Axis,
const OUString& rCategoriesRanges,
- bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
+ bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent, OUString sChartType );
void exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent );
void exportDateScale( const Reference< beans::XPropertySet >& rAxisProps );
void exportAxisTitle( const Reference< beans::XPropertySet >& rTitleProps, bool bExportContent );
@@ -2290,7 +2290,7 @@ void SchXMLExportHelper_Impl::exportAxis(
const Reference< chart2::XAxis >& rChart2Axis,
const OUString& rCategoriesRange,
bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
- bool bExportContent )
+ bool bExportContent, OUString sChartType )
{
std::vector< XMLPropertyState > aPropertyStates;
std::unique_ptr<SvXMLElementExport> pAxis;
@@ -2298,6 +2298,20 @@ void SchXMLExportHelper_Impl::exportAxis(
// get property states for autostyles
if( rAxisProps.is() && mxExpPropMapper.is() )
{
+ const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFDefaultVersion());
+ if (nCurrentODFVersion > SvtSaveOptions::ODFVER_012 && eDimension == XML_X)
+ {
+ chart2::ScaleData aScaleData(rChart2Axis->getScaleData());
+ bool bShiftedCatPos = aScaleData.ShiftedCategoryPosition;
+ if (sChartType == "com.sun.star.chart.BarDiagram" || sChartType == "com.sun.star.chart.StockDiagram")
+ {
+ if (!bShiftedCatPos)
+ rAxisProps->setPropertyValue("MajorOrigin", uno::makeAny(0.0));
+ }
+ else if (bShiftedCatPos)
+ rAxisProps->setPropertyValue("MajorOrigin", uno::makeAny(0.5));
+ }
+
lcl_exportNumberFormat( "NumberFormat", rAxisProps, mrExport );
aPropertyStates = mxExpPropMapper->Filter( rAxisProps );
@@ -2419,6 +2433,7 @@ void SchXMLExportHelper_Impl::exportAxes(
OUString aCategoriesRange;
Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
+ OUString sChartType = xDiagram->getDiagramType();
// x axis
@@ -2440,7 +2455,7 @@ void SchXMLExportHelper_Impl::exportAxes(
}
}
}
- exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
+ exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent, sChartType );
aCategoriesRange.clear();
}
@@ -2450,7 +2465,7 @@ void SchXMLExportHelper_Impl::exportAxes(
if( xNewAxis.is() )
{
Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : nullptr, uno::UNO_QUERY );
- exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
+ exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent, sChartType );
}
// y axis
@@ -2459,7 +2474,7 @@ void SchXMLExportHelper_Impl::exportAxes(
if( xNewAxis.is() )
{
Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : nullptr, uno::UNO_QUERY );
- exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
+ exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent, sChartType );
}
// secondary y axis
@@ -2468,7 +2483,7 @@ void SchXMLExportHelper_Impl::exportAxes(
if( xNewAxis.is() )
{
Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : nullptr, uno::UNO_QUERY );
- exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
+ exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent, sChartType );
}
// z axis
@@ -2477,7 +2492,7 @@ void SchXMLExportHelper_Impl::exportAxes(
if( xNewAxis.is() )
{
Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : nullptr, uno::UNO_QUERY );
- exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
+ exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent, sChartType );
}
}
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index a9cf682e7d5d..253818ccf2df 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1185,6 +1185,7 @@ namespace xmloff::token {
TOKEN( "maction", XML_MACTION ),
TOKEN( "main-entry-style-name", XML_MAIN_ENTRY_STYLE_NAME ),
TOKEN( "major", XML_MAJOR ),
+ TOKEN( "major-origin", XML_MAJOR_ORIGIN ),
TOKEN( "maligngroup", XML_MALIGNGROUP ),
TOKEN( "malignmark", XML_MALIGNMARK ),
TOKEN( "manual", XML_MANUAL ),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index cd94bd5228d6..fd3806a7f0f2 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -1098,6 +1098,7 @@ macro-name
maction
main-entry-style-name
major
+major-origin
maligngroup
malignmark
manual