Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/tools/DiagramHelper.cxx
Line
Count
Source
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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <DiagramHelper.hxx>
21
#include <Diagram.hxx>
22
#include <DataSeries.hxx>
23
#include <DataSeriesHelper.hxx>
24
#include <Axis.hxx>
25
#include <AxisHelper.hxx>
26
#include <ChartType.hxx>
27
#include <ChartModel.hxx>
28
#include <ExplicitCategoriesProvider.hxx>
29
#include <RelativePositionHelper.hxx>
30
#include <ControllerLockGuard.hxx>
31
#include <NumberFormatterWrapper.hxx>
32
#include <unonames.hxx>
33
#include <BaseCoordinateSystem.hxx>
34
35
#include <com/sun/star/chart/XDiagramPositioning.hpp>
36
#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
37
#include <com/sun/star/chart2/AxisType.hpp>
38
#include <com/sun/star/chart2/RelativePosition.hpp>
39
#include <com/sun/star/chart2/RelativeSize.hpp>
40
#include <com/sun/star/chart2/StackingDirection.hpp>
41
42
#include <com/sun/star/util/NumberFormat.hpp>
43
44
#include <unotools/saveopt.hxx>
45
#include <svl/numformat.hxx>
46
#include <svl/zforlist.hxx>
47
#include <vcl/svapp.hxx>
48
#include <vcl/settings.hxx>
49
#include <comphelper/sequence.hxx>
50
#include <comphelper/diagnose_ex.hxx>
51
#include <sal/log.hxx>
52
53
#include <limits>
54
55
using namespace ::com::sun::star;
56
using namespace ::com::sun::star::chart2;
57
58
using ::com::sun::star::uno::Reference;
59
using ::com::sun::star::uno::Sequence;
60
using ::com::sun::star::uno::Any;
61
using ::com::sun::star::chart2::XAnyDescriptionAccess;
62
63
namespace chart
64
{
65
66
StackMode DiagramHelper::getStackModeFromChartType(
67
    const rtl::Reference< ChartType > & xChartType,
68
    bool& rbFound, bool& rbAmbiguous,
69
    const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem )
70
0
{
71
0
    StackMode eStackMode = StackMode::NONE;
72
0
    rbFound = false;
73
0
    rbAmbiguous = false;
74
75
0
    try
76
0
    {
77
0
        const std::vector< rtl::Reference< DataSeries > > & aSeries = xChartType->getDataSeries2();
78
79
0
        chart2::StackingDirection eCommonDirection = chart2::StackingDirection_NO_STACKING;
80
0
        bool bDirectionInitialized = false;
81
82
        // first series is irrelevant for stacking, start with second, unless
83
        // there is only one series
84
0
        const sal_Int32 nSeriesCount = aSeries.size();
85
0
        sal_Int32 i = (nSeriesCount == 1) ? 0: 1;
86
0
        for( ; i<nSeriesCount; ++i )
87
0
        {
88
0
            rbFound = true;
89
0
            chart2::StackingDirection eCurrentDirection = eCommonDirection;
90
            // property is not MAYBEVOID
91
0
            bool bSuccess = ( aSeries[i]->getPropertyValue( u"StackingDirection"_ustr ) >>= eCurrentDirection );
92
0
            OSL_ASSERT( bSuccess );
93
0
            if( ! bDirectionInitialized )
94
0
            {
95
0
                eCommonDirection = eCurrentDirection;
96
0
                bDirectionInitialized = true;
97
0
            }
98
0
            else
99
0
            {
100
0
                if( eCommonDirection != eCurrentDirection )
101
0
                {
102
0
                    rbAmbiguous = true;
103
0
                    break;
104
0
                }
105
0
            }
106
0
        }
107
108
0
        if( rbFound )
109
0
        {
110
0
            if( eCommonDirection == chart2::StackingDirection_Z_STACKING )
111
0
                eStackMode = StackMode::ZStacked;
112
0
            else if( eCommonDirection == chart2::StackingDirection_Y_STACKING )
113
0
            {
114
0
                eStackMode = StackMode::YStacked;
115
116
                // percent stacking
117
0
                if( xCorrespondingCoordinateSystem.is() )
118
0
                {
119
0
                    if( 1 < xCorrespondingCoordinateSystem->getDimension() )
120
0
                    {
121
0
                        sal_Int32 nAxisIndex = 0;
122
0
                        if( nSeriesCount )
123
0
                            nAxisIndex = aSeries[0]->getAttachedAxisIndex();
124
125
0
                        rtl::Reference< Axis > xAxis =
126
0
                            xCorrespondingCoordinateSystem->getAxisByDimension2( 1,nAxisIndex );
127
0
                        if( xAxis.is())
128
0
                        {
129
0
                            chart2::ScaleData aScaleData = xAxis->getScaleData();
130
0
                            if( aScaleData.AxisType==chart2::AxisType::PERCENT )
131
0
                                eStackMode = StackMode::YStackedPercent;
132
0
                        }
133
0
                    }
134
0
                }
135
0
            }
136
0
        }
137
0
    }
138
0
    catch( const uno::Exception & )
139
0
    {
140
0
        DBG_UNHANDLED_EXCEPTION("chart2");
141
0
    }
142
143
0
    return eStackMode;
144
0
}
145
146
static void lcl_generateAutomaticCategoriesFromChartType(
147
            Sequence< OUString >& rRet,
148
            const rtl::Reference< ChartType >& xChartType )
149
0
{
150
0
    if(!xChartType.is())
151
0
        return;
152
0
    OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() );
153
154
0
    const std::vector< rtl::Reference< DataSeries > > & aSeriesSeq = xChartType->getDataSeries2();
155
0
    for( rtl::Reference< DataSeries > const & dataSeries : aSeriesSeq )
156
0
    {
157
0
        uno::Reference< data::XLabeledDataSequence > xLabeledSeq =
158
0
            ::chart::DataSeriesHelper::getDataSequenceByRole( dataSeries, aMainSeq );
159
0
        if( !xLabeledSeq.is() )
160
0
            continue;
161
0
        Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
162
0
        if( !xValueSeq.is() )
163
0
            continue;
164
0
        rRet = xValueSeq->generateLabel( chart2::data::LabelOrigin_LONG_SIDE );
165
0
        if( rRet.hasElements() )
166
0
            return;
167
0
    }
168
0
}
169
170
Sequence< OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const rtl::Reference< BaseCoordinateSystem > & xCooSys )
171
0
{
172
0
    Sequence< OUString > aRet;
173
174
0
    if( xCooSys.is() )
175
0
    {
176
0
        const std::vector< rtl::Reference< ChartType > > & aChartTypes( xCooSys->getChartTypes2() );
177
0
        for( rtl::Reference< ChartType > const & chartType : aChartTypes )
178
0
        {
179
0
            lcl_generateAutomaticCategoriesFromChartType( aRet, chartType );
180
0
            if( aRet.hasElements() )
181
0
                return aRet;
182
0
        }
183
0
    }
184
0
    return aRet;
185
0
}
186
187
Sequence< OUString > DiagramHelper::getExplicitSimpleCategories(
188
            ChartModel& rModel )
189
0
{
190
0
    rtl::Reference< BaseCoordinateSystem > xCooSys( rModel.getFirstCoordinateSystem() );
191
0
    ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel );
192
0
    return aExplicitCategoriesProvider.getSimpleCategories();
193
0
}
194
195
namespace
196
{
197
void lcl_switchToDateCategories( const rtl::Reference< ChartModel >& xChartDoc, const Reference< XAxis >& xAxis )
198
0
{
199
0
    if( !xAxis.is() )
200
0
        return;
201
0
    if( !xChartDoc.is() )
202
0
        return;
203
204
0
    ScaleData aScale( xAxis->getScaleData() );
205
0
    if( xChartDoc->hasInternalDataProvider() )
206
0
    {
207
        //remove all content the is not of type double and remove multiple level
208
0
        Reference< XAnyDescriptionAccess > xDataAccess( xChartDoc->getDataProvider(), uno::UNO_QUERY );
209
0
        if( xDataAccess.is() )
210
0
        {
211
0
            Sequence< Sequence< Any > > aAnyCategories( xDataAccess->getAnyRowDescriptions() );
212
0
            auto aAnyCategoriesRange = asNonConstRange(aAnyCategories);
213
0
            double fTest = 0.0;
214
0
            sal_Int32 nN = aAnyCategories.getLength();
215
0
            for( ; nN--; )
216
0
            {
217
0
                Sequence< Any >& rCat = aAnyCategoriesRange[nN];
218
0
                if( rCat.getLength() > 1 )
219
0
                    rCat.realloc(1);
220
0
                if( rCat.getLength() == 1 )
221
0
                {
222
0
                    Any& rAny = rCat.getArray()[0];
223
0
                    if( !(rAny>>=fTest) )
224
0
                    {
225
0
                        rAny <<= std::numeric_limits<double>::quiet_NaN();
226
0
                    }
227
0
                }
228
0
            }
229
0
            xDataAccess->setAnyRowDescriptions( aAnyCategories );
230
0
        }
231
        //check the numberformat at the axis
232
0
        Reference< beans::XPropertySet > xAxisProps( xAxis, uno::UNO_QUERY );
233
0
        if( xAxisProps.is() )
234
0
        {
235
0
            sal_Int32 nNumberFormat = -1;
236
0
            xAxisProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
237
238
0
            Reference< util::XNumberFormats > xNumberFormats( xChartDoc->getNumberFormats() );
239
0
            if( xNumberFormats.is() )
240
0
            {
241
0
                Reference< beans::XPropertySet > xKeyProps;
242
0
                try
243
0
                {
244
0
                    xKeyProps = xNumberFormats->getByKey( nNumberFormat );
245
0
                }
246
0
                catch( const uno::Exception & )
247
0
                {
248
0
                    DBG_UNHANDLED_EXCEPTION("chart2");
249
0
                }
250
0
                sal_Int32 nType = util::NumberFormat::UNDEFINED;
251
0
                if( xKeyProps.is() )
252
0
                    xKeyProps->getPropertyValue( u"Type"_ustr ) >>= nType;
253
0
                if( !( nType & util::NumberFormat::DATE ) )
254
0
                {
255
                    //set a date format to the axis
256
0
                    const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
257
0
                    Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE,  rLocaleDataWrapper.getLanguageTag().getLocale(), true/*bCreate*/ );
258
0
                    if( aKeySeq.hasElements() )
259
0
                    {
260
0
                        xAxisProps->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any(aKeySeq[0]));
261
0
                    }
262
0
                }
263
0
            }
264
0
        }
265
0
    }
266
0
    if( aScale.AxisType != chart2::AxisType::DATE )
267
0
        AxisHelper::removeExplicitScaling( aScale );
268
0
    aScale.AxisType = chart2::AxisType::DATE;
269
0
    xAxis->setScaleData( aScale );
270
0
}
271
272
void lcl_switchToTextCategories( const rtl::Reference< ChartModel >& xChartDoc, const Reference< XAxis >& xAxis )
273
0
{
274
0
    if( !xAxis.is() )
275
0
        return;
276
0
    if( !xChartDoc.is() )
277
0
        return;
278
0
    ScaleData aScale( xAxis->getScaleData() );
279
0
    if( aScale.AxisType != chart2::AxisType::CATEGORY )
280
0
        AxisHelper::removeExplicitScaling( aScale );
281
    //todo migrate dates to text?
282
0
    aScale.AxisType = chart2::AxisType::CATEGORY;
283
0
    aScale.AutoDateAxis = false;
284
0
    xAxis->setScaleData( aScale );
285
0
}
286
287
}
288
289
void DiagramHelper::switchToDateCategories( const rtl::Reference<::chart::ChartModel>& xChartDoc )
290
0
{
291
0
    if(xChartDoc.is())
292
0
    {
293
0
        ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
294
295
0
        rtl::Reference< BaseCoordinateSystem > xCooSys = xChartDoc->getFirstCoordinateSystem();
296
0
        if( xCooSys.is() )
297
0
        {
298
0
            rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(0,0);
299
0
            lcl_switchToDateCategories( xChartDoc, xAxis );
300
0
        }
301
0
    }
302
0
}
303
304
void DiagramHelper::switchToTextCategories( const rtl::Reference<::chart::ChartModel>& xChartDoc )
305
0
{
306
0
    if(xChartDoc.is())
307
0
    {
308
0
        ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
309
310
0
        rtl::Reference< BaseCoordinateSystem > xCooSys = xChartDoc->getFirstCoordinateSystem();
311
0
        if( xCooSys.is() )
312
0
        {
313
0
            rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(0,0);
314
0
            lcl_switchToTextCategories( xChartDoc, xAxis );
315
0
        }
316
0
    }
317
0
}
318
319
bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat, const css::uno::Reference< css::util::XNumberFormats >& xNumberFormats )
320
0
{
321
0
    bool bIsDate = false;
322
0
    if( !xNumberFormats.is() )
323
0
        return bIsDate;
324
325
0
    Reference< beans::XPropertySet > xKeyProps = xNumberFormats->getByKey( nNumberFormat );
326
0
    if( xKeyProps.is() )
327
0
    {
328
0
        sal_Int32 nType = util::NumberFormat::UNDEFINED;
329
0
        xKeyProps->getPropertyValue( u"Type"_ustr ) >>= nType;
330
0
        bIsDate = nType & util::NumberFormat::DATE;
331
0
    }
332
0
    return bIsDate;
333
0
}
334
335
sal_Int32 DiagramHelper::getDateNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
336
0
{
337
0
    sal_Int32 nRet=-1;
338
339
    //try to get a date format with full year display
340
0
    const LanguageTag& rLanguageTag = Application::GetSettings().GetLanguageTag();
341
0
    NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
342
0
    SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
343
0
    if( pNumFormatter )
344
0
    {
345
0
        nRet = pNumFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, rLanguageTag.getLanguageType() );
346
0
    }
347
0
    else
348
0
    {
349
0
        Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
350
0
        if( xNumberFormats.is() )
351
0
        {
352
0
            Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE,
353
0
                    rLanguageTag.getLocale(), true/*bCreate */);
354
0
            if( aKeySeq.hasElements() )
355
0
            {
356
0
                nRet = aKeySeq[0];
357
0
            }
358
0
        }
359
0
    }
360
0
    return nRet;
361
0
}
362
363
sal_Int32 DiagramHelper::getDateTimeInputNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier, double fNumber )
364
0
{
365
0
    sal_Int32 nRet = 0;
366
367
    // Get the most detailed date/time format according to fNumber.
368
0
    NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
369
0
    SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
370
0
    if (!pNumFormatter)
371
0
        SAL_WARN("chart2", "DiagramHelper::getDateTimeInputNumberFormat - no SvNumberFormatter");
372
0
    else
373
0
    {
374
0
        SvNumFormatType nType;
375
        // Obtain best matching date, time or datetime format.
376
0
        nRet = pNumFormatter->GuessDateTimeFormat( nType, fNumber, LANGUAGE_SYSTEM);
377
        // Obtain the corresponding edit format.
378
0
        nRet = pNumFormatter->GetEditFormat( fNumber, nRet, nType, nullptr);
379
0
    }
380
0
    return nRet;
381
0
}
382
383
sal_Int32 DiagramHelper::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
384
0
{
385
0
    sal_Int32 nRet=-1;
386
0
    const LanguageTag& rLanguageTag = Application::GetSettings().GetLanguageTag();
387
0
    NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
388
0
    SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
389
0
    if( pNumFormatter )
390
0
    {
391
0
        nRet = pNumFormatter->GetFormatIndex( NF_PERCENT_INT, rLanguageTag.getLanguageType() );
392
0
    }
393
0
    else
394
0
    {
395
0
        Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
396
0
        if( xNumberFormats.is() )
397
0
        {
398
0
            Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
399
0
                    rLanguageTag.getLocale(), true/*bCreate*/ );
400
0
            if( aKeySeq.hasElements() )
401
0
            {
402
                // This *assumes* the sequence is sorted as in
403
                // NfIndexTableOffset and the first format is the integer 0%
404
                // format by chance... which usually is the case, but... anyway,
405
                // we usually also have a number formatter so don't reach here.
406
0
                nRet = aKeySeq[0];
407
0
            }
408
0
        }
409
0
    }
410
0
    return nRet;
411
0
}
412
413
bool DiagramHelper::areChartTypesCompatible( const rtl::Reference< ChartType >& xFirstType,
414
                const rtl::Reference< ChartType >& xSecondType )
415
0
{
416
0
    if( !xFirstType.is() || !xSecondType.is() )
417
0
        return false;
418
419
0
    auto aFirstRoles( comphelper::sequenceToContainer<std::vector< OUString >>( xFirstType->getSupportedMandatoryRoles() ) );
420
0
    auto aSecondRoles( comphelper::sequenceToContainer<std::vector< OUString >>( xSecondType->getSupportedMandatoryRoles() ) );
421
0
    std::sort( aFirstRoles.begin(), aFirstRoles.end() );
422
0
    std::sort( aSecondRoles.begin(), aSecondRoles.end() );
423
0
    return ( aFirstRoles == aSecondRoles );
424
0
}
425
426
static void lcl_ensureRange0to1( double& rValue )
427
0
{
428
0
    if(rValue<0.0)
429
0
        rValue=0.0;
430
0
    if(rValue>1.0)
431
0
        rValue=1.0;
432
0
}
433
434
bool DiagramHelper::setDiagramPositioning( const rtl::Reference<::chart::ChartModel>& xChartModel,
435
        const awt::Rectangle& rPosRect /*100th mm*/ )
436
0
{
437
0
    ControllerLockGuardUNO aCtrlLockGuard( xChartModel );
438
439
0
    bool bChanged = false;
440
0
    awt::Size aPageSize( xChartModel->getPageSize() );
441
0
    rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
442
0
    if( !xDiagram.is() )
443
0
        return bChanged;
444
445
0
    RelativePosition aOldPos;
446
0
    RelativeSize aOldSize;
447
0
    xDiagram->getPropertyValue(u"RelativePosition"_ustr ) >>= aOldPos;
448
0
    xDiagram->getPropertyValue(u"RelativeSize"_ustr ) >>= aOldSize;
449
450
0
    RelativePosition aNewPos;
451
0
    aNewPos.Anchor = drawing::Alignment_TOP_LEFT;
452
0
    aNewPos.Primary = double(rPosRect.X)/double(aPageSize.Width);
453
0
    aNewPos.Secondary = double(rPosRect.Y)/double(aPageSize.Height);
454
455
0
    chart2::RelativeSize aNewSize;
456
0
    aNewSize.Primary = double(rPosRect.Width)/double(aPageSize.Width);
457
0
    aNewSize.Secondary = double(rPosRect.Height)/double(aPageSize.Height);
458
459
0
    lcl_ensureRange0to1( aNewPos.Primary );
460
0
    lcl_ensureRange0to1( aNewPos.Secondary );
461
0
    lcl_ensureRange0to1( aNewSize.Primary );
462
0
    lcl_ensureRange0to1( aNewSize.Secondary );
463
0
    if( (aNewPos.Primary + aNewSize.Primary) > 1.0 )
464
0
        aNewPos.Primary = 1.0 - aNewSize.Primary;
465
0
    if( (aNewPos.Secondary + aNewSize.Secondary) > 1.0 )
466
0
        aNewPos.Secondary = 1.0 - aNewSize.Secondary;
467
468
0
    xDiagram->setPropertyValue( u"RelativePosition"_ustr, uno::Any(aNewPos) );
469
0
    xDiagram->setPropertyValue( u"RelativeSize"_ustr, uno::Any(aNewSize) );
470
471
0
    bChanged = (aOldPos.Anchor!=aNewPos.Anchor) ||
472
0
        (aOldPos.Primary!=aNewPos.Primary) ||
473
0
        (aOldPos.Secondary!=aNewPos.Secondary) ||
474
0
        (aOldSize.Primary!=aNewSize.Primary) ||
475
0
        (aOldSize.Secondary!=aNewSize.Secondary);
476
0
    return bChanged;
477
0
}
478
479
awt::Rectangle DiagramHelper::getDiagramRectangleFromModel( const rtl::Reference<::chart::ChartModel>& xChartModel )
480
0
{
481
0
    awt::Rectangle aRet(-1,-1,-1,-1);
482
483
0
    rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
484
0
    if( !xDiagram.is() )
485
0
        return aRet;
486
487
0
    awt::Size aPageSize( xChartModel->getPageSize() );
488
489
0
    RelativePosition aRelPos;
490
0
    RelativeSize aRelSize;
491
0
    xDiagram->getPropertyValue(u"RelativePosition"_ustr ) >>= aRelPos;
492
0
    xDiagram->getPropertyValue(u"RelativeSize"_ustr ) >>= aRelSize;
493
494
0
    awt::Size aAbsSize(
495
0
        static_cast< sal_Int32 >( aRelSize.Primary * aPageSize.Width ),
496
0
        static_cast< sal_Int32 >( aRelSize.Secondary * aPageSize.Height ));
497
498
0
    awt::Point aAbsPos(
499
0
        static_cast< sal_Int32 >( aRelPos.Primary * aPageSize.Width ),
500
0
        static_cast< sal_Int32 >( aRelPos.Secondary * aPageSize.Height ));
501
502
0
    awt::Point aAbsPosLeftTop = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos, aAbsSize, aRelPos.Anchor );
503
504
0
    aRet = awt::Rectangle(aAbsPosLeftTop.X, aAbsPosLeftTop.Y, aAbsSize.Width, aAbsSize.Height );
505
506
0
    return aRet;
507
0
}
508
509
bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
510
    ChartModel& rModel, bool bResetModifiedState, bool bConvertAlsoFromAutoPositioning )
511
0
{
512
    //return true if something was changed
513
0
    const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(GetODFSaneDefaultVersion());
514
0
    if (SvtSaveOptions::ODFSVER_012 < nCurrentODFVersion)
515
0
    {
516
0
        uno::Reference< css::chart::XDiagramPositioning > xDiagramPositioning( rModel.getFirstDiagram(), uno::UNO_QUERY );
517
0
        if( xDiagramPositioning.is() && ( bConvertAlsoFromAutoPositioning || !xDiagramPositioning->isAutomaticDiagramPositioning() )
518
0
                && !xDiagramPositioning->isExcludingDiagramPositioning() )
519
0
        {
520
0
            ControllerLockGuard aCtrlLockGuard( rModel );
521
0
            bool bModelWasModified = rModel.isModified();
522
0
            xDiagramPositioning->setDiagramPositionExcludingAxes( xDiagramPositioning->calculateDiagramPositionExcludingAxes() );
523
0
            if(bResetModifiedState && !bModelWasModified )
524
0
                rModel.setModified(false);
525
0
            return true;
526
0
        }
527
0
    }
528
0
    return false;
529
0
}
530
531
} //  namespace chart
532
533
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */