Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/main/SelectionHelper.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 <SelectionHelper.hxx>
21
#include <ObjectIdentifier.hxx>
22
#include <Diagram.hxx>
23
#include <ChartModel.hxx>
24
25
#include <svx/svdpage.hxx>
26
#include <svx/svditer.hxx>
27
#include <svx/obj3d.hxx>
28
#include <svx/svdopath.hxx>
29
#include <vcl/svapp.hxx>
30
#include <basegfx/point/b2dpoint.hxx>
31
#include <osl/diagnose.h>
32
33
namespace chart
34
{
35
using namespace ::com::sun::star;
36
37
namespace
38
{
39
40
OUString lcl_getObjectName( SdrObject const * pObj )
41
0
{
42
0
    if(pObj)
43
0
       return pObj->GetName();
44
0
    return OUString();
45
0
}
46
47
void impl_selectObject( SdrObject* pObjectToSelect, DrawViewWrapper& rDrawViewWrapper )
48
0
{
49
0
    SolarMutexGuard aSolarGuard;
50
51
0
    if(pObjectToSelect)
52
0
    {
53
0
        SelectionHelper aSelectionHelper( pObjectToSelect );
54
0
        SdrObject* pMarkObj = aSelectionHelper.getObjectToMark();
55
0
        rDrawViewWrapper.setMarkHandleProvider(&aSelectionHelper);
56
0
        rDrawViewWrapper.MarkObject(pMarkObj);
57
0
        rDrawViewWrapper.setMarkHandleProvider(nullptr);
58
0
    }
59
0
}
60
61
}//anonymous namespace
62
63
bool Selection::hasSelection() const
64
0
{
65
0
    return m_aSelectedOID.isValid();
66
0
}
67
68
OUString const & Selection::getSelectedCID() const
69
0
{
70
0
    return m_aSelectedOID.getObjectCID();
71
0
}
72
73
uno::Reference< drawing::XShape > const & Selection::getSelectedAdditionalShape() const
74
0
{
75
0
    return m_aSelectedOID.getAdditionalShape();
76
0
}
77
78
bool Selection::setSelection( const OUString& rCID )
79
0
{
80
0
    if ( rCID != m_aSelectedOID.getObjectCID() )
81
0
    {
82
0
        m_aSelectedOID = ObjectIdentifier( rCID );
83
0
        return true;
84
0
    }
85
0
    return false;
86
0
}
87
88
bool Selection::setSelection( const uno::Reference< drawing::XShape >& xShape )
89
0
{
90
0
    if ( !( xShape == m_aSelectedOID.getAdditionalShape() ) )
91
0
    {
92
0
        clearSelection();
93
0
        m_aSelectedOID = ObjectIdentifier( xShape );
94
0
        return true;
95
0
    }
96
0
    return false;
97
0
}
98
99
void Selection::clearSelection()
100
0
{
101
0
    m_aSelectedOID = ObjectIdentifier();
102
0
    m_aSelectedOID_beforeMouseDown = ObjectIdentifier();
103
0
    m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
104
0
}
105
106
bool Selection::maybeSwitchSelectionAfterSingleClickWasEnsured()
107
0
{
108
0
    if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid()
109
0
         && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing != m_aSelectedOID )
110
0
    {
111
0
        m_aSelectedOID = m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing;
112
0
        m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
113
0
        return true;
114
0
    }
115
0
    return false;
116
0
}
117
118
void Selection::resetPossibleSelectionAfterSingleClickWasEnsured()
119
0
{
120
0
    if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
121
0
    {
122
0
        m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
123
0
    }
124
0
}
125
126
void Selection::remindSelectionBeforeMouseDown()
127
0
{
128
0
    m_aSelectedOID_beforeMouseDown = m_aSelectedOID;
129
0
}
130
131
bool Selection::isSelectionDifferentFromBeforeMouseDown() const
132
0
{
133
0
    return ( m_aSelectedOID != m_aSelectedOID_beforeMouseDown );
134
0
}
135
136
void Selection::applySelection( DrawViewWrapper* pDrawViewWrapper )
137
0
{
138
0
    if( !pDrawViewWrapper )
139
0
        return;
140
141
0
    {
142
0
        SolarMutexGuard aSolarGuard;
143
0
        pDrawViewWrapper->UnmarkAll();
144
0
    }
145
0
    SdrObject* pObjectToSelect = nullptr;
146
0
    if ( m_aSelectedOID.isAutoGeneratedObject() )
147
0
    {
148
0
        pObjectToSelect = pDrawViewWrapper->getNamedSdrObject( m_aSelectedOID.getObjectCID() );
149
0
    }
150
0
    else if( m_aSelectedOID.isAdditionalShape() )
151
0
    {
152
0
        pObjectToSelect = DrawViewWrapper::getSdrObject( m_aSelectedOID.getAdditionalShape() );
153
0
    }
154
155
0
    impl_selectObject( pObjectToSelect, *pDrawViewWrapper );
156
0
}
157
158
void Selection::adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper const * pDrawViewWrapper
159
                                       , bool bIsRightMouse, bool bWaitingForDoubleClick )
160
0
{
161
0
    if( !pDrawViewWrapper )
162
0
        return;
163
164
    //do not toggle multiclick selection if right clicked on the selected object or waiting for double click
165
0
    bool bAllowMultiClickSelectionChange = !bIsRightMouse && !bWaitingForDoubleClick;
166
167
0
    ObjectIdentifier aLastSelectedObject( m_aSelectedOID );
168
169
0
    SolarMutexGuard aSolarGuard;
170
171
    //bAllowMultiClickSelectionChange==true -> a second click on the same object can lead to a changed selection (e.g. series -> single data point)
172
173
    //get object to select:
174
0
    {
175
0
        m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
176
177
        //the search for the object to select starts with the hit object deepest in the grouping hierarchy (a leaf in the tree)
178
        //further we travel along the grouping hierarchy from child to parent
179
0
        SdrObject* pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
180
0
        m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );//name of pNewObj
181
182
        //ignore handle only objects for hit test
183
0
        while( pNewObj && m_aSelectedOID.getObjectCID().match( "HandlesOnly" ) )
184
0
        {
185
0
            pNewObj->SetMarkProtect(true);
186
0
            pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
187
0
            m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );
188
0
        }
189
190
        //accept only named objects while searching for the object to select
191
        //this call may change m_aSelectedOID
192
0
        if ( SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, true ) )
193
0
        {
194
            //if the so far found object is a multi click object further steps are necessary
195
0
            while( ObjectIdentifier::isMultiClickObject( m_aSelectedOID.getObjectCID() ) )
196
0
            {
197
0
                bool bSameObjectAsLastSelected = ( aLastSelectedObject == m_aSelectedOID );
198
0
                if( bSameObjectAsLastSelected )
199
0
                {
200
                    //if the same child is clicked again don't go up further
201
0
                    break;
202
0
                }
203
0
                if ( ObjectIdentifier::areSiblings( aLastSelectedObject.getObjectCID(), m_aSelectedOID.getObjectCID() ) )
204
0
                {
205
                    //if a sibling of the last selected object is clicked don't go up further
206
0
                    break;
207
0
                }
208
0
                ObjectIdentifier aLastChild = m_aSelectedOID;
209
0
                if ( !SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, false ) )
210
0
                {
211
                    //take the one found so far
212
0
                    break;
213
0
                }
214
                //if the last selected object is found don't go up further
215
                //but take the last child if selection change is allowed
216
0
                if ( aLastSelectedObject == m_aSelectedOID )
217
0
                {
218
0
                    if( bAllowMultiClickSelectionChange )
219
0
                    {
220
0
                        m_aSelectedOID = std::move(aLastChild);
221
0
                    }
222
0
                    else
223
0
                        m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = std::move(aLastChild);
224
0
                    break;
225
0
                }
226
0
            }
227
228
0
            OSL_ENSURE(m_aSelectedOID.isValid(), "somehow lost selected object");
229
0
        }
230
0
        else
231
0
        {
232
            //maybe an additional shape was hit
233
0
            if ( pNewObj )
234
0
            {
235
0
                m_aSelectedOID = ObjectIdentifier( uno::Reference< drawing::XShape >( pNewObj->getUnoShape(), uno::UNO_QUERY ) );
236
0
            }
237
0
            else
238
0
            {
239
0
                m_aSelectedOID = ObjectIdentifier();
240
0
            }
241
0
        }
242
243
0
        if ( !m_aSelectedOID.isAdditionalShape() )
244
0
        {
245
0
            OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );//@todo read CID from model
246
247
0
            if ( !m_aSelectedOID.isAutoGeneratedObject() )
248
0
            {
249
0
                m_aSelectedOID = ObjectIdentifier( aPageCID );
250
0
            }
251
252
            //check whether the diagram was hit but not selected (e.g. because it has no filling):
253
0
            OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
254
0
            OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
255
0
            bool bBackGroundHit = m_aSelectedOID.getObjectCID() == aPageCID || m_aSelectedOID.getObjectCID() == aWallCID || !m_aSelectedOID.isAutoGeneratedObject();
256
0
            if( bBackGroundHit )
257
0
            {
258
                //todo: if more than one diagram is available in future do check the list of all diagrams here
259
0
                SdrObject* pDiagram = pDrawViewWrapper->getNamedSdrObject( aDiagramCID );
260
0
                if( pDiagram )
261
0
                {
262
0
                    if( DrawViewWrapper::IsObjectHit( pDiagram, rMousePos ) )
263
0
                    {
264
0
                        m_aSelectedOID = ObjectIdentifier( aDiagramCID );
265
0
                    }
266
0
                }
267
0
            }
268
            //check whether the legend was hit but not selected (e.g. because it has no filling):
269
0
            if( bBackGroundHit || m_aSelectedOID.getObjectCID() == aDiagramCID )
270
0
            {
271
0
                OUString aLegendCID( ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::createParticleForLegend(nullptr) ) );//@todo read CID from model
272
0
                SdrObject* pLegend = pDrawViewWrapper->getNamedSdrObject( aLegendCID );
273
0
                if( pLegend )
274
0
                {
275
0
                    if( DrawViewWrapper::IsObjectHit( pLegend, rMousePos ) )
276
0
                    {
277
0
                        m_aSelectedOID = ObjectIdentifier( aLegendCID );
278
0
                    }
279
0
                }
280
0
            }
281
0
        }
282
0
    }
283
284
0
    if ( bIsRightMouse && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
285
0
    {
286
0
        m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
287
0
    }
288
0
}
289
290
bool Selection::isResizeableObjectSelected() const
291
0
{
292
0
    ObjectType eObjectType = m_aSelectedOID.getObjectType();
293
0
    switch( eObjectType )
294
0
    {
295
0
        case OBJECTTYPE_DIAGRAM:
296
0
        case OBJECTTYPE_DIAGRAM_WALL:
297
0
        case OBJECTTYPE_SHAPE:
298
0
        case OBJECTTYPE_LEGEND:
299
0
            return true;
300
0
        default:
301
0
            return false;
302
0
    }
303
0
}
304
305
bool Selection::isRotateableObjectSelected( const rtl::Reference<::chart::ChartModel>& xChartModel ) const
306
0
{
307
0
    return SelectionHelper::isRotateableObject( m_aSelectedOID.getObjectCID(), xChartModel );
308
0
}
309
310
bool Selection::isDragableObjectSelected() const
311
0
{
312
0
    return m_aSelectedOID.isDragableObject();
313
0
}
314
315
bool Selection::isTitleObjectSelected() const
316
0
{
317
0
    return m_aSelectedOID.getObjectType() == OBJECTTYPE_TITLE;
318
0
}
319
320
bool Selection::isAdditionalShapeSelected() const
321
0
{
322
0
    return m_aSelectedOID.isAdditionalShape();
323
0
}
324
325
bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
326
                                      , OUString& rOutName
327
                                      , bool bGivenObjectMayBeResult )
328
0
{
329
0
    SolarMutexGuard aSolarGuard;
330
    //find the deepest named group
331
0
    SdrObject* pObj = pInOutObject;
332
0
    if (!bGivenObjectMayBeResult && pObj)
333
0
        pObj = pObj->getParentSdrObjectFromSdrObject();
334
335
0
    for (; pObj; pObj = pObj->getParentSdrObjectFromSdrObject())
336
0
    {
337
0
        if (OUString aName = lcl_getObjectName(pObj); ObjectIdentifier::isCID(aName))
338
0
        {
339
0
            pInOutObject = pObj;
340
0
            rOutName = aName;
341
0
            return true;
342
0
        }
343
0
    }
344
0
    return false;
345
0
}
346
347
bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
348
                                      , ObjectIdentifier& rOutObject
349
                                      , bool bGivenObjectMayBeResult )
350
0
{
351
0
    OUString aName;
352
0
    if ( findNamedParent( pInOutObject, aName, bGivenObjectMayBeResult ) )
353
0
    {
354
0
        rOutObject = ObjectIdentifier( aName );
355
0
        return true;
356
0
    }
357
0
    return false;
358
0
}
359
360
bool SelectionHelper::isDragableObjectHitTwice( const Point& rMPos
361
                    , const OUString& rNameOfSelectedObject
362
                    , const DrawViewWrapper& rDrawViewWrapper )
363
0
{
364
0
    if(rNameOfSelectedObject.isEmpty())
365
0
        return false;
366
0
    if( !ObjectIdentifier::isDragableObject(rNameOfSelectedObject) )
367
0
        return false;
368
0
    SolarMutexGuard aSolarGuard;
369
0
    SdrObject* pObj = rDrawViewWrapper.getNamedSdrObject( rNameOfSelectedObject );
370
0
    return DrawViewWrapper::IsObjectHit( pObj, rMPos );
371
0
}
372
373
OUString SelectionHelper::getHitObjectCID(
374
    const Point& rMPos,
375
    DrawViewWrapper const & rDrawViewWrapper,
376
    bool bGetDiagramInsteadOf_Wall )
377
0
{
378
0
    SolarMutexGuard aSolarGuard;
379
0
    OUString aRet;
380
381
0
    SdrObject* pNewObj = rDrawViewWrapper.getHitObject(rMPos);
382
0
    aRet = lcl_getObjectName( pNewObj );//name of pNewObj
383
384
    //ignore handle only objects for hit test
385
0
    while( pNewObj && aRet.match("HandlesOnly") )
386
0
    {
387
0
        pNewObj->SetMarkProtect(true);
388
0
        pNewObj = rDrawViewWrapper.getHitObject(rMPos);
389
0
        aRet = lcl_getObjectName( pNewObj );
390
0
    }
391
392
    //accept only named objects while searching for the object to select
393
0
    if( !findNamedParent( pNewObj, aRet, true ) )
394
0
    {
395
0
        aRet.clear();
396
0
    }
397
398
0
    OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );//@todo read CID from model
399
    //get page when nothing was hit
400
0
    if( aRet.isEmpty() && !pNewObj )
401
0
    {
402
0
        aRet = aPageCID;
403
0
    }
404
405
    //get diagram instead wall or page if hit inside diagram
406
0
    if( !aRet.isEmpty() )
407
0
    {
408
0
        if( aRet == aPageCID )
409
0
        {
410
0
            OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
411
            //todo: if more than one diagram is available in future do check the list of all diagrams here
412
0
            SdrObject* pDiagram = rDrawViewWrapper.getNamedSdrObject( aDiagramCID );
413
0
            if( pDiagram )
414
0
            {
415
0
                if( DrawViewWrapper::IsObjectHit( pDiagram, rMPos ) )
416
0
                {
417
0
                    aRet = aDiagramCID;
418
0
                }
419
0
            }
420
0
        }
421
0
        else if( bGetDiagramInsteadOf_Wall )
422
0
        {
423
0
            OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
424
425
0
            if( aRet == aWallCID )
426
0
            {
427
0
                aRet = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
428
0
            }
429
0
        }
430
0
    }
431
432
0
    return aRet;
433
    // \\- solar mutex
434
0
}
435
436
bool SelectionHelper::isRotateableObject( std::u16string_view rCID
437
                    , const rtl::Reference<::chart::ChartModel>& xChartModel )
438
0
{
439
0
    if( !ObjectIdentifier::isRotateableObject( rCID ) )
440
0
        return false;
441
442
0
    sal_Int32 nDimensionCount = xChartModel->getFirstChartDiagram()->getDimension();
443
444
0
    return nDimensionCount == 3;
445
0
}
446
447
SelectionHelper::SelectionHelper( SdrObject* pSelectedObj )
448
0
                      : m_pSelectedObj( pSelectedObj ), m_pMarkObj(nullptr)
449
0
{
450
451
0
}
452
SelectionHelper::~SelectionHelper()
453
0
{
454
0
}
455
456
bool SelectionHelper::getFrameDragSingles()
457
0
{
458
    //true == green == surrounding handles
459
0
    return DynCastE3dObject( m_pSelectedObj) == nullptr;
460
0
}
461
462
SdrObject* SelectionHelper::getMarkHandlesObject( SdrObject* pObj )
463
0
{
464
0
    if(!pObj)
465
0
        return nullptr;
466
0
    OUString aName( lcl_getObjectName( pObj ) );
467
0
    if( aName.match("MarkHandles") || aName.match("HandlesOnly") )
468
0
        return pObj;
469
0
    if( !aName.isEmpty() )//don't get the markhandles of a different object
470
0
        return nullptr;
471
472
    //search for a child with name "MarkHandles" or "HandlesOnly"
473
0
    SolarMutexGuard aSolarGuard;
474
0
    SdrObjList* pSubList = pObj->GetSubList();
475
0
    if(pSubList)
476
0
    {
477
0
        SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
478
0
        while (aIterator.IsMore())
479
0
        {
480
0
            SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
481
0
            if( pMarkHandles )
482
0
                return pMarkHandles;
483
0
        }
484
0
    }
485
0
    return nullptr;
486
0
}
487
488
SdrObject* SelectionHelper::getObjectToMark()
489
0
{
490
    //return the selected object itself
491
    //or a specific other object if that exists
492
0
    SdrObject* pObj = m_pSelectedObj;
493
0
    m_pMarkObj = pObj;
494
495
    //search for a child with name "MarkHandles" or "HandlesOnly"
496
0
    if(pObj)
497
0
    {
498
0
        SolarMutexGuard aSolarGuard;
499
0
        SdrObjList* pSubList = pObj->GetSubList();
500
0
        if(pSubList)
501
0
        {
502
0
            SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
503
0
            while (aIterator.IsMore())
504
0
            {
505
0
                SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
506
0
                if( pMarkHandles )
507
0
                {
508
0
                    m_pMarkObj = pMarkHandles;
509
0
                    break;
510
0
                }
511
0
            }
512
0
        }
513
0
    }
514
0
    return m_pMarkObj;
515
0
}
516
517
E3dScene* SelectionHelper::getSceneToRotate( SdrObject* pObj )
518
0
{
519
    //search whether the object or one of its children is a 3D object
520
    //if so, return the accessory 3DScene
521
522
0
    E3dObject* pRotateable = nullptr;
523
524
0
    if(pObj)
525
0
    {
526
0
        pRotateable = DynCastE3dObject(pObj);
527
0
        if( !pRotateable )
528
0
        {
529
0
            SolarMutexGuard aSolarGuard;
530
0
            SdrObjList* pSubList = pObj->GetSubList();
531
0
            if(pSubList)
532
0
            {
533
0
                SdrObjListIter aIterator(pSubList, SdrIterMode::DeepWithGroups);
534
0
                while( aIterator.IsMore() && !pRotateable )
535
0
                {
536
0
                    pRotateable = DynCastE3dObject(aIterator.Next());
537
0
                }
538
0
            }
539
0
        }
540
0
    }
541
542
0
    E3dScene* pScene(nullptr);
543
544
0
    if(pRotateable)
545
0
    {
546
0
        SolarMutexGuard aSolarGuard;
547
0
        pScene = pRotateable->getRootE3dSceneFromE3dObject();
548
0
    }
549
550
0
    return pScene;
551
0
}
552
553
bool SelectionHelper::getMarkHandles( SdrHdlList& rHdlList )
554
0
{
555
0
    SolarMutexGuard aSolarGuard;
556
557
    //@todo -> more flexible handle creation
558
    //2 scenarios possible:
559
    //1. add an additional invisible shape as a child to the selected object
560
    //this child needs to be named somehow and handles need to be generated there from...
561
    //or 2. offer a central service per view where renderer and so can register for handle creation for a special shape
562
    //.. or 3. feature from drawinglayer to create handles for each shape... (bad performance... ?) ?
563
564
    //scenario 1 is now used:
565
    //if a child with name MarkHandles exists
566
    //this child is marked instead of the logical selected object
567
568
/*
569
    //if a special mark object was found
570
    //that object should be used for marking only
571
    if( m_pMarkObj != m_pSelectedObj)
572
        return false;
573
*/
574
    //if a special mark object was found
575
    //that object should be used to create handles from
576
0
    if( m_pMarkObj && m_pMarkObj != m_pSelectedObj)
577
0
    {
578
0
        rHdlList.Clear();
579
0
        if( auto pPathObj = dynamic_cast<const SdrPathObj*>( m_pMarkObj) )
580
0
        {
581
            //if th object is a polygon
582
            //from each point a handle is generated
583
0
            const ::basegfx::B2DPolyPolygon& rPolyPolygon = pPathObj->GetPathPoly();
584
0
            for( sal_uInt32 nN = 0; nN < rPolyPolygon.count(); nN++)
585
0
            {
586
0
                const ::basegfx::B2DPolygon& aPolygon(rPolyPolygon.getB2DPolygon(nN));
587
0
                for( sal_uInt32 nM = 0; nM < aPolygon.count(); nM++)
588
0
                {
589
0
                    const ::basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(nM));
590
0
                    rHdlList.AddHdl(std::make_unique<SdrHdl>(Point(basegfx::fround<tools::Long>(aPoint.getX()), basegfx::fround<tools::Long>(aPoint.getY())), SdrHdlKind::Poly));
591
0
                }
592
0
            }
593
0
            return true;
594
0
        }
595
0
        else
596
0
            return false; //use the special MarkObject for marking
597
0
    }
598
599
    //@todo:
600
    //add and document good marking defaults ...
601
602
0
    rHdlList.Clear();
603
604
0
    SdrObject* pObj = m_pSelectedObj;
605
0
    if(!pObj)
606
0
        return false;
607
0
    SdrObjList* pSubList = pObj->GetSubList();
608
0
    if( !pSubList )//no group object !pObj->IsGroupObject()
609
0
        return false;
610
611
0
    OUString aName( lcl_getObjectName( pObj ) );
612
0
    ObjectType eObjectType( ObjectIdentifier::getObjectType( aName ) );
613
0
    if( eObjectType == OBJECTTYPE_DATA_POINT
614
0
        || eObjectType == OBJECTTYPE_DATA_LABEL
615
0
        || eObjectType == OBJECTTYPE_LEGEND_ENTRY
616
0
        || eObjectType == OBJECTTYPE_AXIS_UNITLABEL )
617
0
    {
618
0
        return false;
619
0
    }
620
621
0
    SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
622
623
0
    while (aIterator.IsMore())
624
0
    {
625
0
        SdrObject* pSubObj = aIterator.Next();
626
0
        if( eObjectType == OBJECTTYPE_DATA_SERIES )
627
0
        {
628
0
            OUString aSubName( lcl_getObjectName( pSubObj ) );
629
0
            ObjectType eSubObjectType( ObjectIdentifier::getObjectType( aSubName ) );
630
0
            if( eSubObjectType!=OBJECTTYPE_DATA_POINT  )
631
0
                return false;
632
0
        }
633
634
0
        Point aPos = pSubObj->GetCurrentBoundRect().Center();
635
0
        rHdlList.AddHdl(std::make_unique<SdrHdl>(aPos,SdrHdlKind::Poly));
636
0
    }
637
0
    return true;
638
0
}
639
640
} //namespace chart
641
642
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */