Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/sidebar/SelectionAnalyzer.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 <svx/sidebar/SelectionAnalyzer.hxx>
21
#include <svx/svdmark.hxx>
22
#include <svx/svdobj.hxx>
23
#include <svx/svdotext.hxx>
24
#include <svx/svdpage.hxx>
25
#include <svx/fontworkbar.hxx>
26
27
using vcl::EnumContext;
28
29
namespace svx::sidebar
30
{
31
EnumContext::Context SelectionAnalyzer::GetContextForSelection_SC(const SdrMarkList& rMarkList)
32
0
{
33
0
    EnumContext::Context eContext = EnumContext::Context::Unknown;
34
35
0
    switch (rMarkList.GetMarkCount())
36
0
    {
37
0
        case 0:
38
            // Empty selection.  Return Context::Unknown to let the caller
39
            // substitute it with the default context.
40
0
            break;
41
42
0
        case 1:
43
0
        {
44
0
            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
45
0
            auto pTextObj = DynCastSdrTextObj(pObj);
46
0
            if (pTextObj && pTextObj->IsInEditMode())
47
0
            {
48
0
                eContext = EnumContext::Context::DrawText;
49
0
            }
50
0
            else if (svx::checkForFontWork(pObj))
51
0
            {
52
0
                eContext = EnumContext::Context::DrawFontwork;
53
0
            }
54
0
            else
55
0
            {
56
0
                const SdrInventor nInv = pObj->GetObjInventor();
57
0
                const SdrObjKind nObjId = pObj->GetObjIdentifier();
58
0
                if (nInv == SdrInventor::Default)
59
0
                    eContext = GetContextForObjectId_SC(nObjId);
60
0
                else if (nInv == SdrInventor::FmForm)
61
0
                    eContext = EnumContext::Context::Form;
62
0
            }
63
0
            break;
64
0
        }
65
66
0
        default:
67
0
        {
68
            // Multi selection.
69
0
            switch (GetInventorTypeFromMark(rMarkList))
70
0
            {
71
0
                case SdrInventor::Default:
72
0
                {
73
0
                    const SdrObjKind nObjId(GetObjectTypeFromMark(rMarkList));
74
0
                    if (nObjId == SdrObjKind::NONE)
75
0
                        eContext = EnumContext::Context::MultiObject;
76
0
                    else
77
0
                        eContext = GetContextForObjectId_SC(nObjId);
78
0
                    break;
79
0
                }
80
81
0
                case SdrInventor::FmForm:
82
0
                    eContext = EnumContext::Context::Form;
83
0
                    break;
84
85
0
                case SdrInventor::Unknown:
86
0
                    eContext = EnumContext::Context::MultiObject;
87
0
                    break;
88
89
0
                default:
90
0
                    break;
91
0
            }
92
0
        }
93
0
    }
94
95
0
    return eContext;
96
0
}
97
98
EnumContext::Context SelectionAnalyzer::GetContextForSelection_SD(const SdrMarkList& rMarkList,
99
                                                                  const ViewType eViewType)
100
0
{
101
0
    EnumContext::Context eContext = EnumContext::Context::Unknown;
102
103
    // Note that some cases are handled by the caller.  They rely on
104
    // sd specific data.
105
0
    switch (rMarkList.GetMarkCount())
106
0
    {
107
0
        case 0:
108
0
            switch (eViewType)
109
0
            {
110
0
                case ViewType::Standard:
111
0
                    eContext = EnumContext::Context::DrawPage;
112
0
                    break;
113
0
                case ViewType::Master:
114
0
                    eContext = EnumContext::Context::MasterPage;
115
0
                    break;
116
0
                case ViewType::Handout:
117
0
                    eContext = EnumContext::Context::HandoutPage;
118
0
                    break;
119
0
                case ViewType::Notes:
120
0
                    eContext = EnumContext::Context::NotesPage;
121
0
                    break;
122
0
            }
123
0
            break;
124
125
0
        case 1:
126
0
        {
127
0
            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
128
0
            auto pTextObj = DynCastSdrTextObj(pObj);
129
0
            if (pTextObj && pTextObj->IsInEditMode())
130
0
            {
131
0
                if (pObj->GetObjIdentifier() == SdrObjKind::Table)
132
0
                {
133
                    // Let a table object take precedence over text
134
                    // edit mode.  The panels for text editing are
135
                    // present for table context as well, anyway.
136
0
                    eContext = EnumContext::Context::Table;
137
0
                }
138
0
                else
139
0
                    eContext = EnumContext::Context::DrawText;
140
0
            }
141
0
            else if (svx::checkForFontWork(pObj))
142
0
            {
143
0
                eContext = EnumContext::Context::DrawFontwork;
144
0
            }
145
0
            else
146
0
            {
147
0
                const SdrInventor nInv = pObj->GetObjInventor();
148
0
                SdrObjKind nObjId = pObj->GetObjIdentifier();
149
0
                if (nInv == SdrInventor::Default)
150
0
                {
151
0
                    if (nObjId == SdrObjKind::Group)
152
0
                    {
153
0
                        nObjId = GetObjectTypeFromGroup(pObj);
154
0
                        if (nObjId == SdrObjKind::NONE)
155
0
                            nObjId = SdrObjKind::Group;
156
0
                    }
157
0
                    eContext = GetContextForObjectId_SD(nObjId, eViewType);
158
0
                }
159
0
                else if (nInv == SdrInventor::E3d)
160
0
                {
161
0
                    eContext = EnumContext::Context::ThreeDObject;
162
0
                }
163
0
                else if (nInv == SdrInventor::FmForm)
164
0
                {
165
0
                    eContext = EnumContext::Context::Form;
166
0
                }
167
0
            }
168
0
            break;
169
0
        }
170
171
0
        default:
172
0
        {
173
0
            switch (GetInventorTypeFromMark(rMarkList))
174
0
            {
175
0
                case SdrInventor::Default:
176
0
                {
177
0
                    const SdrObjKind nObjId = GetObjectTypeFromMark(rMarkList);
178
0
                    if (nObjId == SdrObjKind::NONE)
179
0
                        eContext = EnumContext::Context::MultiObject;
180
0
                    else
181
0
                        eContext = GetContextForObjectId_SD(nObjId, eViewType);
182
0
                    break;
183
0
                }
184
185
0
                case SdrInventor::E3d:
186
0
                    eContext = EnumContext::Context::ThreeDObject;
187
0
                    break;
188
189
0
                case SdrInventor::FmForm:
190
0
                    eContext = EnumContext::Context::Form;
191
0
                    break;
192
193
0
                case SdrInventor::Unknown:
194
0
                    eContext = EnumContext::Context::MultiObject;
195
0
                    break;
196
197
0
                default:
198
0
                    break;
199
0
            }
200
0
            break;
201
0
        }
202
0
    }
203
204
0
    return eContext;
205
0
}
206
207
EnumContext::Context SelectionAnalyzer::GetContextForObjectId_SC(const SdrObjKind nObjectId)
208
0
{
209
0
    switch (nObjectId)
210
0
    {
211
0
        case SdrObjKind::Caption:
212
0
        case SdrObjKind::TitleText:
213
0
        case SdrObjKind::OutlineText:
214
0
        case SdrObjKind::Text:
215
0
        case SdrObjKind::Measure:
216
0
        case SdrObjKind::Rectangle:
217
0
        case SdrObjKind::CircleOrEllipse:
218
0
        case SdrObjKind::FreehandFill:
219
0
        case SdrObjKind::PathFill:
220
0
        case SdrObjKind::Polygon:
221
0
        case SdrObjKind::CircleSection:
222
0
        case SdrObjKind::CircleArc:
223
0
        case SdrObjKind::CircleCut:
224
0
        case SdrObjKind::CustomShape:
225
0
        case SdrObjKind::Group:
226
0
            return EnumContext::Context::Draw;
227
228
0
        case SdrObjKind::PolyLine:
229
0
        case SdrObjKind::PathLine:
230
0
        case SdrObjKind::FreehandLine:
231
0
        case SdrObjKind::Line:
232
0
        case SdrObjKind::Edge:
233
0
            return EnumContext::Context::DrawLine;
234
235
0
        case SdrObjKind::Graphic:
236
0
            return EnumContext::Context::Graphic;
237
238
0
        case SdrObjKind::OLE2:
239
0
            return EnumContext::Context::OLE;
240
241
0
        case SdrObjKind::Media:
242
0
            return EnumContext::Context::Media;
243
244
0
        default:
245
0
            return EnumContext::Context::Unknown;
246
0
    }
247
0
}
248
249
EnumContext::Context SelectionAnalyzer::GetContextForObjectId_SD(const SdrObjKind nObjectId,
250
                                                                 const ViewType eViewType)
251
0
{
252
0
    switch (nObjectId)
253
0
    {
254
0
        case SdrObjKind::Caption:
255
0
        case SdrObjKind::Measure:
256
0
        case SdrObjKind::Rectangle:
257
0
        case SdrObjKind::CircleOrEllipse:
258
0
        case SdrObjKind::FreehandFill:
259
0
        case SdrObjKind::PathFill:
260
0
        case SdrObjKind::Polygon:
261
0
        case SdrObjKind::CircleSection:
262
0
        case SdrObjKind::CircleArc:
263
0
        case SdrObjKind::CircleCut:
264
0
        case SdrObjKind::CustomShape:
265
0
        case SdrObjKind::Group:
266
0
            return EnumContext::Context::Draw;
267
268
0
        case SdrObjKind::Edge:
269
0
        case SdrObjKind::PathLine:
270
0
        case SdrObjKind::FreehandLine:
271
0
        case SdrObjKind::PolyLine:
272
0
        case SdrObjKind::Line:
273
0
            return EnumContext::Context::DrawLine;
274
275
0
        case SdrObjKind::TitleText:
276
0
        case SdrObjKind::OutlineText:
277
0
        case SdrObjKind::Text:
278
0
            return EnumContext::Context::TextObject;
279
280
0
        case SdrObjKind::Graphic:
281
0
            return EnumContext::Context::Graphic;
282
283
0
        case SdrObjKind::OLE2:
284
0
            return EnumContext::Context::OLE;
285
286
0
        case SdrObjKind::Media:
287
0
            return EnumContext::Context::Media;
288
289
0
        case SdrObjKind::Table:
290
0
            return EnumContext::Context::Table;
291
292
0
        case SdrObjKind::Page:
293
0
            switch (eViewType)
294
0
            {
295
0
                case ViewType::Handout:
296
0
                    return EnumContext::Context::HandoutPage;
297
0
                case ViewType::Notes:
298
0
                    return EnumContext::Context::NotesPage;
299
0
                default:
300
0
                    return EnumContext::Context::Unknown;
301
0
            }
302
303
0
        default:
304
0
            return EnumContext::Context::Unknown;
305
0
    }
306
0
}
307
308
SdrInventor SelectionAnalyzer::GetInventorTypeFromMark(const SdrMarkList& rMarkList)
309
0
{
310
0
    const size_t nMarkCount(rMarkList.GetMarkCount());
311
312
0
    if (nMarkCount < 1)
313
0
        return SdrInventor::Unknown;
314
315
0
    SdrMark* pMark = rMarkList.GetMark(0);
316
0
    SdrObject* pObj = pMark->GetMarkedSdrObj();
317
0
    const SdrInventor nFirstInv = pObj->GetObjInventor();
318
319
0
    for (size_t nIndex = 1; nIndex < nMarkCount; ++nIndex)
320
0
    {
321
0
        pMark = rMarkList.GetMark(nIndex);
322
0
        pObj = pMark->GetMarkedSdrObj();
323
0
        const SdrInventor nInv(pObj->GetObjInventor());
324
325
0
        if (nInv != nFirstInv)
326
0
            return SdrInventor::Unknown;
327
0
    }
328
329
0
    return nFirstInv;
330
0
}
331
332
SdrObjKind SelectionAnalyzer::GetObjectTypeFromGroup(const SdrObject* pObj)
333
0
{
334
0
    SdrObjList* pObjList = pObj->GetSubList();
335
0
    if (pObjList)
336
0
    {
337
0
        const size_t nSubObjCount(pObjList->GetObjCount());
338
339
0
        if (nSubObjCount > 0)
340
0
        {
341
0
            SdrObject* pSubObj = pObjList->GetObj(0);
342
0
            SdrObjKind nResultType = pSubObj->GetObjIdentifier();
343
344
0
            if (nResultType == SdrObjKind::Group)
345
0
                nResultType = GetObjectTypeFromGroup(pSubObj);
346
347
0
            if (IsShapeType(nResultType))
348
0
                nResultType = SdrObjKind::CustomShape;
349
350
0
            if (IsTextObjType(nResultType))
351
0
                nResultType = SdrObjKind::Text;
352
353
0
            for (size_t nIndex = 1; nIndex < nSubObjCount; ++nIndex)
354
0
            {
355
0
                pSubObj = pObjList->GetObj(nIndex);
356
0
                SdrObjKind nType(pSubObj->GetObjIdentifier());
357
358
0
                if (nType == SdrObjKind::Group)
359
0
                    nType = GetObjectTypeFromGroup(pSubObj);
360
361
0
                if (IsShapeType(nType))
362
0
                    nType = SdrObjKind::CustomShape;
363
364
0
                if ((nType == SdrObjKind::CustomShape) && (nResultType == SdrObjKind::Text))
365
0
                    nType = SdrObjKind::Text;
366
367
0
                if (IsTextObjType(nType))
368
0
                    nType = SdrObjKind::Text;
369
370
0
                if ((nType == SdrObjKind::Text) && (nResultType == SdrObjKind::CustomShape))
371
0
                    nResultType = SdrObjKind::Text;
372
373
0
                if (nType != nResultType)
374
0
                    return SdrObjKind::NONE;
375
0
            }
376
377
0
            return nResultType;
378
0
        }
379
0
    }
380
381
0
    return SdrObjKind::NONE;
382
0
}
383
384
SdrObjKind SelectionAnalyzer::GetObjectTypeFromMark(const SdrMarkList& rMarkList)
385
0
{
386
0
    const size_t nMarkCount(rMarkList.GetMarkCount());
387
388
0
    if (nMarkCount < 1)
389
0
        return SdrObjKind::NONE;
390
391
0
    SdrMark* pMark = rMarkList.GetMark(0);
392
0
    SdrObject* pObj = pMark->GetMarkedSdrObj();
393
0
    SdrObjKind nResultType = pObj->GetObjIdentifier();
394
395
0
    if (nResultType == SdrObjKind::Group)
396
0
        nResultType = GetObjectTypeFromGroup(pObj);
397
398
0
    if (IsShapeType(nResultType))
399
0
        nResultType = SdrObjKind::CustomShape;
400
401
0
    if (IsTextObjType(nResultType))
402
0
        nResultType = SdrObjKind::Text;
403
404
0
    for (size_t nIndex = 1; nIndex < nMarkCount; ++nIndex)
405
0
    {
406
0
        pMark = rMarkList.GetMark(nIndex);
407
0
        pObj = pMark->GetMarkedSdrObj();
408
0
        SdrObjKind nType = pObj->GetObjIdentifier();
409
410
0
        if (nType == SdrObjKind::Group)
411
0
            nType = GetObjectTypeFromGroup(pObj);
412
413
0
        if (IsShapeType(nType))
414
0
            nType = SdrObjKind::CustomShape;
415
416
0
        if ((nType == SdrObjKind::CustomShape) && (nResultType == SdrObjKind::Text))
417
0
            nType = SdrObjKind::Text;
418
419
0
        if (IsTextObjType(nType))
420
0
            nType = SdrObjKind::Text;
421
422
0
        if ((nType == SdrObjKind::Text) && (nResultType == SdrObjKind::CustomShape))
423
0
            nResultType = SdrObjKind::Text;
424
425
0
        if (nType != nResultType)
426
0
            return SdrObjKind::NONE;
427
0
    }
428
429
0
    return nResultType;
430
0
}
431
432
bool SelectionAnalyzer::IsShapeType(const SdrObjKind nType)
433
0
{
434
0
    switch (nType)
435
0
    {
436
0
        case SdrObjKind::Line:
437
0
        case SdrObjKind::CircleArc:
438
0
        case SdrObjKind::PolyLine:
439
0
        case SdrObjKind::PathLine:
440
0
        case SdrObjKind::Rectangle:
441
0
        case SdrObjKind::CircleOrEllipse:
442
0
        case SdrObjKind::CircleSection:
443
0
        case SdrObjKind::CircleCut:
444
0
        case SdrObjKind::PathFill:
445
0
        case SdrObjKind::CustomShape:
446
0
        case SdrObjKind::Caption:
447
0
        case SdrObjKind::Measure:
448
0
        case SdrObjKind::Edge:
449
0
        case SdrObjKind::Polygon:
450
0
        case SdrObjKind::FreehandLine:
451
0
        case SdrObjKind::FreehandFill:
452
453
        // #122145# adding SdrObjKind::OLE2 since these also allow line/fill style and may
454
        // be multiselected/grouped with normal draw objects, e.g. math OLE objects
455
0
        case SdrObjKind::OLE2:
456
0
            return true;
457
458
0
        default:
459
0
            return false;
460
0
    }
461
0
}
462
463
bool SelectionAnalyzer::IsTextObjType(const SdrObjKind nType)
464
0
{
465
0
    switch (nType)
466
0
    {
467
0
        case SdrObjKind::Text:
468
0
        case SdrObjKind::TitleText:
469
0
        case SdrObjKind::OutlineText:
470
0
            return true;
471
472
0
        default:
473
0
            return false;
474
0
    }
475
0
}
476
477
} // end of namespace svx::sidebar
478
479
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */