Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/unodraw/gluepts.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 <com/sun/star/container/NoSuchElementException.hpp>
21
#include <com/sun/star/container/XIdentifierContainer.hpp>
22
#include <com/sun/star/container/XIndexContainer.hpp>
23
#include <com/sun/star/drawing/GluePoint2.hpp>
24
#include <com/sun/star/lang/IllegalArgumentException.hpp>
25
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26
27
#include <cppuhelper/implbase.hxx>
28
#include <unotools/weakref.hxx>
29
30
#include <svx/svdobj.hxx>
31
#include <svx/svdglue.hxx>
32
33
#include "gluepts.hxx"
34
35
using namespace ::com::sun::star;
36
using namespace ::cppu;
37
38
const sal_uInt16 NON_USER_DEFINED_GLUE_POINTS = 4;
39
40
namespace {
41
42
class SvxUnoGluePointAccess : public WeakImplHelper< container::XIndexContainer, container::XIdentifierContainer >
43
{
44
private:
45
    unotools::WeakReference<SdrObject>    mpObject;
46
47
public:
48
    explicit SvxUnoGluePointAccess( SdrObject* pObject ) noexcept;
49
50
    // XIdentifierContainer
51
    virtual sal_Int32 SAL_CALL insert( const uno::Any& aElement ) override;
52
    virtual void SAL_CALL removeByIdentifier( sal_Int32 Identifier ) override;
53
54
    // XIdentifierReplace
55
    virtual void SAL_CALL replaceByIdentifer( sal_Int32 Identifier, const uno::Any& aElement ) override;
56
57
    // XIdentifierReplace
58
    virtual uno::Any SAL_CALL getByIdentifier( sal_Int32 Identifier ) override;
59
    virtual uno::Sequence< sal_Int32 > SAL_CALL getIdentifiers(  ) override;
60
61
    /* deprecated */
62
    // XIndexContainer
63
    virtual void SAL_CALL insertByIndex( sal_Int32 Index, const uno::Any& Element ) override;
64
    virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override;
65
66
    /* deprecated */
67
    // XIndexReplace
68
    virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const uno::Any& Element ) override;
69
70
    /* deprecated */
71
    // XIndexAccess
72
    virtual sal_Int32 SAL_CALL getCount(  ) override;
73
    virtual uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override;
74
75
    // XElementAccess
76
    virtual uno::Type SAL_CALL getElementType(  ) override;
77
    virtual sal_Bool SAL_CALL hasElements(  ) override;
78
};
79
80
}
81
82
static void convert( const SdrGluePoint& rSdrGlue, drawing::GluePoint2& rUnoGlue ) noexcept
83
8
{
84
8
    rUnoGlue.Position.X = rSdrGlue.GetPos().X();
85
8
    rUnoGlue.Position.Y = rSdrGlue.GetPos().Y();
86
8
    rUnoGlue.IsRelative = rSdrGlue.IsPercent();
87
88
8
    SdrAlign eAlign = rSdrGlue.GetAlign();
89
8
    if (eAlign == (SdrAlign::VERT_TOP|SdrAlign::HORZ_LEFT))
90
0
        rUnoGlue.PositionAlignment = drawing::Alignment_TOP_LEFT;
91
8
    else if (eAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_TOP))
92
0
        rUnoGlue.PositionAlignment = drawing::Alignment_TOP;
93
8
    else if (eAlign == (SdrAlign::VERT_TOP|SdrAlign::HORZ_RIGHT))
94
0
        rUnoGlue.PositionAlignment = drawing::Alignment_TOP_RIGHT;
95
8
    else if (eAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER))
96
8
        rUnoGlue.PositionAlignment = drawing::Alignment_CENTER;
97
0
    else if (eAlign == (SdrAlign::HORZ_RIGHT|SdrAlign::VERT_CENTER))
98
0
        rUnoGlue.PositionAlignment = drawing::Alignment_RIGHT;
99
0
    else if (eAlign == (SdrAlign::HORZ_LEFT|SdrAlign::VERT_BOTTOM))
100
0
        rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM_LEFT;
101
0
    else if (eAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_BOTTOM))
102
0
        rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM;
103
0
    else if (eAlign == (SdrAlign::HORZ_RIGHT|SdrAlign::VERT_BOTTOM))
104
0
        rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM_RIGHT;
105
0
    else {
106
0
        rUnoGlue.PositionAlignment = drawing::Alignment_LEFT;
107
0
    }
108
109
8
    switch( rSdrGlue.GetEscDir() )
110
8
    {
111
0
    case SdrEscapeDirection::LEFT:
112
0
        rUnoGlue.Escape = drawing::EscapeDirection_LEFT;
113
0
        break;
114
0
    case SdrEscapeDirection::RIGHT:
115
0
        rUnoGlue.Escape = drawing::EscapeDirection_RIGHT;
116
0
        break;
117
0
    case SdrEscapeDirection::TOP:
118
0
        rUnoGlue.Escape = drawing::EscapeDirection_UP;
119
0
        break;
120
0
    case SdrEscapeDirection::BOTTOM:
121
0
        rUnoGlue.Escape = drawing::EscapeDirection_DOWN;
122
0
        break;
123
0
    case SdrEscapeDirection::HORZ:
124
0
        rUnoGlue.Escape = drawing::EscapeDirection_HORIZONTAL;
125
0
        break;
126
0
    case SdrEscapeDirection::VERT:
127
0
        rUnoGlue.Escape = drawing::EscapeDirection_VERTICAL;
128
0
        break;
129
//          case SdrEscapeDirection::SMART:
130
8
    default:
131
8
        rUnoGlue.Escape = drawing::EscapeDirection_SMART;
132
8
        break;
133
8
    }
134
8
}
135
136
static void convert( const drawing::GluePoint2& rUnoGlue, SdrGluePoint& rSdrGlue ) noexcept
137
0
{
138
0
    rSdrGlue.SetPos( Point( rUnoGlue.Position.X, rUnoGlue.Position.Y ) );
139
0
    rSdrGlue.SetPercent( rUnoGlue.IsRelative );
140
141
0
    switch( rUnoGlue.PositionAlignment )
142
0
    {
143
0
    case drawing::Alignment_TOP_LEFT:
144
0
        rSdrGlue.SetAlign( SdrAlign::VERT_TOP|SdrAlign::HORZ_LEFT );
145
0
        break;
146
0
    case drawing::Alignment_TOP:
147
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_CENTER|SdrAlign::VERT_TOP );
148
0
        break;
149
0
    case drawing::Alignment_TOP_RIGHT:
150
0
        rSdrGlue.SetAlign( SdrAlign::VERT_TOP|SdrAlign::HORZ_RIGHT );
151
0
        break;
152
0
    case drawing::Alignment_CENTER:
153
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER );
154
0
        break;
155
0
    case drawing::Alignment_RIGHT:
156
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_RIGHT|SdrAlign::VERT_CENTER );
157
0
        break;
158
0
    case drawing::Alignment_BOTTOM_LEFT:
159
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_LEFT|SdrAlign::VERT_BOTTOM );
160
0
        break;
161
0
    case drawing::Alignment_BOTTOM:
162
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_CENTER|SdrAlign::VERT_BOTTOM );
163
0
        break;
164
0
    case drawing::Alignment_BOTTOM_RIGHT:
165
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_RIGHT|SdrAlign::VERT_BOTTOM );
166
0
        break;
167
//  case SdrAlign::HORZ_LEFT:
168
0
    default:
169
0
        rSdrGlue.SetAlign( SdrAlign::HORZ_LEFT );
170
0
        break;
171
0
    }
172
0
    switch( rUnoGlue.Escape )
173
0
    {
174
0
    case drawing::EscapeDirection_LEFT:
175
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::LEFT);
176
0
        break;
177
0
    case drawing::EscapeDirection_RIGHT:
178
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::RIGHT);
179
0
        break;
180
0
    case drawing::EscapeDirection_UP:
181
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::TOP);
182
0
        break;
183
0
    case drawing::EscapeDirection_DOWN:
184
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::BOTTOM);
185
0
        break;
186
0
    case drawing::EscapeDirection_HORIZONTAL:
187
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::HORZ);
188
0
        break;
189
0
    case drawing::EscapeDirection_VERTICAL:
190
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::VERT);
191
0
        break;
192
//  case drawing::EscapeDirection_SMART:
193
0
    default:
194
0
        rSdrGlue.SetEscDir(SdrEscapeDirection::SMART);
195
0
        break;
196
0
    }
197
0
}
198
199
SvxUnoGluePointAccess::SvxUnoGluePointAccess( SdrObject* pObject ) noexcept
200
54
: mpObject( pObject )
201
54
{
202
54
}
203
204
// XIdentifierContainer
205
sal_Int32 SAL_CALL SvxUnoGluePointAccess::insert( const uno::Any& aElement )
206
0
{
207
0
    if( auto pObject = mpObject.get() )
208
0
    {
209
0
        SdrGluePointList* pList = pObject->ForceGluePointList();
210
0
        if( pList )
211
0
        {
212
            // second, insert the new gluepoint
213
0
            drawing::GluePoint2 aUnoGlue;
214
215
0
            if( aElement >>= aUnoGlue )
216
0
            {
217
0
                SdrGluePoint aSdrGlue;
218
0
                convert( aUnoGlue, aSdrGlue );
219
0
                sal_uInt16 nId = pList->Insert( aSdrGlue );
220
221
                // only repaint, no objectchange
222
0
                pObject->ActionChanged();
223
                // mpObject->BroadcastObjectChange();
224
225
0
                return static_cast<sal_Int32>((*pList)[nId].GetId() + NON_USER_DEFINED_GLUE_POINTS) - 1;
226
0
            }
227
228
0
            throw lang::IllegalArgumentException();
229
0
        }
230
0
    }
231
232
0
    return -1;
233
0
}
234
235
void SAL_CALL SvxUnoGluePointAccess::removeByIdentifier( sal_Int32 Identifier )
236
0
{
237
0
    auto pObject = mpObject.get();
238
0
    if( pObject && ( Identifier >= NON_USER_DEFINED_GLUE_POINTS ))
239
0
    {
240
0
        const sal_uInt16 nId = static_cast<sal_uInt16>(Identifier - NON_USER_DEFINED_GLUE_POINTS) + 1;
241
242
0
        SdrGluePointList* pList = const_cast<SdrGluePointList*>(pObject->GetGluePointList());
243
0
        const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
244
0
        sal_uInt16 i;
245
246
0
        for( i = 0; i < nCount; i++ )
247
0
        {
248
0
            if( (*pList)[i].GetId() == nId )
249
0
            {
250
0
                pList->Delete( i );
251
252
                // only repaint, no objectchange
253
0
                pObject->ActionChanged();
254
                // pObject->BroadcastObjectChange();
255
256
0
                return;
257
0
            }
258
0
        }
259
0
    }
260
261
0
    throw container::NoSuchElementException();
262
0
}
263
264
// XIdentifierReplace
265
void SAL_CALL SvxUnoGluePointAccess::replaceByIdentifer( sal_Int32 Identifier, const uno::Any& aElement )
266
0
{
267
0
    auto pObject = mpObject.get();
268
0
    if( !pObject )
269
0
        return;
270
271
0
    struct drawing::GluePoint2 aGluePoint;
272
0
    if( (Identifier < NON_USER_DEFINED_GLUE_POINTS) || !(aElement >>= aGluePoint))
273
0
        throw lang::IllegalArgumentException();
274
275
0
    const sal_uInt16 nId = static_cast<sal_uInt16>( Identifier - NON_USER_DEFINED_GLUE_POINTS ) + 1;
276
277
0
    SdrGluePointList* pList = const_cast< SdrGluePointList* >( pObject->GetGluePointList() );
278
0
    const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
279
0
    sal_uInt16 i;
280
0
    for( i = 0; i < nCount; i++ )
281
0
    {
282
0
        if( (*pList)[i].GetId() == nId )
283
0
        {
284
            // change the gluepoint
285
0
            SdrGluePoint& rTempPoint = (*pList)[i];
286
0
            convert( aGluePoint, rTempPoint );
287
288
            // only repaint, no objectchange
289
0
            pObject->ActionChanged();
290
            // pObject->BroadcastObjectChange();
291
292
0
            return;
293
0
        }
294
0
    }
295
296
0
    throw container::NoSuchElementException();
297
0
}
298
299
// XIdentifierAccess
300
uno::Any SAL_CALL SvxUnoGluePointAccess::getByIdentifier( sal_Int32 Identifier )
301
8
{
302
8
    auto pObject = mpObject.get();
303
8
    if( pObject )
304
8
    {
305
8
        struct drawing::GluePoint2 aGluePoint;
306
307
8
        if( Identifier < NON_USER_DEFINED_GLUE_POINTS ) // default gluepoint?
308
8
        {
309
8
            SdrGluePoint aTempPoint = pObject->GetVertexGluePoint( static_cast<sal_uInt16>(Identifier) );
310
8
            aGluePoint.IsUserDefined = false;
311
8
            convert( aTempPoint, aGluePoint );
312
8
            return uno::Any( aGluePoint );
313
8
        }
314
0
        else
315
0
        {
316
0
            const sal_uInt16 nId = static_cast<sal_uInt16>( Identifier - NON_USER_DEFINED_GLUE_POINTS ) + 1;
317
318
0
            const SdrGluePointList* pList = pObject->GetGluePointList();
319
0
            const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
320
0
            for( sal_uInt16 i = 0; i < nCount; i++ )
321
0
            {
322
0
                const SdrGluePoint& rTempPoint = (*pList)[i];
323
0
                if( rTempPoint.GetId() == nId )
324
0
                {
325
                    // #i38892#
326
0
                    if(rTempPoint.IsUserDefined())
327
0
                    {
328
0
                        aGluePoint.IsUserDefined = true;
329
0
                    }
330
331
0
                    convert( rTempPoint, aGluePoint );
332
0
                    return uno::Any( aGluePoint );
333
0
                }
334
0
            }
335
0
        }
336
8
    }
337
338
0
    throw container::NoSuchElementException();
339
8
}
340
341
uno::Sequence< sal_Int32 > SAL_CALL SvxUnoGluePointAccess::getIdentifiers()
342
54
{
343
54
    auto pObject = mpObject.get();
344
54
    if( pObject )
345
54
    {
346
54
        const SdrGluePointList* pList = pObject->GetGluePointList();
347
54
        const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
348
349
54
        sal_uInt16 i;
350
351
54
        uno::Sequence< sal_Int32 > aIdSequence( nCount + NON_USER_DEFINED_GLUE_POINTS );
352
54
        sal_Int32 *pIdentifier = aIdSequence.getArray();
353
354
270
        for( i = 0; i < NON_USER_DEFINED_GLUE_POINTS; i++ )
355
216
            *pIdentifier++ = static_cast<sal_Int32>(i);
356
357
54
        for( i = 0; i < nCount; i++ )
358
0
            *pIdentifier++ = static_cast<sal_Int32>( (*pList)[i].GetId() + NON_USER_DEFINED_GLUE_POINTS ) - 1;
359
360
54
        return aIdSequence;
361
54
    }
362
0
    else
363
0
    {
364
0
        uno::Sequence< sal_Int32 > aEmpty;
365
0
        return aEmpty;
366
0
    }
367
54
}
368
369
/* deprecated */
370
371
// XIndexContainer
372
void SAL_CALL SvxUnoGluePointAccess::insertByIndex( sal_Int32, const uno::Any& Element )
373
0
{
374
0
    auto pObject = mpObject.get();
375
0
    if( pObject )
376
0
    {
377
0
        SdrGluePointList* pList = pObject->ForceGluePointList();
378
0
        if( pList )
379
0
        {
380
0
            drawing::GluePoint2 aUnoGlue;
381
382
0
            if( Element >>= aUnoGlue )
383
0
            {
384
0
                SdrGluePoint aSdrGlue;
385
0
                convert( aUnoGlue, aSdrGlue );
386
0
                pList->Insert( aSdrGlue );
387
388
                // only repaint, no objectchange
389
0
                pObject->ActionChanged();
390
                // pObject->BroadcastObjectChange();
391
392
0
                return;
393
0
            }
394
395
0
            throw lang::IllegalArgumentException();
396
0
        }
397
0
    }
398
399
0
    throw lang::IndexOutOfBoundsException();
400
0
}
401
402
void SAL_CALL SvxUnoGluePointAccess::removeByIndex( sal_Int32 Index )
403
0
{
404
0
    auto pObject = mpObject.get();
405
0
    if( pObject )
406
0
    {
407
0
        SdrGluePointList* pList = pObject->ForceGluePointList();
408
0
        if( pList )
409
0
        {
410
0
            Index -= 4;
411
0
            if( Index >= 0 && Index < pList->GetCount() )
412
0
            {
413
0
                pList->Delete( static_cast<sal_uInt16>(Index) );
414
415
                // only repaint, no objectchange
416
0
                pObject->ActionChanged();
417
                // pObject->BroadcastObjectChange();
418
419
0
                return;
420
0
            }
421
0
        }
422
0
    }
423
424
0
    throw lang::IndexOutOfBoundsException();
425
0
}
426
427
// XIndexReplace
428
void SAL_CALL SvxUnoGluePointAccess::replaceByIndex( sal_Int32 Index, const uno::Any& Element )
429
0
{
430
0
    drawing::GluePoint2 aUnoGlue;
431
0
    if(!(Element >>= aUnoGlue))
432
0
        throw lang::IllegalArgumentException();
433
434
0
    auto pObject = mpObject.get();
435
0
    Index -= 4;
436
0
    if( pObject && Index >= 0 )
437
0
    {
438
0
        SdrGluePointList* pList = const_cast< SdrGluePointList* >( pObject->GetGluePointList() );
439
0
        if( pList && Index < pList->GetCount() )
440
0
        {
441
0
            SdrGluePoint& rGlue = (*pList)[static_cast<sal_uInt16>(Index)];
442
0
            convert( aUnoGlue, rGlue );
443
444
            // only repaint, no objectchange
445
0
            pObject->ActionChanged();
446
            // pObject->BroadcastObjectChange();
447
0
        }
448
0
    }
449
450
0
    throw lang::IndexOutOfBoundsException();
451
0
}
452
453
// XIndexAccess
454
sal_Int32 SAL_CALL SvxUnoGluePointAccess::getCount()
455
0
{
456
0
    auto pObject = mpObject.get();
457
0
    sal_Int32 nCount = 0;
458
0
    if( pObject )
459
0
    {
460
        // each node has a default of 4 gluepoints
461
        // and any number of user defined gluepoints
462
0
        nCount += 4;
463
464
0
        const SdrGluePointList* pList = pObject->GetGluePointList();
465
0
        if( pList )
466
0
            nCount += pList->GetCount();
467
0
    }
468
469
0
    return nCount;
470
0
}
471
472
uno::Any SAL_CALL SvxUnoGluePointAccess::getByIndex( sal_Int32 Index )
473
0
{
474
0
    auto pObject = mpObject.get();
475
0
    if( Index >= 0 && pObject )
476
0
    {
477
0
        struct drawing::GluePoint2 aGluePoint;
478
479
0
        if( Index < 4 ) // default gluepoint?
480
0
        {
481
0
            SdrGluePoint aTempPoint = pObject->GetVertexGluePoint( static_cast<sal_uInt16>(Index) );
482
0
            aGluePoint.IsUserDefined = false;
483
0
            convert( aTempPoint, aGluePoint );
484
0
            return uno::Any(aGluePoint);
485
0
        }
486
0
        else
487
0
        {
488
0
            Index -= 4;
489
0
            const SdrGluePointList* pList = pObject->GetGluePointList();
490
0
            if( pList && Index < pList->GetCount() )
491
0
            {
492
0
                const SdrGluePoint& rTempPoint = (*pList)[static_cast<sal_uInt16>(Index)];
493
0
                aGluePoint.IsUserDefined = true;
494
0
                convert( rTempPoint, aGluePoint );
495
0
                return uno::Any(aGluePoint);
496
0
            }
497
0
        }
498
0
    }
499
500
0
    throw lang::IndexOutOfBoundsException();
501
0
}
502
503
// XElementAccess
504
uno::Type SAL_CALL SvxUnoGluePointAccess::getElementType()
505
0
{
506
0
    return cppu::UnoType<drawing::GluePoint2>::get();
507
0
}
508
509
sal_Bool SAL_CALL SvxUnoGluePointAccess::hasElements()
510
0
{
511
0
    return bool(mpObject.get());
512
0
}
513
514
/**
515
 * Create a SvxUnoGluePointAccess
516
 */
517
uno::Reference< uno::XInterface > SvxUnoGluePointAccess_createInstance( SdrObject* pObject )
518
54
{
519
54
    return *new SvxUnoGluePointAccess(pObject);
520
54
}
521
522
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */