Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/view/drbezob.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 <BezierObjectBar.hxx>
21
#include <sfx2/msg.hxx>
22
#include <sfx2/viewfrm.hxx>
23
#include <sfx2/objface.hxx>
24
25
#include <svx/svxids.hrc>
26
#include <svl/eitem.hxx>
27
#include <sfx2/request.hxx>
28
#include <svx/svdopath.hxx>
29
#include <svx/svdundo.hxx>
30
#include <sfx2/dispatch.hxx>
31
32
#include <sdresid.hxx>
33
34
35
#include <strings.hrc>
36
37
#include <DrawDocShell.hxx>
38
#include <ViewShell.hxx>
39
#include <drawdoc.hxx>
40
#include <fusel.hxx>
41
#include <fuconbez.hxx>
42
43
using namespace sd;
44
#define ShellClass_BezierObjectBar
45
#include <sdslots.hxx>
46
47
namespace sd {
48
49
/**
50
 * Declare default interface (Slotmap must not be empty)
51
 */
52
SFX_IMPL_INTERFACE(BezierObjectBar, ::SfxShell)
53
54
void BezierObjectBar::InitInterface_Impl()
55
6
{
56
6
}
57
58
59
BezierObjectBar::BezierObjectBar(
60
    ViewShell& rSdViewShell,
61
    ::sd::View* pSdView)
62
0
    : SfxShell(rSdViewShell.GetViewShell()),
63
0
      mpView(pSdView),
64
0
      mrViewSh(rSdViewShell)
65
0
{
66
0
    DrawDocShell* pDocShell = mrViewSh.GetDocSh();
67
0
    SetPool(&pDocShell->GetPool());
68
0
    SetUndoManager(pDocShell->GetUndoManager());
69
0
    SetRepeatTarget(mpView);
70
0
}
71
72
BezierObjectBar::~BezierObjectBar()
73
0
{
74
0
    SetRepeatTarget(nullptr);
75
0
}
76
77
/**
78
 * Status of attribute items.
79
 */
80
81
void BezierObjectBar::GetAttrState(SfxItemSet& rSet)
82
0
{
83
0
    SfxItemSet aAttrSet( mpView->GetDoc().GetPool() );
84
0
    mpView->GetAttributes( aAttrSet );
85
0
    rSet.Put(aAttrSet, false); // <- sal_False, so DontCare-Status gets acquired
86
87
0
    rtl::Reference<FuPoor> xFunc( mrViewSh.GetCurrentFunction() );
88
89
0
    if(xFunc.is())
90
0
    {
91
0
        if( auto pFuSelection = dynamic_cast< const FuSelection *>( xFunc.get() ))
92
0
        {
93
0
            sal_uInt16 nEditMode = pFuSelection->GetEditMode();
94
0
            rSet.Put(SfxBoolItem(nEditMode, true));
95
0
        }
96
0
        else if( auto pFuPolygon = dynamic_cast< const FuConstructBezierPolygon *>( xFunc.get() ))
97
0
        {
98
0
            sal_uInt16 nEditMode = pFuPolygon->GetEditMode();
99
0
            rSet.Put(SfxBoolItem(nEditMode, true));
100
0
        }
101
0
    }
102
103
0
    if(!mpView->IsMoveAllowed() || !mpView->IsResizeAllowed())
104
0
    {
105
        // #i77187# if object is move and/or size protected, do not allow point editing at all
106
0
        rSet.DisableItem(SID_BEZIER_MOVE);
107
0
        rSet.DisableItem(SID_BEZIER_INSERT);
108
109
0
        rSet.DisableItem(SID_BEZIER_DELETE);
110
0
        rSet.DisableItem(SID_BEZIER_CUTLINE);
111
0
        rSet.DisableItem(SID_BEZIER_CONVERT);
112
113
0
        rSet.DisableItem(SID_BEZIER_EDGE);
114
0
        rSet.DisableItem(SID_BEZIER_SMOOTH);
115
0
        rSet.DisableItem(SID_BEZIER_SYMMTR);
116
117
0
        rSet.DisableItem(SID_BEZIER_CLOSE);
118
119
0
        rSet.DisableItem(SID_BEZIER_ELIMINATE_POINTS);
120
0
    }
121
0
    else
122
0
    {
123
0
        IPolyPolygonEditorController* pIPPEC = nullptr;
124
0
        const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
125
0
        if( rMarkList.GetMarkCount() )
126
0
            pIPPEC = mpView;
127
0
        else
128
0
            pIPPEC = dynamic_cast< IPolyPolygonEditorController* >( mpView->getSmartTags().getSelected().get() );
129
130
0
        if ( !pIPPEC || !pIPPEC->IsRipUpAtMarkedPointsPossible())
131
0
        {
132
0
            rSet.DisableItem(SID_BEZIER_CUTLINE);
133
0
        }
134
0
        if (!pIPPEC || !pIPPEC->IsDeleteMarkedPointsPossible())
135
0
        {
136
0
            rSet.DisableItem(SID_BEZIER_DELETE);
137
0
        }
138
0
        if (!pIPPEC || !pIPPEC->IsSetMarkedSegmentsKindPossible())
139
0
        {
140
0
            rSet.DisableItem(SID_BEZIER_CONVERT);
141
0
        }
142
0
        else
143
0
        {
144
0
            SdrPathSegmentKind eSegm = pIPPEC->GetMarkedSegmentsKind();
145
0
            switch (eSegm)
146
0
            {
147
0
                case SdrPathSegmentKind::DontCare: rSet.InvalidateItem(SID_BEZIER_CONVERT); break;
148
0
                case SdrPathSegmentKind::Line    : rSet.Put(SfxBoolItem(SID_BEZIER_CONVERT,false)); break; // Button down = curve
149
0
                case SdrPathSegmentKind::Curve   : rSet.Put(SfxBoolItem(SID_BEZIER_CONVERT,true));  break;
150
0
                default: break;
151
0
            }
152
0
        }
153
0
        if (!pIPPEC || !pIPPEC->IsSetMarkedPointsSmoothPossible())
154
0
        {
155
0
            rSet.DisableItem(SID_BEZIER_EDGE);
156
0
            rSet.DisableItem(SID_BEZIER_SMOOTH);
157
0
            rSet.DisableItem(SID_BEZIER_SYMMTR);
158
0
        }
159
0
        else
160
0
        {
161
0
            SdrPathSmoothKind eSmooth = pIPPEC->GetMarkedPointsSmooth();
162
0
            switch (eSmooth)
163
0
            {
164
0
                case SdrPathSmoothKind::DontCare  : break;
165
0
                case SdrPathSmoothKind::Angular   : rSet.Put(SfxBoolItem(SID_BEZIER_EDGE,  true)); break;
166
0
                case SdrPathSmoothKind::Asymmetric: rSet.Put(SfxBoolItem(SID_BEZIER_SMOOTH,true)); break;
167
0
                case SdrPathSmoothKind::Symmetric : rSet.Put(SfxBoolItem(SID_BEZIER_SYMMTR,true)); break;
168
0
            }
169
0
        }
170
0
        if (!pIPPEC || !pIPPEC->IsOpenCloseMarkedObjectsPossible())
171
0
        {
172
0
            rSet.DisableItem(SID_BEZIER_CLOSE);
173
0
        }
174
0
        else
175
0
        {
176
0
            SdrObjClosedKind eClose = pIPPEC->GetMarkedObjectsClosedState();
177
0
            switch (eClose)
178
0
            {
179
0
                case SdrObjClosedKind::DontCare: rSet.InvalidateItem(SID_BEZIER_CLOSE); break;
180
0
                case SdrObjClosedKind::Open    : rSet.Put(SfxBoolItem(SID_BEZIER_CLOSE,false)); break;
181
0
                case SdrObjClosedKind::Closed  : rSet.Put(SfxBoolItem(SID_BEZIER_CLOSE,true)); break;
182
0
                default: break;
183
0
            }
184
0
        }
185
186
0
        if(pIPPEC == mpView)
187
0
            rSet.Put(SfxBoolItem(SID_BEZIER_ELIMINATE_POINTS, mpView->IsEliminatePolyPoints()));
188
0
        else
189
0
            rSet.DisableItem( SID_BEZIER_ELIMINATE_POINTS ); // only works for views
190
0
    }
191
0
}
192
193
/**
194
 * Process SfxRequests
195
 */
196
197
void BezierObjectBar::Execute(SfxRequest& rReq)
198
0
{
199
0
    sal_uInt16 nSId = rReq.GetSlot();
200
201
0
    switch (nSId)
202
0
    {
203
0
        case SID_BEZIER_CUTLINE:
204
0
        case SID_BEZIER_CONVERT:
205
0
        case SID_BEZIER_DELETE:
206
0
        case SID_BEZIER_EDGE:
207
0
        case SID_BEZIER_SMOOTH:
208
0
        case SID_BEZIER_SYMMTR:
209
0
        case SID_BEZIER_CLOSE:
210
0
        {
211
0
            assert(mpView);
212
0
            const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
213
214
0
            IPolyPolygonEditorController* pIPPEC = nullptr;
215
0
            if( rMarkList.GetMarkCount() )
216
0
                pIPPEC = mpView;
217
0
            else
218
0
                pIPPEC = dynamic_cast< IPolyPolygonEditorController* >( mpView->getSmartTags().getSelected().get() );
219
220
0
            if( pIPPEC && !mpView->IsAction())
221
0
            {
222
0
                switch (nSId)
223
0
                {
224
0
                    case SID_BEZIER_DELETE:
225
0
                        pIPPEC->DeleteMarkedPoints();
226
0
                        break;
227
228
0
                    case SID_BEZIER_CUTLINE:
229
0
                        pIPPEC->RipUpAtMarkedPoints();
230
0
                        break;
231
232
0
                    case SID_BEZIER_CONVERT:
233
0
                    {
234
0
                        pIPPEC->SetMarkedSegmentsKind(SdrPathSegmentKind::Toggle);
235
0
                        break;
236
0
                    }
237
238
0
                    case SID_BEZIER_EDGE:
239
0
                    case SID_BEZIER_SMOOTH:
240
0
                    case SID_BEZIER_SYMMTR:
241
0
                    {
242
0
                        SdrPathSmoothKind eKind;
243
244
0
                        switch (nSId)
245
0
                        {
246
0
                            default:
247
0
                            case SID_BEZIER_EDGE:   eKind = SdrPathSmoothKind::Angular; break;
248
0
                            case SID_BEZIER_SMOOTH: eKind = SdrPathSmoothKind::Asymmetric; break;
249
0
                            case SID_BEZIER_SYMMTR: eKind = SdrPathSmoothKind::Symmetric; break;
250
0
                        }
251
252
0
                        pIPPEC->SetMarkedPointsSmooth(eKind);
253
0
                        break;
254
0
                    }
255
256
0
                    case SID_BEZIER_CLOSE:
257
0
                    {
258
0
                        SdrPathObj* pPathObj = static_cast<SdrPathObj*>( rMarkList.GetMark(0)->GetMarkedSdrObj() );
259
0
                        const bool bUndo = mpView->IsUndoEnabled();
260
0
                        if( bUndo )
261
0
                            mpView->BegUndo(SdResId(STR_UNDO_BEZCLOSE));
262
263
0
                        mpView->UnmarkAllPoints();
264
265
0
                        if( bUndo )
266
0
                            mpView->AddUndo(mpView->GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pPathObj));
267
268
0
                        pPathObj->ToggleClosed();
269
270
0
                        if( bUndo )
271
0
                            mpView->EndUndo();
272
0
                        break;
273
0
                    }
274
0
                }
275
0
            }
276
277
0
            if( (pIPPEC == mpView) && rMarkList.GetMarkCount() == 0 )
278
0
                mrViewSh.GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
279
280
0
            rReq.Ignore();
281
0
        }
282
0
        break;
283
284
0
        case SID_BEZIER_ELIMINATE_POINTS:
285
0
        {
286
0
            mpView->SetEliminatePolyPoints(!mpView->IsEliminatePolyPoints());
287
0
            Invalidate(SID_BEZIER_ELIMINATE_POINTS);
288
0
            rReq.Done();
289
0
        }
290
0
        break;
291
292
0
        case SID_BEZIER_MOVE:
293
0
        case SID_BEZIER_INSERT:
294
0
        {
295
0
            rtl::Reference<FuPoor> xFunc( mrViewSh.GetCurrentFunction() );
296
297
0
            if(xFunc.is())
298
0
            {
299
0
                if( auto pFuSelection = dynamic_cast<FuSelection *>( xFunc.get() ))
300
0
                {
301
0
                    pFuSelection->SetEditMode(rReq.GetSlot());
302
0
                }
303
0
                else if( auto pFuPolygon = dynamic_cast<FuConstructBezierPolygon *>( xFunc.get() ))
304
0
                {
305
0
                    pFuPolygon->SetEditMode(rReq.GetSlot());
306
0
                }
307
0
            }
308
309
0
            rReq.Ignore ();
310
0
        }
311
0
        break;
312
313
0
        default:
314
0
        break;
315
0
    }
316
317
0
    Invalidate();
318
0
}
319
320
} // end of namespace sd
321
322
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */