Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svdmark.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 <sal/config.h>
21
22
#include <osl/time.h>
23
#include <svx/svdmark.hxx>
24
#include <svx/svdobj.hxx>
25
#include <svx/svdpage.hxx>
26
#include <svx/svdpagv.hxx>
27
#include <svx/strings.hrc>
28
#include <svx/dialmgr.hxx>
29
#include <svx/diagram/DiagramHelper_svx.hxx>
30
31
32
#include <svl/SfxBroadcaster.hxx>
33
#include <svx/svdoedge.hxx>
34
#include <osl/diagnose.h>
35
#include <tools/debug.hxx>
36
37
#include <cassert>
38
39
void SdrMark::setTime()
40
0
{
41
0
    TimeValue aNow;
42
0
    osl_getSystemTime(&aNow);
43
0
    mnTimeStamp = sal_Int64(aNow.Seconds) * 1000000000 + aNow.Nanosec;
44
0
}
45
46
SdrMark::SdrMark(SdrObject* pNewObj, SdrPageView* pNewPageView)
47
0
:   mpSelectedSdrObject(pNewObj),
48
0
    mpPageView(pNewPageView),
49
0
    mbCon1(false),
50
0
    mbCon2(false),
51
0
    mnUser(0)
52
0
{
53
0
    if(mpSelectedSdrObject)
54
0
    {
55
0
        mpSelectedSdrObject->AddObjectUser( *this );
56
0
    }
57
0
    setTime();
58
0
}
59
60
SdrMark::SdrMark(const SdrMark& rMark)
61
0
:   ObjectUser(),
62
0
    mnTimeStamp(0),
63
0
    mpSelectedSdrObject(nullptr),
64
0
    mpPageView(nullptr),
65
0
    mbCon1(false),
66
0
    mbCon2(false),
67
0
    mnUser(0)
68
0
{
69
0
    *this = rMark;
70
0
}
71
72
SdrMark::~SdrMark()
73
0
{
74
0
    if (mpSelectedSdrObject)
75
0
    {
76
0
        mpSelectedSdrObject->RemoveObjectUser( *this );
77
0
    }
78
0
}
79
80
void SdrMark::ObjectInDestruction(const SdrObject& rObject)
81
0
{
82
0
    (void) rObject; // avoid warnings
83
0
    OSL_ENSURE(mpSelectedSdrObject && mpSelectedSdrObject == &rObject, "SdrMark::ObjectInDestruction: called from object different from hosted one (!)");
84
0
    OSL_ENSURE(mpSelectedSdrObject, "SdrMark::ObjectInDestruction: still selected SdrObject is deleted, deselect first (!)");
85
0
    mpSelectedSdrObject = nullptr;
86
0
}
87
88
void SdrMark::SetMarkedSdrObj(SdrObject* pNewObj)
89
0
{
90
0
    if(mpSelectedSdrObject)
91
0
    {
92
0
        mpSelectedSdrObject->RemoveObjectUser( *this );
93
0
    }
94
95
0
    mpSelectedSdrObject = pNewObj;
96
97
0
    if(mpSelectedSdrObject)
98
0
    {
99
0
        mpSelectedSdrObject->AddObjectUser( *this );
100
0
    }
101
0
}
102
103
SdrMark& SdrMark::operator=(const SdrMark& rMark)
104
0
{
105
0
    SetMarkedSdrObj(rMark.mpSelectedSdrObject);
106
107
0
    mnTimeStamp = rMark.mnTimeStamp;
108
0
    mpPageView = rMark.mpPageView;
109
0
    mbCon1 = rMark.mbCon1;
110
0
    mbCon2 = rMark.mbCon2;
111
0
    mnUser = rMark.mnUser;
112
0
    maPoints = rMark.maPoints;
113
0
    maGluePoints = rMark.maGluePoints;
114
115
0
    return *this;
116
0
}
117
118
static bool ImpSdrMarkListSorter(std::unique_ptr<SdrMark> const& lhs, std::unique_ptr<SdrMark> const& rhs)
119
0
{
120
0
    SdrObject* pObj1 = lhs->GetMarkedSdrObj();
121
0
    SdrObject* pObj2 = rhs->GetMarkedSdrObj();
122
0
    SdrObjList* pOL1 = pObj1 ? pObj1->getParentSdrObjListFromSdrObject() : nullptr;
123
0
    SdrObjList* pOL2 = pObj2 ? pObj2->getParentSdrObjListFromSdrObject() : nullptr;
124
125
0
    if (pOL1 == pOL2)
126
0
    {
127
        // AF: Note that I reverted a change from sal_uInt32 to sal_uLong (made
128
        // for 64bit compliance, #i78198#) because internally in SdrObject
129
        // both nOrdNum and mnNavigationPosition are stored as sal_uInt32.
130
0
        sal_uInt32 nObjOrd1(pObj1 ? pObj1->GetNavigationPosition() : 0);
131
0
        sal_uInt32 nObjOrd2(pObj2 ? pObj2->GetNavigationPosition() : 0);
132
133
0
        return nObjOrd1 < nObjOrd2;
134
0
    }
135
0
    else
136
0
    {
137
0
        return pOL1 < pOL2;
138
0
    }
139
0
}
140
141
142
void SdrMarkList::ForceSort() const
143
0
{
144
0
    if(!mbSorted)
145
0
    {
146
0
        const_cast<SdrMarkList*>(this)->ImpForceSort();
147
0
    }
148
0
}
149
150
void SdrMarkList::ImpForceSort()
151
0
{
152
0
    if(mbSorted)
153
0
        return;
154
155
0
    mbSorted = true;
156
0
    size_t nCount = maList.size();
157
158
    // remove invalid
159
0
    if(nCount > 0 )
160
0
    {
161
0
        std::erase_if(maList, [](std::unique_ptr<SdrMark>& rItem) { return rItem->GetMarkedSdrObj() == nullptr; });
162
0
        nCount = maList.size();
163
0
    }
164
165
0
    if(nCount <= 1)
166
0
        return;
167
168
0
    std::sort(maList.begin(), maList.end(), ImpSdrMarkListSorter);
169
170
    // remove duplicates
171
0
    if(maList.size() <= 1)
172
0
        return;
173
174
0
    SdrMark* pCurrent = maList.back().get();
175
0
    for (size_t count = maList.size() - 1; count; --count)
176
0
    {
177
0
        size_t i = count - 1;
178
0
        SdrMark* pCmp = maList[i].get();
179
0
        assert(pCurrent->GetMarkedSdrObj());
180
0
        if(pCurrent->GetMarkedSdrObj() == pCmp->GetMarkedSdrObj())
181
0
        {
182
            // Con1/Con2 Merging
183
0
            if(pCmp->IsCon1())
184
0
                pCurrent->SetCon1(true);
185
186
0
            if(pCmp->IsCon2())
187
0
                pCurrent->SetCon2(true);
188
189
            // delete pCmp
190
0
            maList.erase(maList.begin() + i);
191
0
        }
192
0
        else
193
0
        {
194
0
            pCurrent = pCmp;
195
0
        }
196
0
    }
197
0
}
198
199
void SdrMarkList::Clear()
200
1.18M
{
201
1.18M
    maList.clear();
202
1.18M
    mbSorted = true; //we're empty, so can be considered sorted
203
1.18M
    SetNameDirty();
204
1.18M
}
205
206
SdrMarkList& SdrMarkList::operator=(const SdrMarkList& rLst)
207
26
{
208
26
    if (this != &rLst)
209
26
    {
210
26
        Clear();
211
212
26
        for(size_t i = 0; i < rLst.GetMarkCount(); ++i)
213
0
        {
214
0
            SdrMark* pMark = rLst.GetMark(i);
215
0
            maList.emplace_back(new SdrMark(*pMark));
216
0
        }
217
218
26
        maMarkName = rLst.maMarkName;
219
26
        mbNameOk = rLst.mbNameOk;
220
26
        maPointName = rLst.maPointName;
221
26
        mbPointNameOk = rLst.mbPointNameOk;
222
26
        maGluePointName = rLst.maGluePointName;
223
26
        mbSorted = rLst.mbSorted;
224
26
    }
225
26
    return *this;
226
26
}
227
228
SdrMark* SdrMarkList::GetMark(size_t nNum) const
229
0
{
230
0
    return (nNum < maList.size()) ? maList[nNum].get() : nullptr;
231
0
}
232
233
size_t SdrMarkList::FindObject(const SdrObject* pObj) const
234
26
{
235
    // Since relying on OrdNums is not allowed for the selection because objects in the
236
    // selection may not be inserted in a list if they are e.g. modified ATM, i changed
237
    // this loop to just look if the object pointer is in the selection.
238
239
    // Problem is that GetOrdNum() which is const, internally casts to non-const and
240
    // hardly sets the OrdNum member of the object (nOrdNum) to 0 (ZERO) if the object
241
    // is not inserted in an object list.
242
    // Since this may be by purpose and necessary somewhere else i decided that it is
243
    // less dangerous to change this method then changing SdrObject::GetOrdNum().
244
26
    if(pObj)
245
26
    {
246
26
        for(size_t a = 0; a < maList.size(); ++a)
247
0
        {
248
0
            if(maList[a]->GetMarkedSdrObj() == pObj)
249
0
            {
250
0
                return a;
251
0
            }
252
0
        }
253
26
    }
254
255
26
    return SAL_MAX_SIZE;
256
26
}
257
258
void SdrMarkList::InsertEntry(const SdrMark& rMark, bool bChkSort)
259
0
{
260
0
    SetNameDirty();
261
0
    const size_t nCount(maList.size());
262
263
0
    if(!bChkSort || !mbSorted || nCount == 0)
264
0
    {
265
0
        if(!bChkSort)
266
0
            mbSorted = false;
267
268
0
        maList.emplace_back(new SdrMark(rMark));
269
0
    }
270
0
    else
271
0
    {
272
0
        SdrMark* pLast = GetMark(nCount - 1);
273
0
        const SdrObject* pLastObj = pLast->GetMarkedSdrObj();
274
0
        const SdrObject* pNewObj = rMark.GetMarkedSdrObj();
275
276
0
        if(pLastObj == pNewObj)
277
0
        {
278
            // This one already exists.
279
            // Con1/Con2 Merging
280
0
            if(rMark.IsCon1())
281
0
                pLast->SetCon1(true);
282
283
0
            if(rMark.IsCon2())
284
0
                pLast->SetCon2(true);
285
0
        }
286
0
        else
287
0
        {
288
0
            maList.emplace_back(new SdrMark(rMark));
289
290
            // now check if the sort is ok
291
0
            const SdrObjList* pLastOL = pLastObj!=nullptr ? pLastObj->getParentSdrObjListFromSdrObject() : nullptr;
292
0
            const SdrObjList* pNewOL = pNewObj !=nullptr ? pNewObj->getParentSdrObjListFromSdrObject() : nullptr;
293
294
0
            if(pLastOL == pNewOL)
295
0
            {
296
0
                const sal_uInt32 nLastNum(pLastObj!=nullptr ? pLastObj->GetOrdNum() : 0);
297
0
                const sal_uInt32 nNewNum(pNewObj !=nullptr ? pNewObj ->GetOrdNum() : 0);
298
299
0
                if(nNewNum < nLastNum)
300
0
                {
301
                    // at some point, we have to sort
302
0
                    mbSorted = false;
303
0
                }
304
0
            }
305
0
            else
306
0
            {
307
                // at some point, we have to sort
308
0
                mbSorted = false;
309
0
            }
310
0
        }
311
0
    }
312
0
}
313
314
void SdrMarkList::DeleteMark(size_t nNum)
315
0
{
316
0
    SdrMark* pMark = GetMark(nNum);
317
0
    DBG_ASSERT(pMark!=nullptr,"DeleteMark: MarkEntry not found.");
318
319
0
    if(pMark)
320
0
    {
321
0
        maList.erase(maList.begin() + nNum);
322
0
        if (maList.empty())
323
0
            mbSorted = true; //we're empty, so can be considered sorted
324
0
        SetNameDirty();
325
0
    }
326
0
}
327
328
void SdrMarkList::ReplaceMark(const SdrMark& rNewMark, size_t nNum)
329
0
{
330
0
    SdrMark* pMark = GetMark(nNum);
331
0
    DBG_ASSERT(pMark!=nullptr,"ReplaceMark: MarkEntry not found.");
332
333
0
    if(pMark)
334
0
    {
335
0
        SetNameDirty();
336
0
        maList[nNum].reset(new SdrMark(rNewMark));
337
0
        mbSorted = false;
338
0
    }
339
0
}
340
341
void SdrMarkList::Merge(const SdrMarkList& rSrcList, bool bReverse)
342
0
{
343
0
    const size_t nCount(rSrcList.maList.size());
344
345
0
    if(rSrcList.mbSorted)
346
0
    {
347
        // merge without forcing a Sort in rSrcList
348
0
        bReverse = false;
349
0
    }
350
351
0
    if(!bReverse)
352
0
    {
353
0
        for(size_t i = 0; i < nCount; ++i)
354
0
        {
355
0
            SdrMark* pM = rSrcList.maList[i].get();
356
0
            InsertEntry(*pM);
357
0
        }
358
0
    }
359
0
    else
360
0
    {
361
0
        for(size_t i = nCount; i > 0;)
362
0
        {
363
0
            --i;
364
0
            SdrMark* pM = rSrcList.maList[i].get();
365
0
            InsertEntry(*pM);
366
0
        }
367
0
    }
368
0
}
369
370
bool SdrMarkList::DeletePageView(const SdrPageView& rPV)
371
60.9k
{
372
60.9k
    bool bChgd(false);
373
374
60.9k
    for(auto it = maList.begin(); it != maList.end(); )
375
0
    {
376
0
        SdrMark* pMark = it->get();
377
378
0
        if(pMark->GetPageView()==&rPV)
379
0
        {
380
0
            it = maList.erase(it);
381
0
            SetNameDirty();
382
0
            bChgd = true;
383
0
        }
384
0
        else
385
0
            ++it;
386
0
    }
387
388
60.9k
    return bChgd;
389
60.9k
}
390
391
bool SdrMarkList::InsertPageView(const SdrPageView& rPV)
392
0
{
393
0
    bool bChgd(false);
394
0
    DeletePageView(rPV); // delete all of them, then append the entire page
395
0
    const SdrObjList* pOL = rPV.GetObjList();
396
397
0
    for (const rtl::Reference<SdrObject>& pObj : *pOL)
398
0
    {
399
0
        bool bDoIt(rPV.IsObjMarkable(pObj.get()));
400
401
0
        if(bDoIt)
402
0
        {
403
0
            maList.emplace_back(new SdrMark(pObj.get(), const_cast<SdrPageView*>(&rPV)));
404
0
            SetNameDirty();
405
0
            bChgd = true;
406
0
        }
407
0
    }
408
409
0
    return bChgd;
410
0
}
411
412
const OUString& SdrMarkList::GetMarkDescription() const
413
0
{
414
0
    const size_t nCount(GetMarkCount());
415
416
0
    if(mbNameOk && 1 == nCount)
417
0
    {
418
        // if it's a single selection, cache only text frame
419
0
        const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
420
0
        const SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );
421
422
0
        if(!pTextObj || !pTextObj->IsTextFrame())
423
0
        {
424
0
            const_cast<SdrMarkList*>(this)->mbNameOk = false;
425
0
        }
426
0
    }
427
428
0
    if(!mbNameOk)
429
0
    {
430
0
        SdrMark* pMark = GetMark(0);
431
0
        OUString aNam;
432
433
0
        if(!nCount)
434
0
        {
435
0
            const_cast<SdrMarkList*>(this)->maMarkName = SvxResId(STR_ObjNameNoObj);
436
0
        }
437
0
        else if(1 == nCount)
438
0
        {
439
0
            if(pMark->GetMarkedSdrObj())
440
0
            {
441
0
                aNam = pMark->GetMarkedSdrObj()->TakeObjNameSingul();
442
0
            }
443
0
        }
444
0
        else
445
0
        {
446
0
            if(pMark->GetMarkedSdrObj())
447
0
            {
448
0
                aNam = pMark->GetMarkedSdrObj()->TakeObjNamePlural();
449
0
                bool bEq(true);
450
451
0
                for(size_t i = 1; i < GetMarkCount() && bEq; ++i)
452
0
                {
453
0
                    SdrMark* pMark2 = GetMark(i);
454
0
                    OUString aStr1(pMark2->GetMarkedSdrObj()->TakeObjNamePlural());
455
0
                    bEq = aNam == aStr1;
456
0
                }
457
458
0
                if(!bEq)
459
0
                {
460
0
                    aNam = SvxResId(STR_ObjNamePlural);
461
0
                }
462
0
            }
463
464
0
            aNam = OUString::number( nCount ) + " " + aNam;
465
0
        }
466
467
0
        const_cast<SdrMarkList*>(this)->maMarkName = aNam;
468
0
        const_cast<SdrMarkList*>(this)->mbNameOk = true;
469
0
    }
470
471
0
    return maMarkName;
472
0
}
473
474
const OUString& SdrMarkList::GetPointMarkDescription(bool bGlue) const
475
0
{
476
0
    bool& rNameOk = const_cast<bool&>(bGlue ? mbGluePointNameOk : mbPointNameOk);
477
0
    OUString& rName = const_cast<OUString&>(bGlue ? maGluePointName : maPointName);
478
0
    const size_t nMarkCount(GetMarkCount());
479
0
    size_t nMarkPtCnt(0);
480
0
    size_t nMarkPtObjCnt(0);
481
0
    size_t n1stMarkNum(SAL_MAX_SIZE);
482
483
0
    for(size_t nMarkNum = 0; nMarkNum < nMarkCount; ++nMarkNum)
484
0
    {
485
0
        const SdrMark* pMark = GetMark(nMarkNum);
486
0
        const SdrUShortCont& rPts = bGlue ? pMark->GetMarkedGluePoints() : pMark->GetMarkedPoints();
487
488
0
        if (!rPts.empty())
489
0
        {
490
0
            if(n1stMarkNum == SAL_MAX_SIZE)
491
0
            {
492
0
                n1stMarkNum = nMarkNum;
493
0
            }
494
495
0
            nMarkPtCnt += rPts.size();
496
0
            nMarkPtObjCnt++;
497
0
        }
498
499
0
        if(nMarkPtObjCnt > 1 && rNameOk)
500
0
        {
501
            // preliminary decision
502
0
            return rName;
503
0
        }
504
0
    }
505
506
0
    if(rNameOk && 1 == nMarkPtObjCnt)
507
0
    {
508
        // if it's a single selection, cache only text frame
509
0
        const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
510
0
        const SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );
511
512
0
        if(!pTextObj || !pTextObj->IsTextFrame())
513
0
        {
514
0
            rNameOk = false;
515
0
        }
516
0
    }
517
518
0
    if(!nMarkPtObjCnt)
519
0
    {
520
0
        rName.clear();
521
0
        rNameOk = true;
522
0
    }
523
0
    else if(!rNameOk)
524
0
    {
525
0
        const SdrMark* pMark = GetMark(n1stMarkNum);
526
0
        OUString aNam;
527
528
0
        if(1 == nMarkPtObjCnt)
529
0
        {
530
0
            if(pMark->GetMarkedSdrObj())
531
0
            {
532
0
                aNam = pMark->GetMarkedSdrObj()->TakeObjNameSingul();
533
0
            }
534
0
        }
535
0
        else
536
0
        {
537
0
            if(pMark->GetMarkedSdrObj())
538
0
            {
539
0
                aNam = pMark->GetMarkedSdrObj()->TakeObjNamePlural();
540
0
            }
541
542
0
            bool bEq(true);
543
544
0
            for(size_t i = n1stMarkNum + 1; i < GetMarkCount() && bEq; ++i)
545
0
            {
546
0
                const SdrMark* pMark2 = GetMark(i);
547
0
                const SdrUShortCont& rPts = bGlue ? pMark2->GetMarkedGluePoints() : pMark2->GetMarkedPoints();
548
549
0
                if (!rPts.empty() && pMark2->GetMarkedSdrObj())
550
0
                {
551
0
                    OUString aStr1(pMark2->GetMarkedSdrObj()->TakeObjNamePlural());
552
0
                    bEq = aNam == aStr1;
553
0
                }
554
0
            }
555
556
0
            if(!bEq)
557
0
            {
558
0
                aNam = SvxResId(STR_ObjNamePlural);
559
0
            }
560
561
0
            aNam = OUString::number( nMarkPtObjCnt ) + " " + aNam;
562
0
        }
563
564
0
        OUString aStr1;
565
566
0
        if(1 == nMarkPtCnt)
567
0
        {
568
0
            aStr1 = SvxResId(bGlue ? STR_ViewMarkedGluePoint : STR_ViewMarkedPoint);
569
0
        }
570
0
        else
571
0
        {
572
0
            aStr1 = SvxResId(bGlue ? STR_ViewMarkedGluePoints : STR_ViewMarkedPoints);
573
0
            aStr1 = aStr1.replaceFirst("%2", OUString::number( nMarkPtCnt ));
574
0
        }
575
576
0
        aStr1 = aStr1.replaceFirst("%1", aNam);
577
0
        rName = aStr1;
578
0
        rNameOk = true;
579
0
    }
580
581
0
    return rName;
582
0
}
583
584
bool SdrMarkList::TakeBoundRect(SdrPageView const * pPV, tools::Rectangle& rRect) const
585
179k
{
586
179k
    bool bFnd(false);
587
179k
    tools::Rectangle aR;
588
589
179k
    for(size_t i = 0; i < GetMarkCount(); ++i)
590
0
    {
591
0
        SdrMark* pMark = GetMark(i);
592
593
0
        if(!pPV || pMark->GetPageView() == pPV)
594
0
        {
595
0
            SdrObject* pCandidate(pMark->GetMarkedSdrObj());
596
597
0
            if(pCandidate)
598
0
            {
599
0
                aR = pCandidate->GetCurrentBoundRect();
600
601
0
                if(bFnd)
602
0
                {
603
0
                    rRect.Union(aR);
604
0
                }
605
0
                else
606
0
                {
607
0
                    rRect = aR;
608
0
                    bFnd = true;
609
0
                }
610
0
            }
611
0
        }
612
0
    }
613
614
179k
    return bFnd;
615
179k
}
616
617
bool SdrMarkList::TakeSnapRect(SdrPageView const * pPV, tools::Rectangle& rRect) const
618
179k
{
619
179k
    bool bFnd(false);
620
621
179k
    for(size_t i = 0; i < GetMarkCount(); ++i)
622
0
    {
623
0
        SdrMark* pMark = GetMark(i);
624
625
0
        if(!pPV || pMark->GetPageView() == pPV)
626
0
        {
627
0
            SdrObject* pCandidate(pMark->GetMarkedSdrObj());
628
629
0
            if(pCandidate)
630
0
            {
631
0
                tools::Rectangle aR(pCandidate->GetSnapRect());
632
633
0
                if(bFnd)
634
0
                {
635
0
                    rRect.Union(aR);
636
0
                }
637
0
                else
638
0
                {
639
0
                    rRect = aR;
640
0
                    bFnd = true;
641
0
                }
642
0
            }
643
0
        }
644
0
    }
645
646
179k
    return bFnd;
647
179k
}
648
649
bool SdrMarkList::isDiagramBackgroundShapeSelected() const
650
0
{
651
0
    if (1 != GetMarkCount())
652
0
        return false;
653
654
0
    SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
655
0
    if (nullptr == pObj || !pObj->isDiagram())
656
0
        return false;
657
658
0
    SdrObject* pSubSelection(pObj->getDiagramSubSelection());
659
0
    if(nullptr == pSubSelection)
660
0
        return false;
661
662
0
    return pSubSelection->isDiagramBackgroundShape();
663
0
}
664
665
namespace sdr
666
{
667
    ViewSelection::ViewSelection()
668
326k
    :   mbEdgesOfMarkedNodesDirty(false)
669
326k
    {
670
326k
    }
671
672
    void ViewSelection::SetEdgesOfMarkedNodesDirty()
673
68.2k
    {
674
68.2k
        if(!mbEdgesOfMarkedNodesDirty)
675
68.2k
        {
676
68.2k
            mbEdgesOfMarkedNodesDirty = true;
677
68.2k
            maEdgesOfMarkedNodes.Clear();
678
68.2k
            maMarkedEdgesOfMarkedNodes.Clear();
679
68.2k
            maAllMarkedObjects.clear();
680
68.2k
        }
681
68.2k
    }
682
683
    const SdrMarkList& ViewSelection::GetEdgesOfMarkedNodes() const
684
0
    {
685
0
        if(mbEdgesOfMarkedNodesDirty)
686
0
        {
687
0
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
688
0
        }
689
690
0
        return maEdgesOfMarkedNodes;
691
0
    }
692
693
    const SdrMarkList& ViewSelection::GetMarkedEdgesOfMarkedNodes() const
694
0
    {
695
0
        if(mbEdgesOfMarkedNodesDirty)
696
0
        {
697
0
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
698
0
        }
699
700
0
        return maMarkedEdgesOfMarkedNodes;
701
0
    }
702
703
    const std::vector<SdrObject*>& ViewSelection::GetAllMarkedObjects() const
704
0
    {
705
0
        if(mbEdgesOfMarkedNodesDirty)
706
0
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
707
708
0
        return maAllMarkedObjects;
709
0
    }
710
711
    void ViewSelection::ImplCollectCompleteSelection(SdrObject* pObj)
712
0
    {
713
0
        if(!pObj)
714
0
            return;
715
716
0
        bool bIsGroup(pObj->IsGroupObject());
717
718
0
        if(bIsGroup && DynCastE3dObject(pObj) != nullptr && DynCastE3dScene(pObj) == nullptr)
719
0
        {
720
0
            bIsGroup = false;
721
0
        }
722
723
0
        if(bIsGroup)
724
0
        {
725
0
            SdrObjList* pList = pObj->GetSubList();
726
727
0
            for (const rtl::Reference<SdrObject>& pObj2 : *pList)
728
0
                ImplCollectCompleteSelection(pObj2.get());
729
0
        }
730
731
0
        maAllMarkedObjects.push_back(pObj);
732
0
    }
733
734
    void ViewSelection::ImpForceEdgesOfMarkedNodes()
735
0
    {
736
0
        if(!mbEdgesOfMarkedNodesDirty)
737
0
            return;
738
739
0
        mbEdgesOfMarkedNodesDirty = false;
740
0
        maMarkedObjectList.ForceSort();
741
0
        maEdgesOfMarkedNodes.Clear();
742
0
        maMarkedEdgesOfMarkedNodes.Clear();
743
0
        maAllMarkedObjects.clear();
744
745
        // GetMarkCount after ForceSort
746
0
        const size_t nMarkCount(maMarkedObjectList.GetMarkCount());
747
748
0
        for(size_t a = 0; a < nMarkCount; ++a)
749
0
        {
750
0
            SdrObject* pCandidate = maMarkedObjectList.GetMark(a)->GetMarkedSdrObj();
751
0
            if(!pCandidate)
752
0
                continue;
753
754
            // build transitive hull
755
0
            ImplCollectCompleteSelection(pCandidate);
756
757
            // travel over broadcaster/listener to access edges connected to the selected object
758
0
            const SfxBroadcaster* pBC = pCandidate->GetBroadcaster();
759
0
            if(!pBC)
760
0
                continue;
761
762
0
            pBC->ForAllListeners(
763
0
                [this, &pCandidate, &a] (SfxListener* pLst)
764
0
                {
765
0
                    SdrEdgeObj* pEdge = dynamic_cast<SdrEdgeObj*>( pLst );
766
767
0
                    if(pEdge && pEdge->IsInserted() && pEdge->getSdrPageFromSdrObject() == pCandidate->getSdrPageFromSdrObject())
768
0
                    {
769
0
                        SdrMark aM(pEdge, maMarkedObjectList.GetMark(a)->GetPageView());
770
771
0
                        if(pEdge->GetConnectedNode(true) == pCandidate)
772
0
                        {
773
0
                            aM.SetCon1(true);
774
0
                        }
775
776
0
                        if(pEdge->GetConnectedNode(false) == pCandidate)
777
0
                        {
778
0
                            aM.SetCon2(true);
779
0
                        }
780
781
0
                        if(SAL_MAX_SIZE == maMarkedObjectList.FindObject(pEdge))
782
0
                        {
783
                            // check if it itself is selected
784
0
                            maEdgesOfMarkedNodes.InsertEntry(aM);
785
0
                        }
786
0
                        else
787
0
                        {
788
0
                            maMarkedEdgesOfMarkedNodes.InsertEntry(aM);
789
0
                        }
790
0
                    }
791
0
                    return false;
792
0
                });
793
0
        }
794
0
        maEdgesOfMarkedNodes.ForceSort();
795
0
        maMarkedEdgesOfMarkedNodes.ForceSort();
796
0
    }
797
} // end of namespace sdr
798
799
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */