Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/uiview/viewdraw.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 <hintids.hxx>
21
#include <svl/itempool.hxx>
22
#include <svl/stritem.hxx>
23
#include <svx/svdobj.hxx>
24
#include <svx/svdview.hxx>
25
#include <svx/svdpage.hxx>
26
#include <editeng/outliner.hxx>
27
#include <svx/fmview.hxx>
28
#include <svx/dataaccessdescriptor.hxx>
29
#include <sfx2/viewfrm.hxx>
30
#include <doc.hxx>
31
#include <IDocumentDeviceAccess.hxx>
32
#include <textboxhelper.hxx>
33
#include <editeng/langitem.hxx>
34
#include <svx/fontworkbar.hxx>
35
#include <svx/fontworkgallery.hxx>
36
#include <editeng/eeitem.hxx>
37
#include <svx/svdogrp.hxx>
38
#include <svx/svdetc.hxx>
39
#include <editeng/editstat.hxx>
40
#include <sfx2/request.hxx>
41
#include <sfx2/bindings.hxx>
42
#include <sfx2/dispatch.hxx>
43
#include <svx/svdoutl.hxx>
44
#include <vcl/ptrstyle.hxx>
45
#include <osl/diagnose.h>
46
47
#include <view.hxx>
48
#include <wrtsh.hxx>
49
#include <viewopt.hxx>
50
#include <cmdid.h>
51
#include <drwbassh.hxx>
52
#include <beziersh.hxx>
53
#include <conrect.hxx>
54
#include <conpoly.hxx>
55
#include <conarc.hxx>
56
#include <conform.hxx>
57
#include <concustomshape.hxx>
58
#include <dselect.hxx>
59
#include <edtwin.hxx>
60
61
#include <dcontact.hxx>
62
63
#include <svx/svdpagv.hxx>
64
#include <svx/extrusionbar.hxx>
65
#include <comphelper/lok.hxx>
66
#include <sfx2/lokhelper.hxx>
67
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
68
69
using namespace ::com::sun::star;
70
71
// Execute Drawing-Ids
72
73
void SwView::ExecDraw(const SfxRequest& rReq)
74
0
{
75
0
    const SfxItemSet *pArgs = rReq.GetArgs();
76
0
    const SfxPoolItem* pItem;
77
0
    const SfxStringItem* pStringItem = nullptr;
78
0
    SdrView *pSdrView = m_pWrtShell->GetDrawView();
79
0
    bool bDeselect = false;
80
81
0
    sal_uInt16 nSlotId = rReq.GetSlot();
82
0
    if(pArgs && SfxItemState::SET == pArgs->GetItemState(GetPool().GetWhichIDFromSlotID(nSlotId), false, &pItem))
83
0
        pStringItem = dynamic_cast< const SfxStringItem*>(pItem);
84
85
0
    SdrObjKind eNewFormObjKind = SdrObjKind::NONE;
86
0
    if (nSlotId == SID_FM_CREATE_CONTROL)
87
0
    {
88
0
        const SfxUInt16Item* pIdentifierItem = rReq.GetArg(SID_FM_CONTROL_IDENTIFIER);
89
0
        if (pIdentifierItem)
90
0
            eNewFormObjKind = static_cast<SdrObjKind>(pIdentifierItem->GetValue());
91
0
    }
92
93
0
    if (nSlotId == SID_OBJECT_SELECT && m_nFormSfxId == nSlotId)
94
0
    {
95
0
        bDeselect = true;
96
0
    }
97
0
    else if (nSlotId == SID_FM_CREATE_CONTROL)
98
0
    {
99
0
        if (eNewFormObjKind == m_eFormObjKind || eNewFormObjKind == SdrObjKind::NONE)
100
0
        {
101
0
            bDeselect = true;
102
0
            GetViewFrame().GetDispatcher()->Execute(SID_FM_LEAVE_CREATE);  // Button should popping out
103
0
        }
104
0
    }
105
0
    else if (nSlotId == SID_FM_CREATE_FIELDCONTROL)
106
0
    {
107
0
        FmFormView* pFormView = dynamic_cast<FmFormView*>(pSdrView);
108
0
        if (pFormView)
109
0
        {
110
0
            const SfxUnoAnyItem* pDescriptorItem = rReq.GetArg<SfxUnoAnyItem>(SID_FM_DATACCESS_DESCRIPTOR);
111
0
            OSL_ENSURE( pDescriptorItem, "SwView::ExecDraw(SID_FM_CREATE_FIELDCONTROL): invalid request args!" );
112
0
            if( pDescriptorItem )
113
0
            {
114
0
                svx::ODataAccessDescriptor aDescriptor( pDescriptorItem->GetValue() );
115
0
                rtl::Reference<SdrObject> pObj = pFormView->CreateFieldControl( aDescriptor );
116
117
0
                if ( pObj )
118
0
                {
119
0
                    Size aDocSize(m_pWrtShell->GetDocSize());
120
0
                    const SwRect& rVisArea = m_pWrtShell->VisArea();
121
0
                    Point aStartPos = rVisArea.Center();
122
0
                    if(rVisArea.Width() > aDocSize.Width())
123
0
                        aStartPos.setX( aDocSize.Width() / 2 + rVisArea.Left() );
124
0
                    if(rVisArea.Height() > aDocSize.Height())
125
0
                        aStartPos.setY( aDocSize.Height() / 2 + rVisArea.Top() );
126
127
                    //determine the size of the object
128
0
                    if(pObj->IsGroupObject())
129
0
                    {
130
0
                        const tools::Rectangle& rBoundRect = static_cast<SdrObjGroup*>(pObj.get())->GetCurrentBoundRect();
131
0
                        aStartPos.AdjustX( -(rBoundRect.GetWidth()/2) );
132
0
                        aStartPos.AdjustY( -(rBoundRect.GetHeight()/2) );
133
0
                    }
134
135
                    // TODO: unmark all other
136
0
                    m_pWrtShell->EnterStdMode();
137
0
                    m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aStartPos );
138
0
                }
139
0
            }
140
0
        }
141
0
    }
142
0
    else if ( nSlotId == SID_FONTWORK_GALLERY_FLOATER )
143
0
    {
144
0
        vcl::Window& rWin = m_pWrtShell->GetView().GetViewFrame().GetWindow();
145
146
0
        rWin.EnterWait();
147
148
0
        if( !m_pWrtShell->HasDrawView() )
149
0
            m_pWrtShell->MakeDrawView();
150
151
0
        pSdrView = m_pWrtShell->GetDrawView();
152
0
        if (pSdrView)
153
0
        {
154
0
            std::shared_ptr<svx::FontWorkGalleryDialog> pDlg = std::make_shared<svx::FontWorkGalleryDialog>(rWin.GetFrameWeld(), *pSdrView, GetFrame()->GetBindings().GetActiveFrame());
155
0
            pDlg->SetSdrObjectRef(&pSdrView->GetModel());
156
0
            weld::DialogController::runAsync(pDlg, [this, pDlg](int) {
157
0
                vcl::Window& rWin2 = m_pWrtShell->GetView().GetViewFrame().GetWindow();
158
159
0
                SdrObject* pObj = pDlg->GetSdrObjectRef();
160
0
                if ( pObj )
161
0
                {
162
0
                    Size            aDocSize( m_pWrtShell->GetDocSize() );
163
0
                    const SwRect    aVisArea = comphelper::LibreOfficeKit::isActive() ?
164
0
                                                SwRect(m_pWrtShell->getLOKVisibleArea()) : m_pWrtShell->VisArea();
165
0
                    Point           aPos( aVisArea.Center() );
166
0
                    tools::Rectangle aObjRect( pObj->GetLogicRect() );
167
168
0
                    if ( aVisArea.Width() > aDocSize.Width())
169
0
                        aPos.setX( aDocSize.Width() / 2 + aVisArea.Left() );
170
0
                    else if (aPos.getX() > aObjRect.GetWidth() / 2)
171
0
                         aPos.AdjustX( -(aObjRect.GetWidth() / 2) );
172
173
0
                    if (aVisArea.Height() > aDocSize.Height())
174
0
                        aPos.setY( aDocSize.Height() / 2 + aVisArea.Top() );
175
0
                    else if (aPos.getY() > aObjRect.GetHeight() / 2)
176
0
                         aPos.AdjustY( -(aObjRect.GetHeight() / 2) );
177
178
0
                    m_pWrtShell->EnterStdMode();
179
0
                    m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aPos );
180
0
                }
181
182
0
                rWin2.LeaveWait();
183
0
            });
184
0
        }
185
0
        else
186
0
            rWin.LeaveWait();
187
0
    }
188
0
    else if ( m_nFormSfxId != USHRT_MAX )
189
0
        GetViewFrame().GetDispatcher()->Execute( SID_FM_LEAVE_CREATE );
190
191
0
    if( nSlotId == SID_DRAW_CS_ID )
192
0
    {
193
        //deselect if same custom shape is selected again
194
0
        SwDrawBase* pFuncPtr = GetDrawFuncPtr();
195
0
        if( pFuncPtr && pFuncPtr->GetSlotId() == SID_DRAW_CS_ID )
196
0
        {
197
0
            ConstCustomShape* pConstCustomShape = static_cast<ConstCustomShape*>(pFuncPtr);
198
0
            OUString aNew = ConstCustomShape::GetShapeTypeFromRequest( rReq );
199
0
            const OUString& aOld = pConstCustomShape->GetShapeType();
200
0
            if( aNew == aOld )
201
0
            {
202
0
                bDeselect = true;
203
0
            }
204
0
        }
205
0
    }
206
207
    //deselect if same shape is selected again (but different custom shapes do have same slot id)
208
0
    if ( bDeselect || (nSlotId == m_nDrawSfxId &&
209
0
            (!pStringItem || (pStringItem->GetValue() == m_sDrawCustom))
210
0
                && (nSlotId != SID_DRAW_CS_ID) ) )
211
0
    {
212
0
        if (GetDrawFuncPtr())
213
0
        {
214
0
            GetDrawFuncPtr()->Deactivate();
215
0
            SetDrawFuncPtr(nullptr);
216
0
        }
217
218
0
        if (m_pWrtShell->GetSelectedObjCount() && !m_pWrtShell->IsSelFrameMode())
219
0
            m_pWrtShell->EnterSelFrameMode();
220
0
        LeaveDrawCreate();
221
222
0
        AttrChangedNotify(nullptr);
223
0
        return;
224
0
    }
225
226
0
    LeaveDrawCreate();
227
228
0
    if (m_pWrtShell->IsFrameSelected())
229
0
        m_pWrtShell->EnterStdMode();  // because bug #45639
230
231
0
    std::unique_ptr<SwDrawBase> pFuncPtr;
232
233
    // for LibreOfficeKit - choosing a shape should construct it directly
234
0
    bool bCreateDirectly = false;
235
236
0
    switch (nSlotId)
237
0
    {
238
0
        case SID_OBJECT_SELECT:
239
0
        case SID_DRAW_SELECT:
240
0
            pFuncPtr.reset( new DrawSelection(m_pWrtShell.get(), m_pEditWin, *this) );
241
0
            m_nDrawSfxId = m_nFormSfxId = SID_OBJECT_SELECT;
242
0
            m_sDrawCustom.clear();
243
0
            break;
244
245
0
        case SID_LINE_ARROW_END:
246
0
        case SID_LINE_ARROW_CIRCLE:
247
0
        case SID_LINE_ARROW_SQUARE:
248
0
        case SID_LINE_ARROW_START:
249
0
        case SID_LINE_CIRCLE_ARROW:
250
0
        case SID_LINE_SQUARE_ARROW:
251
0
        case SID_LINE_ARROWS:
252
0
        case SID_DRAW_LINE:
253
0
        case SID_DRAW_XLINE:
254
0
        case SID_DRAW_MEASURELINE:
255
0
        case SID_DRAW_RECT:
256
0
        case SID_DRAW_ELLIPSE:
257
0
        case SID_DRAW_TEXT:
258
0
        case SID_DRAW_TEXT_VERTICAL:
259
0
        case SID_DRAW_TEXT_MARQUEE:
260
0
        case SID_DRAW_CAPTION:
261
0
        case SID_DRAW_CAPTION_VERTICAL:
262
0
        case SID_TOOL_CONNECTOR:
263
0
        case SID_CONNECTOR_ARROW_END:
264
0
        case SID_CONNECTOR_ARROW_START:
265
0
        case SID_CONNECTOR_ARROWS:
266
0
        case SID_CONNECTOR_CIRCLE_START:
267
0
        case SID_CONNECTOR_CIRCLE_END:
268
0
        case SID_CONNECTOR_CIRCLES:
269
0
        case SID_CONNECTOR_LINE:
270
0
        case SID_CONNECTOR_LINE_ARROW_START:
271
0
        case SID_CONNECTOR_LINE_ARROW_END:
272
0
        case SID_CONNECTOR_LINE_ARROWS:
273
0
        case SID_CONNECTOR_LINE_CIRCLE_START:
274
0
        case SID_CONNECTOR_LINE_CIRCLE_END:
275
0
        case SID_CONNECTOR_LINE_CIRCLES:
276
0
        case SID_CONNECTOR_CURVE:
277
0
        case SID_CONNECTOR_CURVE_ARROW_START:
278
0
        case SID_CONNECTOR_CURVE_ARROW_END:
279
0
        case SID_CONNECTOR_CURVE_ARROWS:
280
0
        case SID_CONNECTOR_CURVE_CIRCLE_START:
281
0
        case SID_CONNECTOR_CURVE_CIRCLE_END:
282
0
        case SID_CONNECTOR_CURVE_CIRCLES:
283
0
        case SID_CONNECTOR_LINES:
284
0
        case SID_CONNECTOR_LINES_ARROW_START:
285
0
        case SID_CONNECTOR_LINES_ARROW_END:
286
0
        case SID_CONNECTOR_LINES_ARROWS:
287
0
        case SID_CONNECTOR_LINES_CIRCLE_START:
288
0
        case SID_CONNECTOR_LINES_CIRCLE_END:
289
0
        case SID_CONNECTOR_LINES_CIRCLES:
290
0
            pFuncPtr.reset( new ConstRectangle(m_pWrtShell.get(), m_pEditWin, *this) );
291
0
            bCreateDirectly = comphelper::LibreOfficeKit::isActive();
292
0
            m_nDrawSfxId = nSlotId;
293
0
            m_sDrawCustom.clear();
294
0
            break;
295
296
0
        case SID_DRAW_XPOLYGON_NOFILL:
297
0
        case SID_DRAW_XPOLYGON:
298
0
        case SID_DRAW_POLYGON_NOFILL:
299
0
        case SID_DRAW_POLYGON:
300
0
        case SID_DRAW_BEZIER_NOFILL:
301
0
        case SID_DRAW_BEZIER_FILL:
302
0
        case SID_DRAW_FREELINE_NOFILL:
303
0
        case SID_DRAW_FREELINE:
304
0
            pFuncPtr.reset( new ConstPolygon(m_pWrtShell.get(), m_pEditWin, *this) );
305
0
            m_nDrawSfxId = nSlotId;
306
0
            m_sDrawCustom.clear();
307
0
            break;
308
309
0
        case SID_DRAW_ARC:
310
0
        case SID_DRAW_PIE:
311
0
        case SID_DRAW_CIRCLECUT:
312
0
            pFuncPtr.reset( new ConstArc(m_pWrtShell.get(), m_pEditWin, *this) );
313
0
            m_nDrawSfxId = nSlotId;
314
0
            m_sDrawCustom.clear();
315
0
            break;
316
317
0
        case SID_FM_CREATE_CONTROL:
318
0
        {
319
0
            pFuncPtr.reset(new ConstFormControl(m_pWrtShell.get(), m_pEditWin, *this, eNewFormObjKind));
320
0
            m_nFormSfxId = nSlotId;
321
0
            m_eFormObjKind = eNewFormObjKind;
322
0
        }
323
0
        break;
324
325
0
        case SID_DRAWTBX_CS_BASIC :
326
0
        case SID_DRAWTBX_CS_SYMBOL :
327
0
        case SID_DRAWTBX_CS_ARROW :
328
0
        case SID_DRAWTBX_CS_FLOWCHART :
329
0
        case SID_DRAWTBX_CS_CALLOUT :
330
0
        case SID_DRAWTBX_CS_STAR :
331
0
        case SID_DRAW_CS_ID :
332
0
        {
333
0
            pFuncPtr.reset( new ConstCustomShape(m_pWrtShell.get(), m_pEditWin, *this, rReq ) );
334
335
0
            bCreateDirectly = comphelper::LibreOfficeKit::isActive();
336
337
0
            m_nDrawSfxId = nSlotId;
338
0
            if ( nSlotId != SID_DRAW_CS_ID )
339
0
            {
340
0
                if ( pStringItem )
341
0
                {
342
0
                    m_sDrawCustom = pStringItem->GetValue();
343
0
                    SfxBindings& rBind = GetViewFrame().GetBindings();
344
0
                    rBind.Invalidate( nSlotId );
345
0
                    rBind.Update( nSlotId );
346
0
                }
347
0
            }
348
0
        }
349
0
        break;
350
351
0
        default:
352
0
            break;
353
0
    }
354
355
0
    GetViewFrame().GetBindings().Invalidate(SID_ATTRIBUTES_AREA);
356
357
0
    bool bEndTextEdit = true;
358
0
    if (pFuncPtr)
359
0
    {
360
0
        if (GetDrawFuncPtr())
361
0
        {
362
0
            GetDrawFuncPtr()->Deactivate();
363
0
        }
364
365
0
        auto pTempFuncPtr = pFuncPtr.get();
366
0
        SetDrawFuncPtr(std::move(pFuncPtr));
367
0
        AttrChangedNotify(nullptr);
368
369
0
        pTempFuncPtr->Activate(nSlotId);
370
0
        NoRotate();
371
0
        if(rReq.GetModifier() == KEY_MOD1 || bCreateDirectly)
372
0
        {
373
0
            if (bCreateDirectly)
374
0
                GetViewFrame().GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
375
0
            if(SID_OBJECT_SELECT == m_nDrawSfxId )
376
0
            {
377
0
                m_pWrtShell->GotoObj(true);
378
0
            }
379
0
            else if (dynamic_cast<ConstCustomShape*>(pTempFuncPtr))
380
0
            {
381
0
                pTempFuncPtr->CreateDefaultObject();
382
0
            }
383
0
            else
384
0
            {
385
0
                pTempFuncPtr->CreateDefaultObject();
386
0
                pTempFuncPtr->Deactivate();
387
0
                SetDrawFuncPtr(nullptr);
388
0
                LeaveDrawCreate();
389
0
                m_pWrtShell->EnterStdMode();
390
0
                SdrView *pTmpSdrView = m_pWrtShell->GetDrawView();
391
0
                const SdrMarkList& rMarkList = pTmpSdrView->GetMarkedObjectList();
392
0
                if(rMarkList.GetMarkCount() == 1 &&
393
0
                        (SID_DRAW_TEXT == nSlotId || SID_DRAW_TEXT_VERTICAL == nSlotId ||
394
0
                            SID_DRAW_TEXT_MARQUEE == nSlotId ))
395
0
                {
396
0
                    SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
397
0
                    BeginTextEdit(pObj);
398
0
                    bEndTextEdit = false;
399
0
                }
400
0
            }
401
0
        }
402
0
    }
403
0
    else
404
0
    {
405
0
        if (m_pWrtShell->GetSelectedObjCount() && !m_pWrtShell->IsSelFrameMode())
406
0
            m_pWrtShell->EnterSelFrameMode();
407
0
    }
408
409
0
    if(bEndTextEdit && pSdrView && pSdrView->IsTextEdit())
410
0
        pSdrView->SdrEndTextEdit( true );
411
412
0
    AttrChangedNotify(nullptr);
413
0
}
414
415
// End drawing
416
417
void SwView::ExitDraw()
418
0
{
419
0
    NoRotate();
420
421
0
    if(!m_pShell)
422
0
        return;
423
424
    // the shell may be invalid at close/reload/SwitchToViewShell
425
0
    SfxDispatcher* pDispatch = GetViewFrame().GetDispatcher();
426
0
    sal_uInt16 nIdx = 0;
427
0
    SfxShell* pTest = nullptr;
428
0
    do
429
0
    {
430
0
        pTest = pDispatch->GetShell(nIdx++);
431
0
    }
432
0
    while( pTest && pTest != this && pTest != m_pShell);
433
0
    if(!(pTest == m_pShell &&
434
        // don't call LeaveSelFrameMode() etc. for the below,
435
        // because objects may still be selected:
436
0
        dynamic_cast< const SwDrawBaseShell *>( m_pShell ) ==  nullptr &&
437
0
        dynamic_cast< const SwBezierShell *>( m_pShell ) ==  nullptr &&
438
0
        dynamic_cast< const svx::ExtrusionBar *>( m_pShell ) ==  nullptr &&
439
0
        dynamic_cast< const svx::FontworkBar *>( m_pShell ) ==  nullptr))
440
0
        return;
441
442
0
    SdrView *pSdrView = m_pWrtShell->GetDrawView();
443
444
0
    if (pSdrView && pSdrView->IsGroupEntered())
445
0
    {
446
0
        pSdrView->LeaveOneGroup();
447
0
        pSdrView->UnmarkAll();
448
0
        GetViewFrame().GetBindings().Invalidate(SID_ENTER_GROUP);
449
0
    }
450
451
0
    if (GetDrawFuncPtr())
452
0
    {
453
0
        if (m_pWrtShell->IsSelFrameMode())
454
0
            m_pWrtShell->LeaveSelFrameMode();
455
0
        GetDrawFuncPtr()->Deactivate();
456
457
0
        SetDrawFuncPtr(nullptr);
458
0
        LeaveDrawCreate();
459
460
0
        GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
461
0
    }
462
0
    GetEditWin().SetPointer(PointerStyle::Text);
463
0
}
464
465
// Disable rotate mode
466
467
void SwView::NoRotate()
468
0
{
469
0
    if (IsDrawRotate())
470
0
    {
471
0
        m_pWrtShell->SetDragMode(SdrDragMode::Move);
472
0
        FlipDrawRotate();
473
474
0
        const SfxBoolItem aTmp( SID_OBJECT_ROTATE, false );
475
0
        GetViewFrame().GetBindings().SetState( aTmp );
476
0
    }
477
0
}
478
479
void SwView::ToggleRotate()
480
0
{
481
0
    if ((m_pWrtShell->GetSelectedObjCount() &&
482
0
        m_pWrtShell->GetDrawView()->IsRotateAllowed()) ||
483
0
          (m_pWrtShell->IsRotationOfSwGrfNodePossible() &&
484
0
              m_pWrtShell->GetDrawViewWithValidMarkList()->IsRotateAllowed()))
485
0
    {
486
0
        if (IsDrawRotate())
487
0
            m_pWrtShell->SetDragMode(SdrDragMode::Move);
488
0
        else
489
0
            m_pWrtShell->SetDragMode(SdrDragMode::Rotate);
490
491
0
        FlipDrawRotate();
492
0
    }
493
0
}
494
495
// Enable DrawTextEditMode
496
497
static bool lcl_isTextBox(SdrObject const * pObject)
498
0
{
499
0
    if (SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pObject->GetUserCall()))
500
0
    {
501
0
        if (SwFrameFormat* pFormat = pDrawContact->GetFormat())
502
0
            return SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT);
503
0
    }
504
0
    return false;
505
0
}
506
507
bool SwView::EnterDrawTextMode(const Point& aDocPos)
508
0
{
509
0
    SwWrtShell *pSh = &GetWrtShell();
510
0
    SdrView *pSdrView = pSh->GetDrawView();
511
0
    assert(pSdrView && "EnterDrawTextMode without DrawView?");
512
513
0
    bool bReturn = false;
514
515
0
    sal_uInt16 nOld = pSdrView->GetHitTolerancePixel();
516
0
    pSdrView->SetHitTolerancePixel( 2 );
517
518
0
    SdrObject* pObj = nullptr;
519
0
    SdrPageView* pPV = nullptr;
520
0
    if (pSdrView->IsMarkedHit(aDocPos) && !pSdrView->PickHandle(aDocPos) && IsTextTool())
521
0
        pObj = pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKTEXTEDIT);
522
523
0
    if (pObj)
524
0
    {
525
        // To allow SwDrawVirtObj text objects to be activated, allow their type, too.
526
0
        auto pVirtObj =  dynamic_cast<SwDrawVirtObj*>( pObj );
527
0
        if ( (pVirtObj && DynCastSdrTextObj(&pVirtObj->GetReferencedObj() ) != nullptr &&
528
0
               m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) ||
529
0
             DynCastSdrTextObj( pObj ) != nullptr )
530
0
        {
531
            // Refuse to edit editeng text of the shape if it has textbox attached.
532
0
            if (!lcl_isTextBox(pObj))
533
0
                bReturn = BeginTextEdit( pObj, pPV, m_pEditWin );
534
0
        }
535
0
    }
536
537
0
    pSdrView->SetHitTolerancePixel( nOld );
538
539
0
    return bReturn;
540
0
}
541
542
bool SwView::EnterShapeDrawTextMode(SdrObject* pObject)
543
0
{
544
0
    SdrView* pSdrView = GetWrtShell().GetDrawView();
545
0
    SdrPageView* pPageView = pSdrView->GetSdrPageView();
546
0
    return BeginTextEdit(pObject, pPageView, m_pEditWin);
547
0
}
548
549
// Enable DrawTextEditMode
550
551
bool SwView::BeginTextEdit(SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin,
552
        bool bIsNewObj, bool bSetSelectionToStart)
553
0
{
554
0
    SwWrtShell *pSh = &GetWrtShell();
555
0
    SdrView *pSdrView = pSh->GetDrawView();
556
0
    std::unique_ptr<SdrOutliner> pOutliner = ::SdrMakeOutliner(OutlinerMode::TextObject, pSdrView->GetModel());
557
0
    uno::Reference< linguistic2::XSpellChecker1 >  xSpell( ::GetSpellChecker() );
558
0
    if (pOutliner)
559
0
    {
560
0
        pOutliner->SetRefDevice(pSh->getIDocumentDeviceAccess().getReferenceDevice(false));
561
0
        pOutliner->SetSpeller(xSpell);
562
0
        uno::Reference<linguistic2::XHyphenator> xHyphenator( ::GetHyphenator() );
563
0
        pOutliner->SetHyphenator( xHyphenator );
564
0
        pSh->SetCalcFieldValueHdl(pOutliner.get());
565
566
0
        EEControlBits nCntrl = pOutliner->GetControlWord();
567
0
        nCntrl |= EEControlBits::ALLOWBIGOBJS;
568
569
0
        const SwViewOption *pOpt = pSh->GetViewOptions();
570
571
0
        if (pOpt->IsFieldShadings())
572
0
            nCntrl |= EEControlBits::MARKFIELDS;
573
0
        else
574
0
            nCntrl &= ~EEControlBits::MARKFIELDS;
575
576
0
        if (pOpt->IsOnlineSpell())
577
0
            nCntrl |= EEControlBits::ONLINESPELLING;
578
0
        else
579
0
            nCntrl &= ~EEControlBits::ONLINESPELLING;
580
581
0
        pOutliner->SetControlWord(nCntrl);
582
0
        const SvxLanguageItem& rItem = pSh->GetDoc()->GetDefault(RES_CHRATR_LANGUAGE);
583
0
        pOutliner->SetDefaultLanguage(rItem.GetLanguage());
584
585
0
        if( bIsNewObj )
586
0
            pOutliner->SetVertical( SID_DRAW_TEXT_VERTICAL == m_nDrawSfxId ||
587
0
                                    SID_DRAW_CAPTION_VERTICAL == m_nDrawSfxId );
588
589
        // set default horizontal text direction at outliner
590
0
        EEHorizontalTextDirection aDefHoriTextDir =
591
0
            pSh->IsShapeDefaultHoriTextDirR2L() ? EEHorizontalTextDirection::R2L : EEHorizontalTextDirection::L2R;
592
0
        pOutliner->SetDefaultHorizontalTextDirection( aDefHoriTextDir );
593
0
    }
594
595
    // To allow editing the referenced object from a SwDrawVirtObj here
596
    // the original needs to be fetched eventually. This ATM activates the
597
    // text edit mode for the original object.
598
0
    SdrObject* pToBeActivated = pObj;
599
600
    // Always the original object is edited. To allow the TextEdit to happen
601
    // where the VirtObj is positioned, on demand an occurring offset is set at
602
    // the TextEdit object. That offset is used for creating and managing the
603
    // OutlinerView.
604
0
    Point aNewTextEditOffset(0, 0);
605
606
0
    if (SwDrawVirtObj* pVirtObj = dynamic_cast<SwDrawVirtObj *>(pObj))
607
0
    {
608
0
        pToBeActivated = &const_cast<SdrObject&>(pVirtObj->GetReferencedObj());
609
0
        aNewTextEditOffset = pVirtObj->GetOffset();
610
0
    }
611
612
    // set in each case, thus it will be correct for all objects
613
0
    static_cast<SdrTextObj*>(pToBeActivated)->SetTextEditOffset(aNewTextEditOffset);
614
615
0
    bool bRet(pSdrView->SdrBeginTextEdit( pToBeActivated, pPV, pWin, true, pOutliner.release(), nullptr, false, false, false ));
616
617
    // #i7672#
618
    // Since SdrBeginTextEdit actually creates the OutlinerView and thus also
619
    // sets the background color, an own background color needs to be set
620
    // after TextEditing was started. This is now done here.
621
0
    if(bRet)
622
0
    {
623
0
        OutlinerView* pView = pSdrView->GetTextEditOutlinerView();
624
625
0
        if(pView)
626
0
        {
627
0
            Color aBackground(pSh->GetShapeBackground());
628
0
            pView->SetBackgroundColor(aBackground);
629
0
        }
630
631
        // editing should start at the end of text, spell checking at the beginning ...
632
0
        ESelection aNewSelection(ESelection::AtEnd());
633
0
        if (bSetSelectionToStart)
634
0
            aNewSelection = ESelection();
635
0
        if (pView)
636
0
        {
637
0
            pView->SetSelection(aNewSelection);
638
639
0
            if (comphelper::LibreOfficeKit::isActive())
640
0
            {
641
0
                OString sRect = pView->GetOutputArea().toString();
642
0
                SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_LOCK, "rectangle", sRect);
643
0
            }
644
0
        }
645
0
    }
646
647
0
    return bRet;
648
0
}
649
650
// Is a DrawTextObject selected?
651
bool SwView::IsTextTool() const
652
0
{
653
0
    SdrObjKind nId;
654
0
    SdrInventor nInvent;
655
0
    SdrView *pSdrView = GetWrtShell().GetDrawView();
656
0
    assert(pSdrView && "IsTextTool without DrawView?");
657
658
0
    if (pSdrView->IsCreateMode())
659
0
        pSdrView->SetCreateMode(false);
660
661
0
    pSdrView->TakeCurrentObj(nId,nInvent);
662
0
    return nInvent == SdrInventor::Default;
663
0
}
664
665
SdrView* SwView::GetDrawView() const
666
6.57k
{
667
6.57k
    return GetWrtShell().GetDrawView();
668
6.57k
}
669
670
bool SwView::IsBezierEditMode() const
671
0
{
672
0
    return (!IsDrawSelMode() && GetWrtShell().GetDrawView()->HasMarkablePoints());
673
0
}
674
675
bool SwView::IsFormMode() const
676
0
{
677
0
    if (GetDrawFuncPtr() && GetDrawFuncPtr()->IsCreateObj())
678
0
    {
679
0
        return GetDrawFuncPtr()->IsInsertForm();
680
0
    }
681
682
0
    return AreOnlyFormsSelected();
683
0
}
684
685
void SwView::SetDrawFuncPtr(std::unique_ptr<SwDrawBase> pFuncPtr)
686
3.28k
{
687
3.28k
    m_pDrawActual = std::move(pFuncPtr);
688
3.28k
}
689
690
void SwView::SetSelDrawSlot()
691
0
{
692
0
    m_nDrawSfxId = SID_OBJECT_SELECT;
693
0
    m_sDrawCustom.clear();
694
0
}
695
696
bool SwView::AreOnlyFormsSelected() const
697
0
{
698
0
    if ( GetWrtShell().IsFrameSelected() )
699
0
        return false;
700
701
0
    bool bForm = true;
702
703
0
    SdrView* pSdrView = GetWrtShell().GetDrawView();
704
705
0
    const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
706
0
    const size_t nCount = rMarkList.GetMarkCount();
707
708
0
    if (nCount)
709
0
    {
710
0
        for (size_t i = 0; i < nCount; ++i)
711
0
        {
712
            // Except controls, are still normal draw objects selected?
713
0
            SdrObject *pSdrObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
714
0
            if (!pSdrObj)
715
0
                continue;
716
717
0
            if (!HasOnlyObj(pSdrObj, SdrInventor::FmForm))
718
0
            {
719
0
                bForm = false;
720
0
                break;
721
0
            }
722
0
        }
723
0
    }
724
0
    else
725
0
        bForm = false;
726
727
0
    return bForm;
728
0
}
729
730
bool SwView::HasOnlyObj(SdrObject const *pSdrObj, SdrInventor eObjInventor) const
731
0
{
732
0
    bool bRet = false;
733
734
0
    if (pSdrObj->IsGroupObject())
735
0
    {
736
0
        SdrObjList* pList = pSdrObj->GetSubList();
737
0
        for (const rtl::Reference<SdrObject>& pObj : *pList)
738
0
        {
739
0
            bRet = HasOnlyObj(pObj.get(), eObjInventor);
740
0
            if (!bRet)
741
0
                break;
742
0
        }
743
0
    }
744
0
    else if (eObjInventor == pSdrObj->GetObjInventor())
745
0
        return true;
746
747
0
    return bRet;
748
0
}
749
750
//#i87414# mod
751
IMPL_LINK(SwView, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void)
752
0
{
753
0
    if (rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG)
754
0
        GetViewFrame().GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON);
755
0
    else if (rInfo.nCommand == SpellCallbackCommand::AUTOCORRECT_OPTIONS)
756
0
        GetViewFrame().GetDispatcher()->Execute( SID_AUTO_CORRECT_DLG, SfxCallMode::ASYNCHRON );
757
0
}
758
759
bool SwView::ExecDrwTextSpellPopup(const Point& rPt)
760
0
{
761
0
    bool bRet = false;
762
0
    SdrView *pSdrView = m_pWrtShell->GetDrawView();
763
0
    OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
764
0
    Point aPos( GetEditWin().LogicToPixel( rPt ) );
765
766
0
    if (pOLV->IsWrongSpelledWordAtPos( aPos ))
767
0
    {
768
0
        Link<SpellCallbackInfo&,void> aLink = LINK(this, SwView, OnlineSpellCallback);
769
0
        bRet = pOLV->ExecuteSpellPopup(aPos, aLink);
770
0
    }
771
0
    return bRet;
772
0
}
773
774
bool SwView::IsDrawTextHyphenate()
775
0
{
776
0
    SdrView *pSdrView = m_pWrtShell->GetDrawView();
777
0
    bool bHyphenate = false;
778
779
0
    SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aNewAttr( pSdrView->GetModel().GetItemPool() );
780
0
    pSdrView->GetAttributes( aNewAttr );
781
0
    if( aNewAttr.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT )
782
0
        bHyphenate = aNewAttr.Get( EE_PARA_HYPHENATE ).GetValue();
783
784
0
    return bHyphenate;
785
0
}
786
787
void SwView::HyphenateDrawText()
788
0
{
789
0
    SdrView *pSdrView = m_pWrtShell->GetDrawView();
790
0
    bool bHyphenate = IsDrawTextHyphenate();
791
792
0
    SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aSet( GetPool() );
793
0
    aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, !bHyphenate ) );
794
0
    pSdrView->SetAttributes( aSet );
795
0
    GetViewFrame().GetBindings().Invalidate(FN_HYPHENATE_OPT_DLG);
796
0
}
797
798
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */