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/func/fuconstr.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 <fuconstr.hxx>
21
22
#include <svx/svxids.hrc>
23
#include <svx/svdpagv.hxx>
24
#include <svx/xdef.hxx>
25
#include <svx/xfillit0.hxx>
26
#include <sfx2/dispatch.hxx>
27
#include <sfx2/viewfrm.hxx>
28
#include <tools/debug.hxx>
29
#include <svx/xflclit.hxx>
30
#include <svx/xlineit0.hxx>
31
#include <svx/xlnclit.hxx>
32
#include <docmodel/theme/Theme.hxx>
33
34
#include <app.hrc>
35
#include <strings.hrc>
36
#include <strings.hxx>
37
#include <fudraw.hxx>
38
#include <View.hxx>
39
#include <Window.hxx>
40
#include <ViewShell.hxx>
41
#include <drawdoc.hxx>
42
#include <FrameView.hxx>
43
#include <sdpage.hxx>
44
#include <sdresid.hxx>
45
#include <glob.hxx>
46
#include <comphelper/lok.hxx>
47
48
using namespace com::sun::star;
49
50
namespace sd {
51
52
53
FuConstruct::FuConstruct (
54
    ViewShell&      rViewSh,
55
    ::sd::Window*           pWin,
56
    ::sd::View*         pView,
57
    SdDrawDocument& rDoc,
58
    SfxRequest&     rReq)
59
0
    : FuDraw(rViewSh, pWin, pView, rDoc, rReq),
60
0
      bSelectionChanged(false)
61
0
{
62
0
}
63
64
bool FuConstruct::MouseButtonDown(const MouseEvent& rMEvt)
65
0
{
66
0
    bool bReturn = FuDraw::MouseButtonDown(rMEvt);
67
68
0
    bMBDown = true;
69
0
    bSelectionChanged = false;
70
71
0
    if ( mpView->IsAction() )
72
0
    {
73
0
        return true;
74
0
    }
75
76
0
    bFirstMouseMove = true;
77
0
    aDragTimer.Start();
78
79
0
    aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
80
0
    sal_uInt16 nHitLog = sal_uInt16 (mpWindow->PixelToLogic(Size(HITPIX,0)).Width());
81
82
0
    if (rMEvt.IsLeft() && mpView->IsExtendedMouseEventDispatcherEnabled())
83
0
    {
84
0
        mpWindow->CaptureMouse();
85
86
0
        SdrHdl* pHdl = mpView->PickHandle(aMDPos);
87
88
0
        const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
89
0
        if ( pHdl != nullptr || mpView->IsMarkedHit(aMDPos, nHitLog) )
90
0
        {
91
0
            sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
92
0
            mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog);
93
0
            bReturn = true;
94
0
        }
95
0
        else if ( rMarkList.GetMarkCount() != 0 )
96
0
        {
97
0
            mpView->UnmarkAll();
98
0
            bReturn = true;
99
0
        }
100
0
    }
101
102
0
    return bReturn;
103
0
}
104
105
bool FuConstruct::MouseMove(const MouseEvent& rMEvt)
106
0
{
107
0
    FuDraw::MouseMove(rMEvt);
108
109
0
    if (aDragTimer.IsActive() )
110
0
    {
111
0
        if( bFirstMouseMove )
112
0
            bFirstMouseMove = false;
113
0
        else
114
0
            aDragTimer.Stop();
115
0
    }
116
117
0
    Point aPix(rMEvt.GetPosPixel());
118
0
    Point aPnt( mpWindow->PixelToLogic(aPix) );
119
120
0
    if ( mpView->IsAction() )
121
0
    {
122
0
        ForceScroll(aPix);
123
0
        mpView->MovAction(aPnt);
124
0
    }
125
126
0
    return true;
127
0
}
128
129
bool FuConstruct::MouseButtonUp(const MouseEvent& rMEvt)
130
0
{
131
0
    bool bReturn = true;
132
133
0
    if (aDragTimer.IsActive() )
134
0
    {
135
0
        aDragTimer.Stop();
136
0
        bIsInDragMode = false;
137
0
    }
138
139
0
    FuDraw::MouseButtonUp(rMEvt);
140
141
0
    Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
142
143
0
    if ( mpView && mpView->IsDragObj() )
144
0
    {
145
0
        FrameView* pFrameView = mrViewShell.GetFrameView();
146
0
        bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
147
148
0
        if (bDragWithCopy)
149
0
        {
150
0
            bDragWithCopy = !mpView->IsPresObjSelected(false);
151
0
        }
152
153
0
        mpView->SetDragWithCopy(bDragWithCopy);
154
0
        mpView->EndDragObj( mpView->IsDragWithCopy() );
155
0
    }
156
0
    else if ( mpView && mpView->IsMarkObj() )
157
0
    {
158
0
        mpView->EndMarkObj();
159
0
    }
160
0
    else
161
0
    {
162
0
        bReturn = false;
163
0
    }
164
165
0
    if ( mpView &&  !mpView->IsAction() )
166
0
    {
167
0
        mpWindow->ReleaseMouse();
168
0
        sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
169
170
0
        const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
171
0
        if ( rMarkList.GetMarkCount() == 0 )
172
0
        {
173
0
            SdrPageView* pPV;
174
0
            sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
175
176
0
            SdrObject* pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV);
177
0
            if (!pObj)
178
0
            {
179
0
                mpView->MarkObj(aPnt, nHitLog);
180
0
            }
181
182
0
            mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
183
0
        }
184
0
        else if (rMEvt.IsLeft() && !rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() &&
185
0
                 !bSelectionChanged                   &&
186
0
                 std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
187
0
                 std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
188
0
        {
189
            // toggle between selection and rotation
190
0
            SdrObject* pSingleObj = nullptr;
191
192
0
            if (rMarkList.GetMarkCount()==1)
193
0
            {
194
0
                pSingleObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
195
0
            }
196
197
0
            const bool bTiledRendering = comphelper::LibreOfficeKit::isActive();
198
0
            if (!bTiledRendering && (mpView->GetDragMode() == SdrDragMode::Move && mpView->IsRotateAllowed() &&
199
0
                (mrViewShell.GetFrameView()->IsClickChangeRotation() ||
200
0
                 (pSingleObj && pSingleObj->GetObjInventor()==SdrInventor::E3d))))
201
0
            {
202
0
                mpView->SetDragMode(SdrDragMode::Rotate);
203
0
            }
204
0
            else
205
0
            {
206
0
                mpView->SetDragMode(SdrDragMode::Move);
207
0
            }
208
0
        }
209
0
    }
210
211
0
    sal_uInt16 nClicks = rMEvt.GetClicks();
212
213
0
    if (nClicks == 2 && rMEvt.IsLeft() && bMBDown &&
214
0
        !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift() )
215
0
    {
216
0
        DoubleClick(rMEvt);
217
0
    }
218
0
    bMBDown = false;
219
220
0
    return bReturn;
221
0
}
222
223
void FuConstruct::Activate()
224
0
{
225
0
    mpView->SetEditMode(SdrViewEditMode::Create);
226
0
    FuDraw::Activate();
227
0
}
228
229
void FuConstruct::Deactivate()
230
0
{
231
0
    FuDraw::Deactivate();
232
0
    mpView->SetEditMode(SdrViewEditMode::Edit);
233
0
}
234
235
bool FuConstruct::IsIgnoreUnexpectedMouseButtonUp()
236
0
{
237
    // tdf#153446 if there is a MouseButtonUp without a previous MouseButtonDown event,
238
    // the MouseButtonDown was probably swallowed by a gain-focus action,
239
    // and then this MouseButtonUp should be ignored
240
241
0
    if (bMBDown || bIsInDragMode)
242
0
        return false;
243
244
    // Don't ignore if there are pending mouse-initiated tasks to complete.
245
0
    return !mpView->IsDragObj() && !mpWindow->IsMouseCaptured() && !mpView->IsAction();
246
0
}
247
248
/**
249
 * set style sheet for the object to be created
250
 */
251
void FuConstruct::SetStyleSheet(SfxItemSet& rAttr, SdrObject* pObj)
252
0
{
253
0
    bool bUseFillStyle, bUseNoFillStyle;
254
0
    bUseFillStyle = bUseNoFillStyle = false;
255
256
0
    switch( nSlotId )
257
0
    {
258
0
    case SID_DRAW_RECT:
259
0
    case SID_DRAW_RECT_ROUND:
260
0
    case SID_DRAW_SQUARE:
261
0
    case SID_DRAW_SQUARE_ROUND:
262
0
    case SID_DRAW_ELLIPSE:
263
0
    case SID_DRAW_PIE:
264
0
    case SID_DRAW_ELLIPSECUT:
265
0
    case SID_DRAW_CIRCLE:
266
0
    case SID_DRAW_CIRCLEPIE:
267
0
    case SID_DRAW_CIRCLECUT:
268
0
    case SID_DRAW_POLYGON:
269
0
    case SID_DRAW_XPOLYGON:
270
0
    case SID_DRAW_FREELINE:
271
0
    case SID_DRAW_BEZIER_FILL:
272
0
    {
273
0
        bUseFillStyle = true;
274
0
        break;
275
0
    }
276
0
    case  SID_DRAW_RECT_NOFILL:
277
0
    case SID_DRAW_RECT_ROUND_NOFILL:
278
0
    case SID_DRAW_SQUARE_NOFILL:
279
0
    case SID_DRAW_SQUARE_ROUND_NOFILL:
280
0
    case SID_DRAW_ELLIPSE_NOFILL:
281
0
    case SID_DRAW_PIE_NOFILL:
282
0
    case SID_DRAW_ELLIPSECUT_NOFILL:
283
0
    case SID_DRAW_CIRCLE_NOFILL:
284
0
    case SID_DRAW_CIRCLEPIE_NOFILL:
285
0
    case SID_DRAW_CIRCLECUT_NOFILL:
286
0
    case SID_DRAW_POLYGON_NOFILL:
287
0
    case SID_DRAW_XPOLYGON_NOFILL:
288
0
    case SID_DRAW_FREELINE_NOFILL:
289
0
    case SID_DRAW_LINE:
290
0
    case SID_DRAW_XLINE:
291
0
    case SID_CONNECTOR_ARROW_START:
292
0
    case SID_CONNECTOR_ARROW_END:
293
0
    case SID_CONNECTOR_ARROWS:
294
0
    case SID_CONNECTOR_CIRCLE_START:
295
0
    case SID_CONNECTOR_CIRCLE_END:
296
0
    case SID_CONNECTOR_CIRCLES:
297
0
    case SID_CONNECTOR_LINE:
298
0
    case SID_CONNECTOR_LINE_ARROW_START:
299
0
    case SID_CONNECTOR_LINE_ARROW_END:
300
0
    case SID_CONNECTOR_LINE_ARROWS:
301
0
    case SID_CONNECTOR_LINE_CIRCLE_START:
302
0
    case SID_CONNECTOR_LINE_CIRCLE_END:
303
0
    case SID_CONNECTOR_LINE_CIRCLES:
304
0
    case SID_CONNECTOR_CURVE:
305
0
    case SID_CONNECTOR_CURVE_ARROW_START:
306
0
    case SID_CONNECTOR_CURVE_ARROW_END:
307
0
    case SID_CONNECTOR_CURVE_ARROWS:
308
0
    case SID_CONNECTOR_CURVE_CIRCLE_START:
309
0
    case SID_CONNECTOR_CURVE_CIRCLE_END:
310
0
    case SID_CONNECTOR_CURVE_CIRCLES:
311
0
    case SID_CONNECTOR_LINES:
312
0
    case SID_CONNECTOR_LINES_ARROW_START:
313
0
    case SID_CONNECTOR_LINES_ARROW_END:
314
0
    case SID_CONNECTOR_LINES_ARROWS:
315
0
    case SID_CONNECTOR_LINES_CIRCLE_START:
316
0
    case SID_CONNECTOR_LINES_CIRCLE_END:
317
0
    case SID_CONNECTOR_LINES_CIRCLES:
318
0
    case SID_DRAW_BEZIER_NOFILL:
319
0
    case SID_LINE_ARROW_END:
320
0
    {
321
0
        bUseNoFillStyle = true;
322
0
        break;
323
0
    }
324
0
    }
325
0
    SetStyleSheet( rAttr, pObj, bUseFillStyle, bUseNoFillStyle );
326
0
}
327
328
void FuConstruct::SetStyleSheet( SfxItemSet& rAttr, SdrObject* pObj,
329
        const bool bForceFillStyle, const bool bForceNoFillStyle )
330
0
{
331
0
    SdPage* pPage = static_cast<SdPage*>(mpView->GetSdrPageView()->GetPage());
332
0
    if ( pPage->IsMasterPage() && pPage->GetPageKind() == PageKind::Standard &&
333
0
         mrDoc.GetDocumentType() == DocumentType::Impress )
334
0
    {
335
        /**********************************************
336
        * Objects was created on the slide master page
337
        ***********************************************/
338
0
        OUString aName( pPage->GetLayoutName() );
339
0
        sal_Int32 n = aName.indexOf(SD_LT_SEPARATOR) + SD_LT_SEPARATOR.getLength();
340
0
        aName = OUString::Concat(aName.subView(0, n)) + STR_LAYOUT_BACKGROUNDOBJECTS;
341
0
        SfxStyleSheet* pSheet(
342
0
            static_cast< SfxStyleSheet* >(
343
0
                pPage->getSdrModelFromSdrPage().GetStyleSheetPool()->Find(aName, SfxStyleFamily::Page)));
344
0
        DBG_ASSERT(pSheet, "StyleSheet missing");
345
0
        if (pSheet)
346
0
        {
347
            // applying style sheet for background objects
348
0
            pObj->SetStyleSheet(pSheet, false);
349
0
            SfxItemSet& rSet = pSheet->GetItemSet();
350
0
            const XFillStyleItem& rFillStyle = rSet.Get(XATTR_FILLSTYLE);
351
0
            if ( bForceFillStyle )
352
0
            {
353
0
                if (rFillStyle.GetValue() == drawing::FillStyle_NONE)
354
0
                    rAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
355
0
            }
356
0
            else if ( bForceNoFillStyle )
357
0
            {
358
0
                if (rFillStyle.GetValue() != drawing::FillStyle_NONE)
359
0
                    rAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
360
0
            }
361
0
        }
362
0
    }
363
0
    else
364
0
    {
365
        /***********************************
366
        * object was created on normal page
367
        ************************************/
368
0
        if ( bForceNoFillStyle )
369
0
        {
370
0
            OUString aName(SdResId(STR_POOLSHEET_OBJWITHOUTFILL));
371
0
            SfxStyleSheet* pSheet(
372
0
                static_cast< SfxStyleSheet* >(
373
0
                    pPage->getSdrModelFromSdrPage().GetStyleSheetPool()->Find(aName, SfxStyleFamily::Para)));
374
0
            DBG_ASSERT(pSheet, "Stylesheet missing");
375
0
            if (pSheet)
376
0
            {
377
0
                pObj->SetStyleSheet(pSheet, false);
378
0
                SfxItemSet aAttr(mpView->GetDefaultAttr());
379
0
                aAttr.Put(pSheet->GetItemSet().Get(XATTR_FILLSTYLE));
380
0
                pObj->SetMergedItemSet(aAttr);
381
0
            }
382
0
            else
383
0
            {
384
0
                SfxItemSet aAttr(mpView->GetDefaultAttr());
385
0
                rAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
386
0
                pObj->SetMergedItemSet(aAttr);
387
0
            }
388
0
        }
389
0
    }
390
0
}
391
392
} // end of namespace sd
393
394
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */