Coverage Report

Created: 2026-07-10 11:04

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
623k
{
201
623k
    maList.clear();
202
623k
    mbSorted = true; //we're empty, so can be considered sorted
203
623k
    SetNameDirty();
204
623k
}
205
206
SdrMarkList& SdrMarkList::operator=(const SdrMarkList& rLst)
207
27
{
208
27
    if (this != &rLst)
209
27
    {
210
27
        Clear();
211
212
27
        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
27
        maMarkName = rLst.maMarkName;
219
27
        mbNameOk = rLst.mbNameOk;
220
27
        maPointName = rLst.maPointName;
221
27
        mbPointNameOk = rLst.mbPointNameOk;
222
27
        maGluePointName = rLst.maGluePointName;
223
27
        mbSorted = rLst.mbSorted;
224
27
    }
225
27
    return *this;
226
27
}
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
28
{
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
28
    if(pObj)
245
28
    {
246
28
        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
28
    }
254
255
28
    return SAL_MAX_SIZE;
256
28
}
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
64.2k
{
372
64.2k
    bool bChgd(false);
373
374
64.2k
    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
64.2k
    return bChgd;
389
64.2k
}
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
193k
{
586
193k
    bool bFnd(false);
587
193k
    tools::Rectangle aR;
588
589
193k
    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
193k
    return bFnd;
615
193k
}
616
617
bool SdrMarkList::TakeSnapRect(SdrPageView const * pPV, tools::Rectangle& rRect) const
618
193k
{
619
193k
    bool bFnd(false);
620
621
193k
    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
193k
    return bFnd;
647
193k
}
648
649
namespace sdr
650
{
651
    ViewSelection::ViewSelection()
652
133k
    :   mbEdgesOfMarkedNodesDirty(false)
653
133k
    {
654
133k
    }
655
656
    void ViewSelection::SetEdgesOfMarkedNodesDirty()
657
72.3k
    {
658
72.3k
        if(!mbEdgesOfMarkedNodesDirty)
659
72.3k
        {
660
72.3k
            mbEdgesOfMarkedNodesDirty = true;
661
72.3k
            maEdgesOfMarkedNodes.Clear();
662
72.3k
            maMarkedEdgesOfMarkedNodes.Clear();
663
72.3k
            maAllMarkedObjects.clear();
664
72.3k
        }
665
72.3k
    }
666
667
    const SdrMarkList& ViewSelection::GetEdgesOfMarkedNodes() const
668
0
    {
669
0
        if(mbEdgesOfMarkedNodesDirty)
670
0
        {
671
0
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
672
0
        }
673
674
0
        return maEdgesOfMarkedNodes;
675
0
    }
676
677
    const SdrMarkList& ViewSelection::GetMarkedEdgesOfMarkedNodes() const
678
0
    {
679
0
        if(mbEdgesOfMarkedNodesDirty)
680
0
        {
681
0
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
682
0
        }
683
684
0
        return maMarkedEdgesOfMarkedNodes;
685
0
    }
686
687
    const std::vector<SdrObject*>& ViewSelection::GetAllMarkedObjects() const
688
0
    {
689
0
        if(mbEdgesOfMarkedNodesDirty)
690
0
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
691
692
0
        return maAllMarkedObjects;
693
0
    }
694
695
    void ViewSelection::ImplCollectCompleteSelection(SdrObject* pObj)
696
0
    {
697
0
        if(!pObj)
698
0
            return;
699
700
0
        bool bIsGroup(pObj->IsGroupObject());
701
702
0
        if(bIsGroup && DynCastE3dObject(pObj) != nullptr && DynCastE3dScene(pObj) == nullptr)
703
0
        {
704
0
            bIsGroup = false;
705
0
        }
706
707
0
        if(bIsGroup)
708
0
        {
709
0
            SdrObjList* pList = pObj->GetSubList();
710
711
0
            for (const rtl::Reference<SdrObject>& pObj2 : *pList)
712
0
                ImplCollectCompleteSelection(pObj2.get());
713
0
        }
714
715
0
        maAllMarkedObjects.push_back(pObj);
716
0
    }
717
718
    void ViewSelection::ImpForceEdgesOfMarkedNodes()
719
0
    {
720
0
        if(!mbEdgesOfMarkedNodesDirty)
721
0
            return;
722
723
0
        mbEdgesOfMarkedNodesDirty = false;
724
0
        maMarkedObjectList.ForceSort();
725
0
        maEdgesOfMarkedNodes.Clear();
726
0
        maMarkedEdgesOfMarkedNodes.Clear();
727
0
        maAllMarkedObjects.clear();
728
729
        // GetMarkCount after ForceSort
730
0
        const size_t nMarkCount(maMarkedObjectList.GetMarkCount());
731
732
0
        for(size_t a = 0; a < nMarkCount; ++a)
733
0
        {
734
0
            SdrObject* pCandidate = maMarkedObjectList.GetMark(a)->GetMarkedSdrObj();
735
0
            if(!pCandidate)
736
0
                continue;
737
738
            // build transitive hull
739
0
            ImplCollectCompleteSelection(pCandidate);
740
741
            // travel over broadcaster/listener to access edges connected to the selected object
742
0
            const SfxBroadcaster* pBC = pCandidate->GetBroadcaster();
743
0
            if(!pBC)
744
0
                continue;
745
746
0
            pBC->ForAllListeners(
747
0
                [this, &pCandidate, &a] (SfxListener* pLst)
748
0
                {
749
0
                    SdrEdgeObj* pEdge = dynamic_cast<SdrEdgeObj*>( pLst );
750
751
0
                    if(pEdge && pEdge->IsInserted() && pEdge->getSdrPageFromSdrObject() == pCandidate->getSdrPageFromSdrObject())
752
0
                    {
753
0
                        SdrMark aM(pEdge, maMarkedObjectList.GetMark(a)->GetPageView());
754
755
0
                        if(pEdge->GetConnectedNode(true) == pCandidate)
756
0
                        {
757
0
                            aM.SetCon1(true);
758
0
                        }
759
760
0
                        if(pEdge->GetConnectedNode(false) == pCandidate)
761
0
                        {
762
0
                            aM.SetCon2(true);
763
0
                        }
764
765
0
                        if(SAL_MAX_SIZE == maMarkedObjectList.FindObject(pEdge))
766
0
                        {
767
                            // check if it itself is selected
768
0
                            maEdgesOfMarkedNodes.InsertEntry(aM);
769
0
                        }
770
0
                        else
771
0
                        {
772
0
                            maMarkedEdgesOfMarkedNodes.InsertEntry(aM);
773
0
                        }
774
0
                    }
775
0
                    return false;
776
0
                });
777
0
        }
778
0
        maEdgesOfMarkedNodes.ForceSort();
779
0
        maMarkedEdgesOfMarkedNodes.ForceSort();
780
0
    }
781
} // end of namespace sdr
782
783
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */