Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/chart2/source/view/main/DataTableView.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include <DataTableView.hxx>
11
#include <VSeriesPlotter.hxx>
12
#include <ShapeFactory.hxx>
13
#include <ExplicitCategoriesProvider.hxx>
14
#include <ChartModel.hxx>
15
#include <ObjectIdentifier.hxx>
16
17
#include <svx/svdotable.hxx>
18
19
#include <com/sun/star/table/BorderLine.hpp>
20
#include <com/sun/star/table/BorderLine2.hpp>
21
#include <com/sun/star/table/TableBorder.hpp>
22
#include <com/sun/star/table/BorderLineStyle.hpp>
23
#include <com/sun/star/text/XTextRange.hpp>
24
#include <com/sun/star/text/XText.hpp>
25
#include <com/sun/star/style/ParagraphAdjust.hpp>
26
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
27
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
28
#include <com/sun/star/drawing/LineDash.hpp>
29
#include <com/sun/star/drawing/LineStyle.hpp>
30
#include <com/sun/star/drawing/FillStyle.hpp>
31
#include <com/sun/star/util/XBroadcaster.hpp>
32
#include <com/sun/star/container/XNameContainer.hpp>
33
#include <com/sun/star/uno/XComponentContext.hpp>
34
35
#include <o3tl/unit_conversion.hxx>
36
37
using namespace css;
38
39
namespace chart
40
{
41
namespace
42
{
43
void setTopCell(const uno::Reference<beans::XPropertySet>& xPropertySet)
44
0
{
45
0
    xPropertySet->setPropertyValue(u"FillColor"_ustr, uno::Any(Color(0xFFFFFF)));
46
0
    xPropertySet->setPropertyValue(u"TextVerticalAdjust"_ustr,
47
0
                                   uno::Any(drawing::TextVerticalAdjust_TOP));
48
0
    xPropertySet->setPropertyValue(u"ParaAdjust"_ustr, uno::Any(style::ParagraphAdjust_CENTER));
49
50
0
    table::BorderLine2 aBorderLine;
51
0
    aBorderLine.LineWidth = 0;
52
0
    aBorderLine.Color = 0x000000;
53
54
0
    xPropertySet->setPropertyValue(u"TopBorder"_ustr, uno::Any(aBorderLine));
55
0
    xPropertySet->setPropertyValue(u"LeftBorder"_ustr, uno::Any(aBorderLine));
56
0
}
57
58
void copyProperty(const uno::Reference<beans::XPropertySet>& xOut,
59
                  const uno::Reference<beans::XPropertySet>& xIn, OUString const& sPropertyName)
60
0
{
61
0
    xOut->setPropertyValue(sPropertyName, xIn->getPropertyValue(sPropertyName));
62
0
}
63
64
uno::Reference<text::XTextRange> getFirstParagraph(uno::Reference<text::XText> const& xText)
65
0
{
66
0
    uno::Reference<text::XTextRange> xParagraph;
67
0
    uno::Reference<container::XEnumerationAccess> xEnumAccess(xText, uno::UNO_QUERY);
68
0
    if (!xEnumAccess.is())
69
0
        return xParagraph;
70
0
    uno::Reference<container::XEnumeration> xEnumeration(xEnumAccess->createEnumeration());
71
0
    xParagraph.set(xEnumeration->nextElement(), uno::UNO_QUERY);
72
0
    return xParagraph;
73
0
}
74
75
uno::Reference<beans::XPropertySet>
76
getFirstParagraphProperties(uno::Reference<text::XText> const& xText)
77
0
{
78
0
    uno::Reference<beans::XPropertySet> xPropertySet;
79
0
    auto xParagraph = getFirstParagraph(xText);
80
0
    if (!xParagraph.is())
81
0
        return xPropertySet;
82
0
    xPropertySet.set(xParagraph, uno::UNO_QUERY);
83
0
    return xPropertySet;
84
0
}
85
86
} // end anonymous namespace
87
88
DataTableView::DataTableView(
89
    rtl::Reference<::chart::ChartModel> const& xChartModel,
90
    rtl::Reference<DataTable> const& rDataTableModel,
91
    css::uno::Reference<css::uno::XComponentContext> const& rComponentContext,
92
    bool bAlignAxisValuesWithColumns)
93
0
    : m_xChartModel(xChartModel)
94
0
    , m_xDataTableModel(rDataTableModel)
95
0
    , m_xComponentContext(rComponentContext)
96
0
    , m_bAlignAxisValuesWithColumns(bAlignAxisValuesWithColumns)
97
0
{
98
0
    m_aLineProperties.initFromPropertySet(uno::Reference<beans::XPropertySet>(m_xDataTableModel));
99
0
}
100
101
void DataTableView::setCellCharAndParagraphProperties(
102
    const uno::Reference<beans::XPropertySet>& xPropertySet)
103
0
{
104
0
    uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel);
105
106
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharColor"_ustr);
107
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontFamily"_ustr);
108
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontFamilyAsian"_ustr);
109
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontFamilyComplex"_ustr);
110
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontCharSet"_ustr);
111
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontCharSetAsian"_ustr);
112
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontCharSetComplex"_ustr);
113
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontName"_ustr);
114
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontNameAsian"_ustr);
115
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontNameComplex"_ustr);
116
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontPitch"_ustr);
117
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontPitchAsian"_ustr);
118
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontPitchComplex"_ustr);
119
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontStyleName"_ustr);
120
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontStyleNameAsian"_ustr);
121
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharFontStyleNameComplex"_ustr);
122
123
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharHeight"_ustr);
124
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharHeightAsian"_ustr);
125
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharHeightComplex"_ustr);
126
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharKerning"_ustr);
127
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharLocale"_ustr);
128
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharLocaleAsian"_ustr);
129
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharLocaleComplex"_ustr);
130
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharPosture"_ustr);
131
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharPostureAsian"_ustr);
132
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharPostureComplex"_ustr);
133
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharRelief"_ustr);
134
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharShadowed"_ustr);
135
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharStrikeout"_ustr);
136
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharUnderline"_ustr);
137
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharUnderlineColor"_ustr);
138
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharUnderlineHasColor"_ustr);
139
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharOverline"_ustr);
140
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharOverlineColor"_ustr);
141
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharOverlineHasColor"_ustr);
142
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharWeight"_ustr);
143
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharWeightAsian"_ustr);
144
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharWeightComplex"_ustr);
145
0
    copyProperty(xPropertySet, xDataTableProperties, u"CharWordMode"_ustr);
146
147
0
    drawing::FillStyle eFillStyle = drawing::FillStyle_NONE;
148
0
    xDataTableProperties->getPropertyValue(u"FillStyle"_ustr) >>= eFillStyle;
149
0
    if (eFillStyle == drawing::FillStyle_SOLID)
150
0
    {
151
0
        sal_Int32 aColor = 0;
152
0
        if (xDataTableProperties->getPropertyValue(u"FillColor"_ustr) >>= aColor)
153
0
            xPropertySet->setPropertyValue(u"CharBackColor"_ustr, uno::Any(aColor));
154
0
    }
155
156
0
    xPropertySet->setPropertyValue(u"ParaAdjust"_ustr, uno::Any(style::ParagraphAdjust_CENTER));
157
0
}
158
159
void DataTableView::setCellProperties(const css::uno::Reference<beans::XPropertySet>& xPropertySet,
160
                                      bool bLeft, bool bTop, bool bRight, bool bBottom)
161
0
{
162
0
    xPropertySet->setPropertyValue(u"FillColor"_ustr, uno::Any(Color(0xFFFFFF)));
163
164
0
    float fFontHeight = 0.0;
165
0
    m_xDataTableModel->getPropertyValue(u"CharHeight"_ustr) >>= fFontHeight;
166
0
    fFontHeight = o3tl::convert(fFontHeight, o3tl::Length::pt, o3tl::Length::mm100);
167
0
    sal_Int32 nXDistance = std::round(fFontHeight * 0.18f);
168
0
    sal_Int32 nYDistance = std::round(fFontHeight * 0.30f);
169
170
0
    xPropertySet->setPropertyValue(u"TextLeftDistance"_ustr, uno::Any(nXDistance));
171
0
    xPropertySet->setPropertyValue(u"TextRightDistance"_ustr, uno::Any(nXDistance));
172
0
    xPropertySet->setPropertyValue(u"TextUpperDistance"_ustr, uno::Any(nYDistance));
173
0
    xPropertySet->setPropertyValue(u"TextLowerDistance"_ustr, uno::Any(nYDistance));
174
175
0
    xPropertySet->setPropertyValue(u"TextVerticalAdjust"_ustr,
176
0
                                   uno::Any(drawing::TextVerticalAdjust_TOP));
177
178
0
    drawing::LineStyle eStyle = drawing::LineStyle_NONE;
179
0
    m_aLineProperties.LineStyle >>= eStyle;
180
181
0
    if (eStyle != drawing::LineStyle_NONE)
182
0
    {
183
0
        table::BorderLine2 aBorderLine;
184
185
0
        sal_Int32 nWidth = 0;
186
0
        m_aLineProperties.Width >>= nWidth;
187
0
        aBorderLine.LineWidth = o3tl::convert(nWidth, o3tl::Length::mm100, o3tl::Length::twip);
188
189
0
        sal_Int32 nColor = 0;
190
0
        m_aLineProperties.Color >>= nColor;
191
0
        aBorderLine.Color = nColor;
192
193
0
        aBorderLine.LineStyle = table::BorderLineStyle::SOLID;
194
195
0
        if (eStyle == drawing::LineStyle_DASH)
196
0
        {
197
0
            OUString aDashName;
198
0
            m_aLineProperties.DashName >>= aDashName;
199
0
            if (!aDashName.isEmpty() && m_xChartModel.is())
200
0
            {
201
0
                uno::Reference<container::XNameContainer> xDashTable(
202
0
                    m_xChartModel->createInstance(u"com.sun.star.drawing.DashTable"_ustr),
203
0
                    uno::UNO_QUERY);
204
0
                if (xDashTable.is() && xDashTable->hasByName(aDashName))
205
0
                {
206
0
                    drawing::LineDash aLineDash;
207
0
                    xDashTable->getByName(aDashName) >>= aLineDash;
208
209
0
                    if (aLineDash.Dots == 0 && aLineDash.Dashes == 0)
210
0
                        aBorderLine.LineStyle = table::BorderLineStyle::SOLID;
211
0
                    else if (aLineDash.Dots == 1 && aLineDash.Dashes == 0)
212
0
                        aBorderLine.LineStyle = table::BorderLineStyle::DOTTED;
213
0
                    else if (aLineDash.Dots == 0 && aLineDash.Dashes == 1)
214
0
                        aBorderLine.LineStyle = table::BorderLineStyle::DASHED;
215
0
                    else if (aLineDash.Dots == 1 && aLineDash.Dashes == 1)
216
0
                        aBorderLine.LineStyle = table::BorderLineStyle::DASH_DOT;
217
0
                    else if (aLineDash.Dots == 2 && aLineDash.Dashes == 1)
218
0
                        aBorderLine.LineStyle = table::BorderLineStyle::DASH_DOT_DOT;
219
0
                    else
220
0
                        aBorderLine.LineStyle = table::BorderLineStyle::DASHED;
221
0
                }
222
0
            }
223
0
        }
224
225
0
        if (bLeft)
226
0
            xPropertySet->setPropertyValue(u"LeftBorder"_ustr, uno::Any(aBorderLine));
227
0
        if (bTop)
228
0
            xPropertySet->setPropertyValue(u"TopBorder"_ustr, uno::Any(aBorderLine));
229
0
        if (bRight)
230
0
            xPropertySet->setPropertyValue(u"RightBorder"_ustr, uno::Any(aBorderLine));
231
0
        if (bBottom)
232
0
            xPropertySet->setPropertyValue(u"BottomBorder"_ustr, uno::Any(aBorderLine));
233
0
    }
234
0
}
235
236
void DataTableView::createShapes(basegfx::B2DVector const& rStart, basegfx::B2DVector const& rEnd,
237
                                 sal_Int32 nAxisStepWidth)
238
0
{
239
0
    if (!m_xTarget.is())
240
0
        return;
241
242
    // Remove shapes first before we add the new ones
243
0
    ShapeFactory::removeSubShapes(m_xTarget);
244
0
    auto sParticle = ObjectIdentifier::createParticleForDataTable(m_xChartModel);
245
0
    auto sCID = ObjectIdentifier::createClassifiedIdentifierForParticle(sParticle);
246
0
    m_xTableShape = ShapeFactory::createTable(m_xTarget, sCID);
247
248
    // calculate the table size
249
0
    auto rDelta = rEnd - rStart;
250
0
    sal_Int32 nTableSize = basegfx::fround(rDelta.getX());
251
0
    m_xTableShape->setSize({ nTableSize, 0 });
252
253
0
    try
254
0
    {
255
0
        m_xTableShape->getPropertyValue(u"Model"_ustr) >>= m_xTable;
256
0
    }
257
0
    catch (const uno::Exception&)
258
0
    {
259
0
        return;
260
0
    }
261
262
0
    if (!m_xTable.is())
263
0
        return;
264
265
0
    uno::Reference<util::XBroadcaster> xBroadcaster(m_xTable, uno::UNO_QUERY);
266
267
0
    if (!xBroadcaster.is())
268
0
        return;
269
270
0
    xBroadcaster->lockBroadcasts();
271
272
0
    auto* pTableObject = static_cast<sdr::table::SdrTableObj*>(m_xTableShape->GetSdrObject());
273
274
    // get the data table properties from the model
275
0
    bool bHBorder = false;
276
0
    bool bVBorder = false;
277
0
    bool bOutline = false;
278
0
    bool bKeys = false;
279
280
0
    std::vector<ViewLegendSymbol> aSymbols;
281
282
0
    m_xDataTableModel->getPropertyValue(u"HBorder"_ustr) >>= bHBorder;
283
0
    m_xDataTableModel->getPropertyValue(u"VBorder"_ustr) >>= bVBorder;
284
0
    m_xDataTableModel->getPropertyValue(u"Outline"_ustr) >>= bOutline;
285
0
    m_xDataTableModel->getPropertyValue(u"Keys"_ustr) >>= bKeys;
286
287
    // set the data table row and column size
288
0
    sal_Int32 nColumnCount = m_aXValues.size();
289
0
    uno::Reference<table::XTableColumns> xTableColumns = m_xTable->getColumns();
290
0
    xTableColumns->insertByIndex(0, nColumnCount);
291
292
0
    sal_Int32 nRowCount = m_aDataSeriesNames.size();
293
0
    uno::Reference<table::XTableRows> xTableRows = m_xTable->getRows();
294
0
    xTableRows->insertByIndex(0, nRowCount);
295
296
0
    sal_Int32 nColumnWidth = 0.0;
297
298
    // If we don't align, we have to calculate the column width ourselves,
299
    // otherwise the column width is taken from the x-axis width
300
0
    if (m_bAlignAxisValuesWithColumns)
301
0
        nColumnWidth = nAxisStepWidth;
302
0
    else
303
0
        nColumnWidth = double(nTableSize) / nColumnCount;
304
305
    // Setup empty top-left cell
306
0
    {
307
0
        uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(0, 0);
308
0
        uno::Reference<beans::XPropertySet> xPropertySet(xCell, uno::UNO_QUERY);
309
0
        if (xPropertySet.is())
310
0
        {
311
0
            setTopCell(xPropertySet);
312
0
        }
313
0
    }
314
315
0
    sal_Int32 nColumn;
316
0
    sal_Int32 nRow;
317
318
    // COLUMN HEADER
319
320
0
    nColumn = 1;
321
0
    for (auto const& rString : m_aXValues)
322
0
    {
323
0
        uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(nColumn, 0);
324
0
        uno::Reference<beans::XPropertySet> xPropertySet(xCell, uno::UNO_QUERY);
325
0
        uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY);
326
0
        if (xCellTextRange.is())
327
0
        {
328
0
            auto xText = xCellTextRange->getText();
329
0
            xText->insertString(xText->getStart(), rString, false);
330
0
            auto xTextPropertySet = getFirstParagraphProperties(xText);
331
0
            if (xTextPropertySet)
332
0
            {
333
0
                bool bLeft = (bOutline && nColumn == 1)
334
0
                             || (bVBorder && nColumn > 1 && nColumn < nColumnCount);
335
0
                bool bRight = (bOutline && nColumn == nColumnCount)
336
0
                              || (bVBorder && nColumn > 1 && nColumn < nColumnCount);
337
0
                setCellCharAndParagraphProperties(xTextPropertySet);
338
0
                setCellProperties(xPropertySet, bLeft, bOutline, bRight, bOutline);
339
0
            }
340
0
        }
341
0
        nColumn++;
342
0
    }
343
344
    // ROW HEADER
345
    // Prepare keys (symbols)
346
0
    sal_Int32 nMaxSymbolWidth = 0;
347
0
    constexpr const sal_Int32 constSymbolMargin = 100; // 1mm
348
0
    if (bKeys)
349
0
    {
350
0
        float fFontHeight = 0.0;
351
0
        m_xDataTableModel->getPropertyValue(u"CharHeight"_ustr) >>= fFontHeight;
352
0
        fFontHeight = o3tl::convert(fFontHeight, o3tl::Length::pt, o3tl::Length::mm100);
353
354
0
        sal_Int32 nSymbolHeight = sal_Int32(fFontHeight * 0.6);
355
0
        sal_Int32 nSymbolWidth = nSymbolHeight;
356
357
0
        for (VSeriesPlotter* pSeriesPlotter : m_pSeriesPlotterList)
358
0
        {
359
0
            if (pSeriesPlotter)
360
0
            {
361
0
                awt::Size aCurrentRatio = pSeriesPlotter->getPreferredLegendKeyAspectRatio();
362
0
                sal_Int32 nCurrentWidth = aCurrentRatio.Width;
363
0
                if (aCurrentRatio.Height > 0)
364
0
                    nCurrentWidth = nSymbolHeight * aCurrentRatio.Width / aCurrentRatio.Height;
365
0
                nSymbolWidth = std::max(nSymbolWidth, nCurrentWidth);
366
0
            }
367
0
        }
368
0
        nMaxSymbolWidth = nSymbolWidth;
369
370
0
        for (VSeriesPlotter* pSeriesPlotter : m_pSeriesPlotterList)
371
0
        {
372
0
            if (pSeriesPlotter)
373
0
            {
374
0
                awt::Size aSize(nSymbolWidth, nSymbolHeight);
375
0
                std::vector<ViewLegendSymbol> aNewEntries
376
0
                    = pSeriesPlotter->createSymbols(aSize, m_xTarget, m_xComponentContext);
377
378
0
                for (auto const& rSymbol : aNewEntries)
379
0
                    aSymbols.push_back(rSymbol);
380
0
            }
381
0
        }
382
0
    }
383
384
0
    nRow = 1;
385
0
    for (auto const& rSeriesName : m_aDataSeriesNames)
386
0
    {
387
0
        uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(0, nRow);
388
0
        uno::Reference<beans::XPropertySet> xCellPropertySet(xCell, uno::UNO_QUERY);
389
0
        uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY);
390
0
        if (xCellTextRange.is())
391
0
        {
392
0
            bool bTop = (bOutline && nRow == 1) || (bHBorder && nRow > 1 && nRow < nRowCount);
393
0
            bool bBottom
394
0
                = (bOutline && nRow == nRowCount) || (bHBorder && nRow > 1 && nRow < nRowCount);
395
396
0
            auto xText = xCellTextRange->getText();
397
0
            xText->insertString(xText->getStart(), rSeriesName, false);
398
0
            auto xTextPropertySet = getFirstParagraphProperties(xText);
399
0
            if (xTextPropertySet)
400
0
            {
401
0
                setCellCharAndParagraphProperties(xTextPropertySet);
402
0
                setCellProperties(xCellPropertySet, bOutline, bTop, bOutline, bBottom);
403
404
0
                xCellPropertySet->setPropertyValue(u"ParaAdjust"_ustr,
405
0
                                                   uno::Any(style::ParagraphAdjust_LEFT));
406
0
                if (bKeys)
407
0
                {
408
0
                    xCellPropertySet->setPropertyValue(
409
0
                        u"ParaLeftMargin"_ustr,
410
0
                        uno::Any(nMaxSymbolWidth + sal_Int32(2 * constSymbolMargin)));
411
0
                }
412
0
            }
413
0
        }
414
0
        nRow++;
415
0
    }
416
417
    // TABLE
418
0
    nRow = 1;
419
0
    const sal_Int32 nTableModelRowCount = m_xTable->getRowCount();
420
0
    const sal_Int32 nTableModelColCount = m_xTable->getColumnCount();
421
    // tdf#153182 the broken bounds are most likely because we don't know if the
422
    // data-table has header rows and columns. Most likely it does not.
423
0
    bool bBrokenBounds = false;
424
0
    for (auto const& rSeries : m_pDataSeriesValues)
425
0
    {
426
0
        nColumn = 1;
427
0
        for (auto const& rValue : rSeries)
428
0
        {
429
0
            if (nRow >= nTableModelRowCount || nColumn >= nTableModelColCount)
430
0
            {
431
0
                bBrokenBounds = true;
432
0
                SAL_WARN("chart2", "exceeding bounds of table model?");
433
0
                break;
434
0
            }
435
0
            uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(nColumn, nRow);
436
0
            uno::Reference<beans::XPropertySet> xCellPropertySet(xCell, uno::UNO_QUERY);
437
0
            uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY);
438
0
            if (xCellTextRange.is())
439
0
            {
440
0
                auto xText = xCellTextRange->getText();
441
0
                xText->insertString(xText->getStart(), rValue, false);
442
0
                auto xTextPropertySet = getFirstParagraphProperties(xText);
443
0
                if (xTextPropertySet.is())
444
0
                {
445
0
                    bool bLeft = false;
446
0
                    bool bTop = false;
447
0
                    bool bRight = false;
448
0
                    bool bBottom = false;
449
450
0
                    if (nColumn > 1 && bVBorder)
451
0
                        bLeft = true;
452
453
0
                    if (nRow > 1 && bHBorder)
454
0
                        bTop = true;
455
456
0
                    if (nRow == nRowCount && bOutline)
457
0
                        bBottom = true;
458
459
0
                    if (nColumn == nColumnCount && bOutline)
460
0
                        bRight = true;
461
462
0
                    setCellCharAndParagraphProperties(xTextPropertySet);
463
0
                    setCellProperties(xCellPropertySet, bLeft, bTop, bRight, bBottom);
464
0
                }
465
0
            }
466
0
            nColumn++;
467
0
        }
468
0
        if (bBrokenBounds)
469
0
            break;
470
0
        nRow++;
471
0
    }
472
473
    // force recalculation of column widths in the table shape
474
0
    xBroadcaster->unlockBroadcasts();
475
0
    pTableObject->DistributeColumns(0, nColumnCount, true, true);
476
477
0
    xBroadcaster->lockBroadcasts();
478
479
    // reposition the data table
480
0
    changePosition(basegfx::fround(rStart.getX()), basegfx::fround(rStart.getY()));
481
482
0
    sal_Int32 nTableX = m_xTableShape->getPosition().X;
483
0
    sal_Int32 nTableY = m_xTableShape->getPosition().Y;
484
485
0
    uno::Reference<beans::XPropertySet> xPropertySet(xTableColumns->getByIndex(0), uno::UNO_QUERY);
486
487
0
    for (sal_Int32 i = 1; i < xTableColumns->getCount(); ++i)
488
0
    {
489
0
        xPropertySet.set(xTableColumns->getByIndex(i), uno::UNO_QUERY);
490
0
        xPropertySet->setPropertyValue(u"Width"_ustr, uno::Any(nColumnWidth));
491
0
    }
492
493
    // force recalculation of row heights in the table shape
494
0
    xBroadcaster->unlockBroadcasts();
495
0
    pTableObject->DistributeRows(0, nRowCount, true, true);
496
497
0
    if (bKeys)
498
0
    {
499
0
        sal_Int32 nTotalHeight = 0;
500
0
        for (sal_Int32 i = 0; i < xTableRows->getCount(); i++)
501
0
        {
502
0
            sal_Int32 nSymbolIndex = i - 1;
503
0
            if (nSymbolIndex < sal_Int32(aSymbols.size()))
504
0
            {
505
0
                xPropertySet.set(xTableRows->getByIndex(i), uno::UNO_QUERY);
506
0
                sal_Int32 nHeight = 0;
507
0
                xPropertySet->getPropertyValue(u"Height"_ustr) >>= nHeight;
508
0
                if (i > 0)
509
0
                {
510
0
                    auto& rSymbol = aSymbols[nSymbolIndex].xSymbol;
511
0
                    sal_Int32 nSymbolHeight = rSymbol->getSize().Height;
512
0
                    sal_Int32 nSymbolY
513
0
                        = basegfx::fround(double(nHeight) / 2.0 - double(nSymbolHeight) / 2.0);
514
0
                    rSymbol->setPosition(
515
0
                        { nTableX + constSymbolMargin, nTableY + nTotalHeight + nSymbolY });
516
0
                }
517
0
                nTotalHeight += nHeight;
518
0
            }
519
0
        }
520
0
    }
521
0
}
522
523
void DataTableView::changePosition(sal_Int32 x, sal_Int32 y)
524
0
{
525
0
    if (!m_xTable.is())
526
0
        return;
527
528
0
    uno::Reference<table::XTableColumns> xTableColumns = m_xTable->getColumns();
529
0
    uno::Reference<beans::XPropertySet> xPropertySet(xTableColumns->getByIndex(0), uno::UNO_QUERY);
530
531
0
    sal_Int32 nWidth = 0;
532
0
    xPropertySet->getPropertyValue(u"Width"_ustr) >>= nWidth;
533
534
0
    m_xTarget->setPosition({ x - nWidth, y });
535
0
}
536
537
void DataTableView::initializeShapes(const rtl::Reference<SvxShapeGroupAnyD>& xTarget)
538
0
{
539
0
    m_xTarget = xTarget;
540
0
}
541
542
void DataTableView::initializeValues(
543
    std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList)
544
0
{
545
0
    for (auto& rSeriesPlotter : rSeriesPlotterList)
546
0
    {
547
0
        m_pSeriesPlotterList.push_back(rSeriesPlotter.get());
548
549
0
        for (auto const& rCategory :
550
0
             rSeriesPlotter->getExplicitCategoriesProvider()->getSimpleCategories())
551
0
        {
552
0
            m_aXValues.push_back(rCategory);
553
0
        }
554
555
0
        for (auto const& rString : rSeriesPlotter->getAllSeriesNames())
556
0
        {
557
0
            m_aDataSeriesNames.push_back(rString);
558
0
        }
559
560
0
        for (VDataSeries* pSeries : rSeriesPlotter->getAllSeries())
561
0
        {
562
0
            auto& rValues = m_pDataSeriesValues.emplace_back();
563
0
            for (int i = 0; i < pSeries->getTotalPointCount(); i++)
564
0
            {
565
0
                double nValue = pSeries->getYValue(i);
566
0
                rValues.push_back(rSeriesPlotter->getLabelTextForValue(*pSeries, i, nValue, false));
567
0
            }
568
0
        }
569
0
    }
570
0
}
571
572
} //namespace chart
573
574
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */