chart2/qa/extras/chart2import.cxx                                  |   22 +++++
 chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx |    1 
 chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx |    1 
 chart2/source/model/main/DataPointProperties.cxx                   |    6 +
 chart2/source/model/main/DataPointProperties.hxx                   |    3 
 chart2/source/tools/DataSeriesHelper.cxx                           |    3 
 chart2/source/view/charttypes/PieChart.cxx                         |   38 
++++++----
 chart2/source/view/inc/VDataSeries.hxx                             |    1 
 chart2/source/view/main/VDataSeries.cxx                            |   21 +++++
 offapi/com/sun/star/chart2/DataPointProperties.idl                 |    6 +
 oox/source/drawingml/chart/seriesconverter.cxx                     |    3 
 oox/source/token/properties.txt                                    |    1 
 12 files changed, 92 insertions(+), 14 deletions(-)

New commits:
commit a77403d11a60ebe6aeb33d9b6ae611412d9ab1cc
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Thu Jan 25 11:57:40 2024 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Jan 30 10:40:43 2024 +0100

    tdf#146756 pie chart2 import: use manualLayout Width for pie chart labels
    
    ... and use a compatible 1/5 width if not specified.
    
    This patch depends on the previous oox patch
    (commit 301e27cbebf7d6e4c9b82290d7cd555c43f0c999)
    which actually reads the width into the model.
    
    Fixes a 7.2 regression from
    commit b0068342398786ca50304260434a18880dddf74d
    author Tünde Tóth on Wed Dec 16 18:26:26 2020 +0100
        tdf#138777 pie chart: improve long data label width
    
    and is basically a re-write of 7.1's
    commit 20da1a5dd37c7edac620566c992d5a53b23a5f12
    author Tünde Tóth <toth.tu...@nisz.hu>  on Fri Oct 09 09:24:18 2020 +0200
        tdf#134978 Chart OOXML Import: fix pie chart label custom position
    
    This is very risky, but then ANYTHING changing chart2 is risky.
    There were a lot of changes made in 7.1,
    and they all invited regressions.
    However, our chart implementation is not in a good state,
    and certainly is not very interoperable,
    so it is worth taking the risk.
    
    Anything dealing with manualLayout at this point
    should have originated as a pptx,
    so forcing a compatible max width should be fairly safe.
    
    It probably isn't actually all that risky after all.
    
    largely copied code from
    commit 4223ff2be69f03e571464b0b09ad0d278918631b
    Author: Balazs Varga on Wed Jan 15 16:31:35 2020 +0100
        tdf#48436 Chart: add CustomLabelPosition UNO API property
    
    Fortunately this all goes away after a round-trip
    since custom label placement is lost on export to OOXML,
    and that really helps to reduce the risk.
    
    make CppunitTest_chart2_import CPPUNIT_TEST_NAME=testTdf146487
    
    Change-Id: I9722fc6c759c15ac3924780e6fc124f02fba07e1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162590
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/chart2/qa/extras/chart2import.cxx 
b/chart2/qa/extras/chart2import.cxx
index fc8042a38393..b23e048c6949 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -29,6 +29,7 @@
 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
 #include <com/sun/star/chart/DataLabelPlacement.hpp>
 #include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/qa/XDumper.hpp>
 #include <iterator>
 
 #include <com/sun/star/util/Color.hpp>
@@ -37,6 +38,8 @@
 #include <basegfx/utils/gradienttools.hxx>
 #include <docmodel/uno/UnoGradientTools.hxx>
 
+namespace
+{
 class Chart2ImportTest : public ChartTest
 {
 public:
@@ -46,6 +49,11 @@ protected:
     void testTransparentBackground(std::u16string_view filename);
 };
 
+OUString getShapeDump(css::uno::Reference<css::chart::XChartDocument> const& 
doc)
+{
+    return css::uno::Reference<css::qa::XDumper>(doc, 
css::uno::UNO_QUERY_THROW)->dump("shapes");
+}
+
 // error bar import
 // split method up into smaller chunks for more detailed tests
 CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFdo60083)
@@ -187,7 +195,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSteppedLines)
     }
 }
 
-static uno::Sequence < OUString > getChartColumnDescriptions( uno::Reference< 
chart::XChartDocument > const & xChart1Doc)
+uno::Sequence < OUString > getChartColumnDescriptions( uno::Reference< 
chart::XChartDocument > const & xChart1Doc)
 {
     CPPUNIT_ASSERT(xChart1Doc.is());
     uno::Reference< chart::XChartDataArray > xChartData ( 
xChart1Doc->getData(), UNO_QUERY_THROW);
@@ -1988,6 +1996,17 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf146487)
     Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
     uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
     CPPUNIT_ASSERT_MESSAGE("chart doc should not have a title", !xTitle.is());
+
+    // tdf#146756 use manualLayout Width that was provided (so Green;  
$7,654,321 is not wrapped
+    if (!IsDefaultDPI())
+        return;
+    uno::Reference<chart::XChartDocument> xDoc = getChartDocFromDrawImpress(0, 
0);
+    OString aXmlDump = OUStringToOString(getShapeDump(xDoc), 
RTL_TEXTENCODING_UTF8);
+    xmlDocUniquePtr pXmlDoc(xmlParseDoc(reinterpret_cast<const 
xmlChar*>(aXmlDump.getStr())));
+    OString aPath("//XShape[@text='Green;  $7,654,321 ']"_ostr);
+    assertXPath(pXmlDoc, aPath, 1);
+    // Expected - 1 line tall(371), not 4 lines(1481).
+    CPPUNIT_ASSERT_EQUAL(OUString("371"), getXPath(pXmlDoc, aPath, 
"sizeY"_ostr));
 }
 
 CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFixedSizeBarChartVeryLongLabel)
@@ -2248,6 +2267,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest, 
testPieChartPlotAreaMarginWithAutomaticLa
     }
 }
 
+} // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx 
b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
index 2b194051a1f2..93490438d753 100644
--- a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
+++ b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
@@ -460,6 +460,7 @@ bool DataPointItemConverter::ApplySpecialItem(
                 {
                     GetPropertySet()->setPropertyValue("LabelPlacement", 
uno::Any(nNew));
                     GetPropertySet()->setPropertyValue("CustomLabelPosition", 
uno::Any());
+                    GetPropertySet()->setPropertyValue("CustomLabelSize", 
uno::Any());
                     bChanged = true;
                 }
             }
diff --git a/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx 
b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
index 0f4019546592..10c1f9373547 100644
--- a/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
+++ b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
@@ -401,6 +401,7 @@ bool TextLabelItemConverter::ApplySpecialItem( sal_uInt16 
nWhichId, const SfxIte
                 {
                     GetPropertySet()->setPropertyValue("LabelPlacement", 
uno::Any(nNew));
                     GetPropertySet()->setPropertyValue("CustomLabelPosition", 
uno::Any());
+                    GetPropertySet()->setPropertyValue("CustomLabelSize", 
uno::Any());
                     bChanged = true;
                 }
             }
diff --git a/chart2/source/model/main/DataPointProperties.cxx 
b/chart2/source/model/main/DataPointProperties.cxx
index 819336edd9c4..c27407c98fca 100644
--- a/chart2/source/model/main/DataPointProperties.cxx
+++ b/chart2/source/model/main/DataPointProperties.cxx
@@ -30,6 +30,7 @@
 #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/RelativeSize.hpp>
 #include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
 #include <com/sun/star/chart2/DataPointLabel.hpp>
@@ -447,6 +448,11 @@ void DataPointProperties::AddPropertiesToVector(
                   cppu::UnoType<chart2::RelativePosition>::get(),
                   beans::PropertyAttribute::BOUND
                   | beans::PropertyAttribute::MAYBEVOID );
+
+    rOutProperties.emplace_back("CustomLabelSize", 
PROP_DATAPOINT_LABEL_CUSTOM_SIZE,
+                                cppu::UnoType<chart2::RelativeSize>::get(),
+                                beans::PropertyAttribute::BOUND
+                                    | beans::PropertyAttribute::MAYBEVOID);
 }
 
 void DataPointProperties::AddDefaultsToMap(
diff --git a/chart2/source/model/main/DataPointProperties.hxx 
b/chart2/source/model/main/DataPointProperties.hxx
index ada7907b888f..1689322148d8 100644
--- a/chart2/source/model/main/DataPointProperties.hxx
+++ b/chart2/source/model/main/DataPointProperties.hxx
@@ -87,7 +87,8 @@ namespace DataPointProperties
         PROP_DATAPOINT_LABEL_BORDER_DASH_NAME,
         PROP_DATAPOINT_LABEL_BORDER_TRANS,
         PROP_DATAPOINT_CUSTOM_LABEL_FIELDS,
-        PROP_DATAPOINT_LABEL_CUSTOM_POS
+        PROP_DATAPOINT_LABEL_CUSTOM_POS,
+        PROP_DATAPOINT_LABEL_CUSTOM_SIZE
 
         // additionally some properties from ::chart::LineProperties
     };
diff --git a/chart2/source/tools/DataSeriesHelper.cxx 
b/chart2/source/tools/DataSeriesHelper.cxx
index dba33728b5aa..a6efbda3a1e9 100644
--- a/chart2/source/tools/DataSeriesHelper.cxx
+++ b/chart2/source/tools/DataSeriesHelper.cxx
@@ -467,7 +467,10 @@ void setPropertyAlsoToAllAttributedDataPoints( const 
rtl::Reference< ::chart::Da
                 continue;
             xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
             if( rPropertyName == "LabelPlacement" )
+            {
                 xPointProp->setPropertyValue("CustomLabelPosition", 
uno::Any());
+                xPointProp->setPropertyValue("CustomLabelSize", uno::Any());
+            }
         }
     }
 }
diff --git a/chart2/source/view/charttypes/PieChart.cxx 
b/chart2/source/view/charttypes/PieChart.cxx
index 5e3a6dcaad17..93221b468473 100644
--- a/chart2/source/view/charttypes/PieChart.cxx
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -324,14 +324,18 @@ void PieChart::createTextLabelShape(
     sal_Int32 nLabelPlacement = rSeries.getLabelPlacement(
         nPointIndex, m_xChartTypeModel, m_aPosHelper.isSwapXAndY());
 
+    // has an X/Y offset (relative to the OUTSIDE label default position) been 
provided?
+    const bool bHasCustomLabelPlacement = nLabelPlacement == 
css::chart::DataLabelPlacement::CUSTOM;
+    if (bHasCustomLabelPlacement)
+        nLabelPlacement = css::chart::DataLabelPlacement::OUTSIDE;
+
     ///when the placement is of `AVOID_OVERLAP` type a later rearrangement of
     ///the label position is allowed; the `createTextLabelShape` treats the
     ///`AVOID_OVERLAP` as if it was of `CENTER` type;
 
     double nVal = rSeries.getYValue(nPointIndex);
     //AVOID_OVERLAP is in fact "Best fit" in the UI.
-    bool bMovementAllowed = nLabelPlacement == 
css::chart::DataLabelPlacement::AVOID_OVERLAP
-                            || nLabelPlacement == 
css::chart::DataLabelPlacement::CUSTOM;
+    bool bMovementAllowed = nLabelPlacement == 
css::chart::DataLabelPlacement::AVOID_OVERLAP;
     if( bMovementAllowed )
         nLabelPlacement = css::chart::DataLabelPlacement::CENTER;
 
@@ -398,14 +402,26 @@ void PieChart::createTextLabelShape(
 
     // set the maximum text width to be used when text wrapping is enabled
     double fTextMaximumFrameWidth = 0.8 * fPieRadius;
-    if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE
-        && m_aAvailableOuterRect.getWidth())
+    if (m_aAvailableOuterRect.getWidth())
     {
-        if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
-            || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
-            fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 3.0;
-        else
-            fTextMaximumFrameWidth = 0.85 * (m_aAvailableOuterRect.getWidth() 
/ 2.0 - fPieRadius);
+        if (bHasCustomLabelPlacement)
+        {
+            // if a custom width has been provided, then use that of course,
+            // otherwise use the interoperability-compliant 1/5 of the chart 
space as max width
+            const awt::Size aCustomSize = 
rSeries.getLabelCustomSize(nPointIndex);
+            if (aCustomSize.Width > 0)
+                fTextMaximumFrameWidth = aCustomSize.Width;
+            else
+                fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 
5.0;
+        }
+        else if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE)
+        {
+            if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
+                || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
+                fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 
3.0;
+            else
+                fTextMaximumFrameWidth = 0.85 * 
(m_aAvailableOuterRect.getWidth() / 2.0 - fPieRadius);
+        }
     }
     sal_Int32 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth);
 
@@ -430,9 +446,7 @@ void PieChart::createTextLabelShape(
          *  First off the routine try to place the label inside the related 
pie slice,
          *  if this is not possible the label is placed outside.
          */
-        if (rSeries.getLabelPlacement(nPointIndex, m_xChartTypeModel, 
m_aPosHelper.isSwapXAndY())
-                == css::chart::DataLabelPlacement::CUSTOM
-            || !performLabelBestFitInnerPlacement(rParam, aPieLabelInfo))
+        if (!performLabelBestFitInnerPlacement(rParam, aPieLabelInfo))
         {
             if (m_aAvailableOuterRect.getWidth())
             {
diff --git a/chart2/source/view/inc/VDataSeries.hxx 
b/chart2/source/view/inc/VDataSeries.hxx
index 65f7247bc197..72f5fca80089 100644
--- a/chart2/source/view/inc/VDataSeries.hxx
+++ b/chart2/source/view/inc/VDataSeries.hxx
@@ -112,6 +112,7 @@ public:
 
     css::awt::Point getLabelPosition( css::awt::Point aTextShapePos, sal_Int32 
nPointIndex ) const;
     bool isLabelCustomPos( sal_Int32 nPointIndex ) const;
+    css::awt::Size getLabelCustomSize(sal_Int32 nPointIndex) const;
 
     css::uno::Reference<css::beans::XPropertySet> getPropertiesOfPoint( 
sal_Int32 index ) const;
 
diff --git a/chart2/source/view/main/VDataSeries.cxx 
b/chart2/source/view/main/VDataSeries.cxx
index 845e6d6ef0db..455c991b9f89 100644
--- a/chart2/source/view/main/VDataSeries.cxx
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -36,6 +36,7 @@
 #include <com/sun/star/chart2/Symbol.hpp>
 #include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
 #include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
 
 #include <osl/diagnose.h>
 #include <tools/color.hxx>
@@ -645,6 +646,26 @@ bool VDataSeries::isLabelCustomPos(sal_Int32 nPointIndex) 
const
     return bCustom;
 }
 
+awt::Size VDataSeries::getLabelCustomSize(sal_Int32 nPointIndex) const
+{
+    awt::Size aSize(-1, -1);
+    try
+    {
+        RelativeSize aCustomLabelSize;
+        const uno::Reference<beans::XPropertySet> 
xPointProps(getPropertiesOfPoint(nPointIndex));
+        if (xPointProps.is() && 
(xPointProps->getPropertyValue("CustomLabelSize") >>= aCustomLabelSize))
+        {
+            aSize.Width = static_cast<sal_Int32>(aCustomLabelSize.Primary * 
m_aReferenceSize.Width);
+            aSize.Height = static_cast<sal_Int32>(aCustomLabelSize.Secondary * 
m_aReferenceSize.Height);
+        }
+    }
+    catch (const uno::Exception&)
+    {
+        DBG_UNHANDLED_EXCEPTION("chart2");
+    }
+    return aSize;
+}
+
 double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const
 {
     double fMin = std::numeric_limits<double>::infinity();
diff --git a/offapi/com/sun/star/chart2/DataPointProperties.idl 
b/offapi/com/sun/star/chart2/DataPointProperties.idl
index b2dd1163967a..7fe64e77ad9d 100644
--- a/offapi/com/sun/star/chart2/DataPointProperties.idl
+++ b/offapi/com/sun/star/chart2/DataPointProperties.idl
@@ -317,6 +317,12 @@ service DataPointProperties
         @since LibreOffice 7.0
     */
     [optional, maybevoid, property] ::com::sun::star::chart2::RelativePosition 
CustomLabelPosition;
+
+    /** Custom size associated with the CUSTOM label placement.
+
+        @since LibreOffice 24.8
+    */
+    [optional, maybevoid, property] ::com::sun::star::chart2::RelativeSize 
CustomLabelSize;
 };
 
 } ; // chart2
diff --git a/oox/source/drawingml/chart/seriesconverter.cxx 
b/oox/source/drawingml/chart/seriesconverter.cxx
index db3916b74f63..2d07f26493ef 100644
--- a/oox/source/drawingml/chart/seriesconverter.cxx
+++ b/oox/source/drawingml/chart/seriesconverter.cxx
@@ -21,6 +21,7 @@
 
 #include <com/sun/star/chart/DataLabelPlacement.hpp>
 #include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
 #include <com/sun/star/chart/ErrorBarStyle.hpp>
 #include <com/sun/star/chart2/DataPointLabel.hpp>
 #include <com/sun/star/drawing/Hatch.hpp>
@@ -291,6 +292,8 @@ void DataLabelConverter::convertFromModel( const Reference< 
XDataSeries >& rxDat
         {
             RelativePosition aPos(mrModel.mxLayout->mfX, 
mrModel.mxLayout->mfY, css::drawing::Alignment_TOP_LEFT);
             aPropSet.setProperty(PROP_CustomLabelPosition, aPos);
+            const RelativeSize aSize(mrModel.mxLayout->mfW, 
mrModel.mxLayout->mfH);
+            aPropSet.setProperty(PROP_CustomLabelSize, aSize);
             sal_Int32 nPlacement = -1;
             if (bIsPie && aPropSet.getProperty(nPlacement, PROP_LabelPlacement)
                 && nPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP)
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index b6fa29c090fe..a8764a432b5d 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -123,6 +123,7 @@ CursorPositionY
 CurveName
 CurveStyle
 CustomLabelPosition
+CustomLabelSize
 CustomShapeGeometry
 D3DSceneAmbientColor
 D3DSceneLightColor2

Reply via email to