Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/drawview.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 <com/sun/star/embed/XEmbeddedObject.hpp>
21
22
#include <svx/svditer.hxx>
23
#include <svx/svdograf.hxx>
24
#include <svx/svdogrp.hxx>
25
#include <svx/svdoole2.hxx>
26
#include <svx/svdouno.hxx>
27
#include <svx/svdpage.hxx>
28
#include <svx/svdpagv.hxx>
29
#include <svx/svdundo.hxx>
30
#include <svx/svdocapt.hxx>
31
#include <svx/sdrpaintwindow.hxx>
32
#include <sfx2/bindings.hxx>
33
#include <sfx2/viewfrm.hxx>
34
#include <svx/sdrundomanager.hxx>
35
#include <svx/xfillit0.hxx>
36
#include <svx/xbtmpit.hxx>
37
#include <comphelper/lok.hxx>
38
#include <sfx2/lokhelper.hxx>
39
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
40
#include <svx/sdr/contact/objectcontactofpageview.hxx>
41
#include <svx/sdr/contact/viewobjectcontact.hxx>
42
#include <svx/sdr/contact/viewcontact.hxx>
43
#include <svx/sdrpagewindow.hxx>
44
#include <tools/debug.hxx>
45
#include <tools/UnitConversion.hxx>
46
#include <osl/diagnose.h>
47
48
#include <drawview.hxx>
49
#include <global.hxx>
50
#include <viewdata.hxx>
51
#include <document.hxx>
52
#include <drawutil.hxx>
53
#include <globstr.hrc>
54
#include <scresid.hxx>
55
#include <tabvwsh.hxx>
56
#include <client.hxx>
57
#include <scmod.hxx>
58
#include <drwlayer.hxx>
59
#include <docsh.hxx>
60
#include <viewuno.hxx>
61
#include <userdat.hxx>
62
#include <postit.hxx>
63
#include <undocell.hxx>
64
#include <gridwin.hxx>
65
66
#include <sc.hrc>
67
68
using namespace com::sun::star;
69
70
0
#define SC_HANDLESIZE_BIG       9
71
72
void ScDrawView::Construct()
73
0
{
74
0
    EnableExtendedKeyInputDispatcher(false);
75
0
    EnableExtendedMouseEventDispatcher(false);
76
77
0
    SetFrameDragSingles();
78
79
0
    SetMinMoveDistancePixel( 2 );
80
0
    SetHitTolerancePixel( 2 );
81
82
0
    SCTAB nViewTab = rViewData.CurrentTabForData();
83
    // For sheet view tabs, use the default view's draw page so that
84
    // all draw operations and undo actions reference the default view's page.
85
0
    SCTAB nDrawTab = rDoc.GetDefaultViewTableNumber(nViewTab);
86
0
    ShowSdrPage(GetModel().GetPage(nDrawTab));
87
88
0
    bool bEx = rViewData.GetViewShell()->IsDrawSelMode();
89
0
    bool bProt = rDoc.IsTabProtected( nViewTab ) ||
90
0
                 rViewData.GetSfxDocShell()->IsReadOnly();
91
92
0
    SdrLayer* pLayer;
93
0
    SdrLayerAdmin& rAdmin = GetModel().GetLayerAdmin();
94
0
    pLayer = rAdmin.GetLayerPerID(SC_LAYER_BACK);
95
0
    if (pLayer)
96
0
        SetLayerLocked( pLayer->GetName(), bProt || !bEx );
97
0
    pLayer = rAdmin.GetLayerPerID(SC_LAYER_INTERN);
98
0
    if (pLayer)
99
0
        SetLayerLocked( pLayer->GetName() );
100
0
    pLayer = rAdmin.GetLayerPerID(SC_LAYER_FRONT);
101
0
    if (pLayer)
102
0
    {
103
0
        SetLayerLocked( pLayer->GetName(), bProt );
104
0
        SetActiveLayer( pLayer->GetName() );        // set active layer to FRONT
105
0
    }
106
0
    pLayer = rAdmin.GetLayerPerID(SC_LAYER_CONTROLS);
107
0
    if (pLayer)
108
0
        SetLayerLocked( pLayer->GetName(), bProt );
109
0
    pLayer = rAdmin.GetLayerPerID(SC_LAYER_HIDDEN);
110
0
    if (pLayer)
111
0
    {
112
0
        SetLayerLocked( pLayer->GetName(), bProt );
113
0
        SetLayerVisible( pLayer->GetName(), false);
114
0
    }
115
116
0
    SetSwapAsynchron();
117
118
0
    UpdateUserViewOptions();
119
0
    RecalcScale();
120
0
    UpdateWorkArea();
121
122
0
    bInConstruct = false;
123
0
}
124
125
void ScDrawView::ImplClearCalcDropMarker()
126
0
{
127
0
    pDropMarker.reset();
128
0
}
129
130
ScDrawView::~ScDrawView()
131
0
{
132
0
    ImplClearCalcDropMarker();
133
0
}
134
135
void ScDrawView::AddCustomHdl()
136
0
{
137
0
    const SdrMarkList &rMarkList = GetMarkedObjectList();
138
0
    const size_t nCount = rMarkList.GetMarkCount();
139
0
    for(size_t nPos=0; nPos<nCount; ++nPos )
140
0
    {
141
0
        SdrObject* pObj = rMarkList.GetMark(nPos)->GetMarkedSdrObj();
142
0
        if (ScDrawObjData *pAnchor = ScDrawLayer::GetObjDataTab(pObj, nTab))
143
0
        {
144
0
            if (ScTabView* pView = rViewData.GetView())
145
0
                pView->CreateAnchorHandles(maHdlList, pAnchor->maStart);
146
0
        }
147
0
    }
148
0
}
149
150
void ScDrawView::InvalidateAttribs()
151
0
{
152
0
    SfxBindings& rBindings = rViewData.GetBindings();
153
154
        // true status values:
155
0
    rBindings.InvalidateAll( true );
156
0
}
157
158
void ScDrawView::InvalidateDrawTextAttrs()
159
0
{
160
0
    SfxBindings& rBindings = rViewData.GetBindings();
161
162
    //  cjk/ctl font items have no configured slots,
163
    //  need no invalidate
164
165
0
    rBindings.Invalidate( SID_ATTR_CHAR_FONT );
166
0
    rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
167
0
    rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT );
168
0
    rBindings.Invalidate( SID_ATTR_CHAR_POSTURE );
169
0
    rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
170
0
    rBindings.Invalidate( SID_ULINE_VAL_NONE );
171
0
    rBindings.Invalidate( SID_ULINE_VAL_SINGLE );
172
0
    rBindings.Invalidate( SID_ULINE_VAL_DOUBLE );
173
0
    rBindings.Invalidate( SID_ULINE_VAL_DOTTED );
174
0
    rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE );
175
0
    rBindings.Invalidate( SID_ATTR_CHAR_COLOR );
176
0
    rBindings.Invalidate( SID_ATTR_CHAR_BACK_COLOR );
177
0
    rBindings.Invalidate( SID_ATTR_PARA_ADJUST_LEFT );
178
0
    rBindings.Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
179
0
    rBindings.Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
180
0
    rBindings.Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
181
0
    rBindings.Invalidate( SID_ATTR_PARA_ADJUST_START );
182
0
    rBindings.Invalidate( SID_ATTR_PARA_ADJUST_END );
183
0
    rBindings.Invalidate( SID_ALIGNLEFT );
184
0
    rBindings.Invalidate( SID_ALIGNCENTERHOR );
185
0
    rBindings.Invalidate( SID_ALIGNRIGHT );
186
0
    rBindings.Invalidate( SID_ALIGNBLOCK );
187
0
    rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_10 );
188
0
    rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_15 );
189
0
    rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_20 );
190
0
    rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
191
0
    rBindings.Invalidate( SID_SET_SUB_SCRIPT );
192
0
    rBindings.Invalidate( SID_ATTR_CHAR_KERNING );
193
0
    rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT );
194
0
    rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED );
195
0
    rBindings.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT );
196
0
    rBindings.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM );
197
0
    rBindings.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
198
0
    rBindings.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
199
0
    rBindings.Invalidate( SID_TABLE_VERT_NONE );
200
0
    rBindings.Invalidate( SID_TABLE_VERT_CENTER );
201
0
    rBindings.Invalidate( SID_TABLE_VERT_BOTTOM );
202
    // pseudo slots for Format menu
203
0
    rBindings.Invalidate( SID_ALIGN_ANY_LEFT );
204
0
    rBindings.Invalidate( SID_ALIGN_ANY_HCENTER );
205
0
    rBindings.Invalidate( SID_ALIGN_ANY_RIGHT );
206
0
    rBindings.Invalidate( SID_ALIGN_ANY_START );
207
0
    rBindings.Invalidate( SID_ALIGN_ANY_END );
208
0
    rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED );
209
0
}
210
211
void ScDrawView::SetMarkedToLayer( SdrLayerID nLayerNo )
212
0
{
213
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
214
0
    if (rMarkList.GetMarkCount() == 0)
215
0
        return;
216
217
    //  #i11702# use SdrUndoObjectLayerChange for undo
218
    //  STR_UNDO_SELATTR is "Attributes" - should use a different text later
219
0
    BegUndo( ScResId( STR_UNDO_SELATTR ) );
220
221
0
    const SdrMarkList& rMark = GetMarkedObjectList();
222
0
    const size_t nCount = rMark.GetMarkCount();
223
0
    for (size_t i=0; i<nCount; ++i)
224
0
    {
225
0
        SdrObject* pObj = rMark.GetMark(i)->GetMarkedSdrObj();
226
0
        assert(pObj);
227
0
        if ( dynamic_cast<const SdrUnoObj*>( pObj) == nullptr && (pObj->GetLayer() != SC_LAYER_INTERN) )
228
0
        {
229
0
            AddUndo( std::make_unique<SdrUndoObjectLayerChange>( *pObj, pObj->GetLayer(), nLayerNo) );
230
0
            pObj->SetLayer( nLayerNo );
231
0
        }
232
0
    }
233
234
0
    EndUndo();
235
236
    //  repaint is done in SetLayer
237
238
0
    rViewData.GetDocShell()->SetDrawModified();
239
240
    //  check mark list now instead of later in a timer
241
0
    CheckMarked();
242
0
    MarkListHasChanged();
243
0
}
244
245
bool ScDrawView::HasMarkedControl() const
246
0
{
247
0
    SdrObjListIter aIter( GetMarkedObjectList() );
248
0
    for( SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next() )
249
0
        if( dynamic_cast<const SdrUnoObj*>( pObj) !=  nullptr )
250
0
            return true;
251
0
    return false;
252
0
}
253
254
bool ScDrawView::HasMarkedInternal() const
255
0
{
256
    // internal objects should not be inside a group, but who knows...
257
0
    SdrObjListIter aIter( GetMarkedObjectList() );
258
0
    for( SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next() )
259
0
        if( pObj->GetLayer() == SC_LAYER_INTERN )
260
0
            return true;
261
0
    return false;
262
0
}
263
264
void ScDrawView::UpdateWorkArea()
265
0
{
266
0
    SdrPage* pPage = GetModel().GetPage(static_cast<sal_uInt16>(nTab));
267
0
    if (pPage)
268
0
    {
269
0
        Size aPageSize( pPage->GetSize() );
270
0
        tools::Rectangle aNewArea( Point(), aPageSize );
271
0
        if ( aPageSize.Width() < 0 )
272
0
        {
273
            //  RTL: from max.negative (left) to zero (right)
274
0
            aNewArea.SetRight( 0 );
275
0
            aNewArea.SetLeft( aPageSize.Width() + 1 );
276
0
        }
277
0
        SetWorkArea( aNewArea );
278
0
    }
279
0
    else
280
0
    {
281
0
        OSL_FAIL("Page not found");
282
0
    }
283
0
}
284
285
void ScDrawView::DoCut()
286
0
{
287
0
    DoCopy();
288
0
    BegUndo( ScResId( STR_UNDO_CUT ) );
289
0
    DeleteMarked();     // In this View - not affected by 505f change
290
0
    EndUndo();
291
0
}
292
293
void ScDrawView::GetScale( double& rFractX, double& rFractY ) const
294
0
{
295
0
    rFractX = mfScaleX;
296
0
    rFractY = mfScaleY;
297
0
}
298
299
void ScDrawView::RecalcScale()
300
0
{
301
0
    double nPPTX;
302
0
    double nPPTY;
303
0
    double fZoomX(1.0);
304
0
    double fZoomY(1.0);
305
306
0
    nTab = rViewData.CurrentTabForData();
307
0
    nPPTX = rViewData.GetPPTX();
308
0
    nPPTY = rViewData.GetPPTY();
309
0
    fZoomX = rViewData.GetZoomX();
310
0
    fZoomY = rViewData.GetZoomY();
311
312
0
    SCCOL nEndCol = 0;
313
0
    SCROW nEndRow = 0;
314
0
    rDoc.GetTableArea( nTab, nEndCol, nEndRow );
315
0
    if (nEndCol<20)
316
0
        nEndCol = 20;
317
0
    if (nEndRow<20)
318
0
        nEndRow = 20;
319
320
0
    ScDrawUtil::CalcScale(
321
0
        rDoc, nTab, 0, 0, nEndCol, nEndRow, pDev, fZoomX, fZoomY, nPPTX, nPPTY,
322
0
        mfScaleX, mfScaleY);
323
324
    // clear all evtl existing GridOffset vectors
325
0
    resetGridOffsetsForAllSdrPageViews();
326
327
0
    SdrPageView* pPV = GetSdrPageView();
328
0
    if ( !pPV )
329
0
        return;
330
331
0
    if ( SdrPage* pPage = pPV->GetPage() )
332
0
    {
333
0
        for (const rtl::Reference<SdrObject>& pObj : *pPage)
334
            // Align objects to nearest grid position
335
0
            SyncForGrid( pObj.get() );
336
0
    }
337
0
}
338
339
void ScDrawView::DoConnect(SdrOle2Obj* pOleObj)
340
0
{
341
0
    rViewData.GetViewShell()->ConnectObject( pOleObj );
342
0
}
343
344
void ScDrawView::MarkListHasChanged()
345
0
{
346
0
    FmFormView::MarkListHasChanged();
347
348
0
    ScTabViewShell* pViewSh = rViewData.GetViewShell();
349
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
350
0
    ScModule* pScMod = ScModule::get();
351
352
    // #i110829# remove the cell selection only if drawing objects are selected
353
0
    if ( !bInConstruct && rMarkList.GetMarkCount() )
354
0
    {
355
0
        pViewSh->Unmark();      // remove cell selection
356
357
        //  end cell edit mode if drawing objects are selected
358
0
        pScMod->InputEnterHandler();
359
0
    }
360
361
    // deactivate IP
362
363
0
    bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
364
365
0
    ScClient* pClient = static_cast<ScClient*>( pViewSh->GetIPClient() );
366
0
    if ( pClient && pClient->IsObjectInPlaceActive() && !bUnoRefDialog )
367
0
    {
368
        // do not display the handles for ViewShell::Activate from the Reset2Open
369
0
        pClient->DeactivateObject();
370
        // replacing image ole graphics is now done in ScClient::UIActivate
371
0
    }
372
373
    //  Select Ole object?
374
375
0
    SdrOle2Obj* pOle2Obj = nullptr;
376
0
    SdrGrafObj* pGrafObj = nullptr;
377
378
0
    const size_t nMarkCount = rMarkList.GetMarkCount();
379
380
0
    if ( nMarkCount == 0 && !rViewData.GetViewShell()->IsDrawSelMode() && !bInConstruct )
381
0
    {
382
        //  relock layers that may have been unlocked before
383
0
        LockBackgroundLayer(true);
384
0
        LockInternalLayer();
385
0
    }
386
387
0
    bool bSubShellSet = false;
388
0
    if (nMarkCount == 1)
389
0
    {
390
0
        SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
391
0
        SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
392
0
        if (nSdrObjKind == SdrObjKind::OLE2)
393
0
        {
394
0
            pOle2Obj = static_cast<SdrOle2Obj*>(pObj);
395
0
            if (!ScDocument::IsChart(pObj) )
396
0
                pViewSh->SetOleObjectShell(true);
397
0
            else
398
0
                pViewSh->SetChartShell(true);
399
0
            bSubShellSet = true;
400
0
        }
401
0
        else if (nSdrObjKind == SdrObjKind::Graphic)
402
0
        {
403
0
            pGrafObj = static_cast<SdrGrafObj*>(pObj);
404
0
            pViewSh->SetGraphicShell(true);
405
0
            bSubShellSet = true;
406
0
        }
407
0
        else if (nSdrObjKind == SdrObjKind::Media)
408
0
        {
409
0
            pViewSh->SetMediaShell(true);
410
0
            bSubShellSet = true;
411
0
        }
412
0
        else if (nSdrObjKind == SdrObjKind::Text)
413
0
        {
414
            // prevent switching to the drawing shell
415
0
            if (!pViewSh->IsDrawTextShell()) // when creating a text object @#70206#
416
0
                pViewSh->SetDrawShell(true);
417
0
        }
418
0
        else if (!pViewSh->IsDrawTextShell())
419
0
        {
420
            // tdf#166481: we only need to switch to draw shell if we have not
421
            // already created a text shell for text edit mode
422
0
            pViewSh->SetDrawShell(true);
423
0
        }
424
0
    }
425
426
0
    if ( nMarkCount && !bSubShellSet )
427
0
    {
428
0
        bool bOnlyControls = true;
429
0
        bool bOnlyGraf     = true;
430
0
        for (size_t i=0; i<nMarkCount; ++i)
431
0
        {
432
0
            SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
433
0
            if ( auto pObjGroup = dynamic_cast<const SdrObjGroup*>( pObj) )
434
0
            {
435
0
                const SdrObjList *pLst = pObjGroup->GetSubList();
436
0
                const size_t nListCount = pLst->GetObjCount();
437
0
                if ( nListCount == 0 )
438
0
                {
439
                    //  An empty group (may occur during Undo) is no control or graphics object.
440
                    //  Creating the form shell during undo would lead to problems with the undo manager.
441
0
                    bOnlyControls = false;
442
0
                    bOnlyGraf = false;
443
0
                }
444
0
                for ( size_t j = 0; j < nListCount; ++j )
445
0
                {
446
0
                    SdrObject *pSubObj = pLst->GetObj( j );
447
0
                    assert(pSubObj);
448
449
0
                    if (dynamic_cast<const SdrUnoObj*>( pSubObj) ==  nullptr)
450
0
                        bOnlyControls = false;
451
0
                    if (pSubObj->GetObjIdentifier() != SdrObjKind::Graphic)
452
0
                        bOnlyGraf = false;
453
454
0
                    if ( !bOnlyControls && !bOnlyGraf ) break;
455
0
                }
456
0
            }
457
0
            else
458
0
            {
459
0
                if (dynamic_cast<const SdrUnoObj*>( pObj) ==  nullptr)
460
0
                    bOnlyControls = false;
461
0
                if (pObj->GetObjIdentifier() != SdrObjKind::Graphic)
462
0
                    bOnlyGraf = false;
463
0
            }
464
465
0
            if ( !bOnlyControls && !bOnlyGraf ) break;
466
0
        }
467
468
0
        if(bOnlyControls)
469
0
        {
470
0
            pViewSh->SetDrawFormShell(true);            // now UNO controls
471
0
        }
472
0
        else if(bOnlyGraf)
473
0
        {
474
0
            pViewSh->SetGraphicShell(true);
475
0
        }
476
0
        else if(nMarkCount>1)
477
0
        {
478
0
            pViewSh->SetDrawShell(true);
479
0
        }
480
0
    }
481
482
    // adjust verbs
483
484
0
    SfxViewFrame& rViewFrame = pViewSh->GetViewFrame();
485
0
    bool bOle = pViewSh->GetViewFrame().GetFrame().IsInPlace();
486
0
    uno::Sequence< embed::VerbDescriptor > aVerbs;
487
0
    if ( pOle2Obj && !bOle )
488
0
    {
489
0
        const uno::Reference < embed::XEmbeddedObject >& xObj = pOle2Obj->GetObjRef();
490
0
        OSL_ENSURE( xObj.is(), "SdrOle2Obj without ObjRef" );
491
0
        if (xObj.is())
492
0
            aVerbs = xObj->getSupportedVerbs();
493
0
    }
494
0
    pViewSh->SetVerbs( aVerbs );
495
496
    // image map editor
497
498
0
    if ( pOle2Obj )
499
0
        UpdateIMap( pOle2Obj );
500
0
    else if ( pGrafObj )
501
0
        UpdateIMap( pGrafObj );
502
503
0
    InvalidateAttribs();                // after the image map editor update
504
0
    InvalidateDrawTextAttrs();
505
506
0
    for(sal_uInt32 a(0); a < PaintWindowCount(); a++)
507
0
    {
508
0
        SdrPaintWindow* pPaintWindow = GetPaintWindow(a);
509
0
        OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
510
511
0
        if(OUTDEV_WINDOW == rOutDev.GetOutDevType())
512
0
        {
513
0
            rOutDev.GetOwnerWindow()->PaintImmediately();
514
0
        }
515
0
    }
516
517
    //  uno object for view returns drawing objects as selection,
518
    //  so it must notify its SelectionChangeListeners
519
520
0
    SfxFrame& rFrame = rViewFrame.GetFrame();
521
0
    uno::Reference<frame::XController> xController = rFrame.GetController();
522
0
    if (xController.is())
523
0
    {
524
0
        ScTabViewObj* pImp = dynamic_cast<ScTabViewObj*>( xController.get() );
525
0
        if (pImp)
526
0
            pImp->SelectionChanged();
527
0
    }
528
529
    //  update selection transfer object
530
531
0
    pViewSh->CheckSelectionTransfer();
532
533
0
}
534
535
bool ScDrawView::SdrBeginTextEdit(
536
    SdrObject* pObj,
537
    SdrPageView* pPV,
538
    vcl::Window* pWinL,
539
    bool bIsNewObj,
540
    SdrOutliner* pGivenOutliner,
541
    OutlinerView* pGivenOutlinerView,
542
    bool bDontDeleteOutliner,
543
    bool bOnlyOneView,
544
    bool bGrabFocus )
545
0
{
546
0
    const bool bRet = FmFormView::SdrBeginTextEdit(
547
0
        pObj, pPV, pWinL, bIsNewObj,
548
0
        pGivenOutliner, pGivenOutlinerView, bDontDeleteOutliner,
549
0
        bOnlyOneView, bGrabFocus );
550
551
0
    ScTabViewShell* pViewSh = rViewData.GetViewShell();
552
553
0
    if (comphelper::LibreOfficeKit::isActive())
554
0
    {
555
0
        if (OutlinerView* pView = GetTextEditOutlinerView())
556
0
        {
557
0
            tools::Rectangle aRectangle = pView->GetOutputArea();
558
0
            if (pWinL && pWinL->GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
559
0
            {
560
0
                aRectangle = o3tl::convert(aRectangle, o3tl::Length::mm100, o3tl::Length::twip);
561
0
            }
562
0
            OString sRectangle = aRectangle.toString();
563
0
            SfxLokHelper::notifyOtherViews(pViewSh, LOK_CALLBACK_VIEW_LOCK, "rectangle", sRectangle);
564
0
        }
565
0
    }
566
567
0
    SfxFrame& rFrame = pViewSh->GetViewFrame().GetFrame();
568
0
    uno::Reference< frame::XController > xController = rFrame.GetController();
569
0
    if (xController.is())
570
0
    {
571
0
        ScTabViewObj* pImp = dynamic_cast<ScTabViewObj*>( xController.get() );
572
0
        if (pImp)
573
0
            pImp->SelectionChanged();
574
0
    }
575
576
0
    return bRet;
577
0
}
578
579
SdrEndTextEditKind ScDrawView::SdrEndTextEdit( bool bDontDeleteReally )
580
0
{
581
0
    const SdrEndTextEditKind eRet = FmFormView::SdrEndTextEdit( bDontDeleteReally );
582
583
0
    ScTabViewShell* pViewSh = rViewData.GetViewShell();
584
585
0
    if (comphelper::LibreOfficeKit::isActive())
586
0
        SfxLokHelper::notifyOtherViews(pViewSh, LOK_CALLBACK_VIEW_LOCK, "rectangle", "EMPTY"_ostr);
587
588
0
    SfxFrame& rFrame = pViewSh->GetViewFrame().GetFrame();
589
0
    uno::Reference< frame::XController > xController = rFrame.GetController();
590
0
    if (xController.is())
591
0
    {
592
0
        ScTabViewObj* pImp = dynamic_cast<ScTabViewObj*>( xController.get() );
593
0
        if (pImp)
594
0
            pImp->SelectionChanged();
595
0
    }
596
597
0
    return eRet;
598
0
}
599
600
void ScDrawView::ModelHasChanged()
601
0
{
602
0
    SdrObject* pEditObj = GetTextEditObject();
603
0
    if ( pEditObj && !pEditObj->IsInserted() )
604
0
    {
605
        //  SdrObjEditView::ModelHasChanged will end text edit in this case,
606
        //  so make sure the EditEngine's undo manager is no longer used.
607
0
        rViewData.GetViewShell()->SetDrawTextUndo(nullptr);
608
0
        SetCreateMode();    // don't leave FuText in a funny state
609
0
    }
610
611
0
    FmFormView::ModelHasChanged();
612
0
}
613
614
void ScDrawView::UpdateUserViewOptions()
615
0
{
616
0
    const ScViewOptions&    rOpt = rViewData.GetOptions();
617
0
    const ScGridOptions&    rGrid = rOpt.GetGridOptions();
618
619
0
    SetDragStripes( rOpt.GetOption(sc::ViewOption::HELPLINES) );
620
0
    SetMarkHdlSizePixel( SC_HANDLESIZE_BIG );
621
622
0
    SetGridVisible( rGrid.GetGridVisible() );
623
0
    SetSnapEnabled( rGrid.GetUseGridSnap() );
624
0
    SetGridSnap( rGrid.GetUseGridSnap() );
625
626
0
    double aFractX = double(rGrid.GetFieldDrawX()) / ( rGrid.GetFieldDivisionX() + 1 );
627
0
    double aFractY = double(rGrid.GetFieldDrawY()) / ( rGrid.GetFieldDivisionY() + 1 );
628
0
    SetSnapGridWidth( aFractX, aFractY );
629
630
0
    SetGridCoarse( Size( rGrid.GetFieldDrawX(), rGrid.GetFieldDrawY() ) );
631
0
    SetGridFine( Size( rGrid.GetFieldDrawX() / (rGrid.GetFieldDivisionX() + 1),
632
0
                       rGrid.GetFieldDrawY() / (rGrid.GetFieldDivisionY() + 1) ) );
633
0
}
634
635
SdrObject* ScDrawView::GetObjectByName(std::u16string_view rName)
636
0
{
637
0
    ScDocShell* pShell = rDoc.GetDocumentShell();
638
0
    if (pShell)
639
0
    {
640
0
        SdrModel& rDrawLayer = GetModel();
641
0
        sal_uInt16 nTabCount = rDoc.GetTableCount();
642
0
        for (sal_uInt16 i=0; i<nTabCount; i++)
643
0
        {
644
0
            SdrPage* pPage = rDrawLayer.GetPage(i);
645
0
            DBG_ASSERT(pPage,"Page ?");
646
0
            if (pPage)
647
0
            {
648
0
                SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
649
0
                SdrObject* pObject = aIter.Next();
650
0
                while (pObject)
651
0
                {
652
0
                    if ( ScDrawLayer::GetVisibleName( pObject ) == rName )
653
0
                    {
654
0
                        return pObject;
655
0
                    }
656
0
                    pObject = aIter.Next();
657
0
                }
658
0
            }
659
0
        }
660
0
    }
661
0
    return nullptr;
662
0
}
663
664
//realize multi-selection of objects
665
666
void ScDrawView::SelectCurrentViewObject( std::u16string_view rName )
667
0
{
668
0
    sal_uInt16 nObjectTab = 0;
669
0
    SdrObject* pFound = nullptr;
670
0
    ScDocShell* pShell = rDoc.GetDocumentShell();
671
0
    if (pShell)
672
0
    {
673
0
        SdrModel& rDrawLayer = GetModel();
674
0
        sal_uInt16 nTabCount = rDoc.GetTableCount();
675
0
        for (sal_uInt16 i=0; i<nTabCount && !pFound; i++)
676
0
        {
677
0
            SdrPage* pPage = rDrawLayer.GetPage(i);
678
0
            DBG_ASSERT(pPage,"Page ?");
679
0
            if (pPage)
680
0
            {
681
0
                SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
682
0
                SdrObject* pObject = aIter.Next();
683
0
                while (pObject && !pFound)
684
0
                {
685
0
                    if ( ScDrawLayer::GetVisibleName( pObject ) == rName )
686
0
                    {
687
0
                        pFound = pObject;
688
0
                        nObjectTab = i;
689
0
                    }
690
0
                    pObject = aIter.Next();
691
0
                }
692
0
            }
693
0
        }
694
0
    }
695
0
    if ( !pFound )
696
0
        return;
697
698
0
    ScTabView* pView = rViewData.GetView();
699
0
    if ( nObjectTab != nTab )                               // switch sheet
700
0
        pView->SetTabNo( nObjectTab );
701
0
    DBG_ASSERT( nTab == nObjectTab, "Switching sheets did not work" );
702
0
    pView->ScrollToObject( pFound );
703
0
    if ( pFound->GetLayer() == SC_LAYER_BACK &&
704
0
            !rViewData.GetViewShell()->IsDrawSelMode() &&
705
0
            !rDoc.IsTabProtected( nTab ) &&
706
0
            !rViewData.GetSfxDocShell()->IsReadOnly() )
707
0
    {
708
0
        SdrLayer* pLayer = GetModel().GetLayerAdmin().GetLayerPerID(SC_LAYER_BACK);
709
0
        if (pLayer)
710
0
            SetLayerLocked( pLayer->GetName(), false );
711
0
    }
712
0
    SdrPageView* pPV = GetSdrPageView();
713
0
    const bool bUnMark = IsObjMarked(pFound);
714
0
    MarkObj( pFound, pPV, bUnMark);
715
0
}
716
717
bool ScDrawView::SelectObject( std::u16string_view rName )
718
0
{
719
0
    UnmarkAll();
720
721
0
    SCTAB nObjectTab = 0;
722
0
    SdrObject* pFound = nullptr;
723
724
0
    ScDocShell* pShell = rDoc.GetDocumentShell();
725
0
    if (pShell)
726
0
    {
727
0
        SdrModel& rDrawLayer = GetModel();
728
0
        SCTAB nTabCount = rDoc.GetTableCount();
729
0
        for (SCTAB i=0; i<nTabCount && !pFound; i++)
730
0
        {
731
0
            SdrPage* pPage = rDrawLayer.GetPage(static_cast<sal_uInt16>(i));
732
0
            OSL_ENSURE(pPage,"Page ?");
733
0
            if (pPage)
734
0
            {
735
0
                SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
736
0
                SdrObject* pObject = aIter.Next();
737
0
                while (pObject && !pFound)
738
0
                {
739
0
                    if ( ScDrawLayer::GetVisibleName( pObject ) == rName )
740
0
                    {
741
0
                        pFound = pObject;
742
0
                        nObjectTab = i;
743
0
                    }
744
0
                    pObject = aIter.Next();
745
0
                }
746
0
            }
747
0
        }
748
0
    }
749
750
0
    if ( pFound )
751
0
    {
752
0
        ScTabView* pView = rViewData.GetView();
753
0
        if ( nObjectTab != nTab )                               // switch sheet
754
0
            pView->SetTabNo( nObjectTab );
755
756
0
        OSL_ENSURE( nTab == nObjectTab, "Switching sheets did not work" );
757
758
0
        pView->ScrollToObject( pFound );
759
760
        /*  To select an object on the background layer, the layer has to
761
            be unlocked even if exclusive drawing selection mode is not active
762
            (this is reversed in MarkListHasChanged when nothing is selected) */
763
0
        if ( pFound->GetLayer() == SC_LAYER_BACK &&
764
0
                !rViewData.GetViewShell()->IsDrawSelMode() &&
765
0
                !rDoc.IsTabProtected( nTab ) &&
766
0
                !rViewData.GetSfxDocShell()->IsReadOnly() )
767
0
        {
768
0
            LockBackgroundLayer(false);
769
0
        }
770
771
0
        SdrPageView* pPV = GetSdrPageView();
772
0
        MarkObj( pFound, pPV );
773
0
    }
774
775
0
    return ( pFound != nullptr );
776
0
}
777
778
//If  object  is marked , return true , else return false .
779
bool ScDrawView::GetObjectIsMarked(  const SdrObject* pObject  )
780
0
{
781
0
    bool bisMarked = false;
782
0
    if (pObject )
783
0
    {
784
0
        bisMarked = IsObjMarked(pObject);
785
0
    }
786
0
    return  bisMarked;
787
0
}
788
789
bool ScDrawView::InsertObjectSafe(SdrObject* pObj, SdrPageView& rPV)
790
0
{
791
0
    SdrInsertFlags nOptions=SdrInsertFlags::NONE;
792
    // Do not change marks when the ole object is active
793
    // (for Drop from ole object would otherwise be deactivated in the middle of ExecuteDrag!)
794
795
0
    SfxInPlaceClient* pClient = rViewData.GetViewShell()->GetIPClient();
796
0
    if ( pClient && pClient->IsObjectInPlaceActive() )
797
0
        nOptions |= SdrInsertFlags::DONTMARK;
798
799
0
    return InsertObjectAtView(pObj, rPV, nOptions);
800
0
}
801
802
SdrObject* ScDrawView::GetMarkedNoteCaption( ScDrawObjData** ppCaptData )
803
0
{
804
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
805
0
    if( rMarkList.GetMarkCount() == 1 )
806
0
    {
807
0
        SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
808
0
        if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObj, rViewData.CurrentTabForData() ) )
809
0
        {
810
0
            if( ppCaptData ) *ppCaptData = pCaptData;
811
0
            return pObj;
812
0
        }
813
0
    }
814
0
    return nullptr;
815
0
}
816
817
void ScDrawView::LockCalcLayer( SdrLayerID nLayer, bool bLock )
818
0
{
819
0
    SdrLayer* pLockLayer = GetModel().GetLayerAdmin().GetLayerPerID( nLayer );
820
0
    if( pLockLayer && (IsLayerLocked( pLockLayer->GetName() ) != bLock) )
821
0
        SetLayerLocked( pLockLayer->GetName(), bLock );
822
0
}
823
824
void ScDrawView::MakeVisible( const tools::Rectangle& rRect, vcl::Window& rWin )
825
0
{
826
    //! Evaluate rWin properly
827
    //! change zoom if necessary
828
829
0
    if ( rViewData.GetActiveWin() == &rWin )
830
0
        rViewData.GetView()->MakeVisible( rRect );
831
0
}
832
833
SfxViewShell* ScDrawView::GetSfxViewShell() const
834
0
{
835
0
    return rViewData.GetViewShell();
836
0
}
837
838
void ScDrawView::DeleteMarked()
839
0
{
840
    // try to delete a note caption object with its cell note in the Calc document
841
0
    ScDrawObjData* pCaptData = nullptr;
842
0
    if( SdrObject* pCaptObj = GetMarkedNoteCaption( &pCaptData ) )
843
0
    {
844
0
        ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
845
0
        ScDocShell* pDocShell = rViewData.GetDocShell();
846
0
        SfxUndoManager* pUndoMgr = pDocShell ? pDocShell->GetUndoManager() : nullptr;
847
0
        bool bUndo = pDrawLayer && pDocShell && pUndoMgr && rDoc.IsUndoEnabled();
848
849
        // remove the cell note from document, we are its owner now
850
0
        std::unique_ptr<ScPostIt> pNote = rDoc.ReleaseNote( pCaptData->maStart );
851
0
        OSL_ENSURE( pNote, "ScDrawView::DeleteMarked - cell note missing in document" );
852
0
        if( pNote )
853
0
        {
854
            // rescue note data for undo (with pointer to caption object)
855
0
            ScNoteData aNoteData = pNote->GetNoteData();
856
0
            OSL_ENSURE( aNoteData.mxCaption.get() == pCaptObj, "ScDrawView::DeleteMarked - caption object does not match" );
857
            // collect the drawing undo action created while deleting the note
858
0
            if( bUndo )
859
0
                pDrawLayer->BeginCalcUndo(false);
860
            // delete the note (already removed from document above)
861
0
            pNote.reset();
862
            // add the undo action for the note
863
0
            if( bUndo )
864
0
                pUndoMgr->AddUndoAction( std::make_unique<ScUndoReplaceNote>( *pDocShell, pCaptData->maStart, aNoteData, false, pDrawLayer->GetCalcUndo() ) );
865
            // repaint the cell to get rid of the note marker
866
0
            if( pDocShell )
867
0
                pDocShell->PostPaintCell( pCaptData->maStart );
868
            // done, return now to skip call of FmFormView::DeleteMarked()
869
0
            return;
870
0
        }
871
0
    }
872
873
0
    FmFormView::DeleteMarked();
874
0
}
875
876
SdrEndTextEditKind ScDrawView::ScEndTextEdit()
877
0
{
878
0
    bool bIsTextEdit = IsTextEdit();
879
0
    SdrEndTextEditKind eKind = SdrEndTextEdit();
880
881
0
    if (bIsTextEdit)
882
0
        rViewData.GetViewShell()->SetDrawTextUndo(nullptr);   // the "normal" undo manager
883
884
0
    return eKind;
885
0
}
886
887
void ScDrawView::MarkDropObj( SdrObject* pObj )
888
0
{
889
0
    if ( pDropMarkObj != pObj )
890
0
    {
891
0
        pDropMarkObj = pObj;
892
0
        ImplClearCalcDropMarker();
893
894
0
        if(pDropMarkObj)
895
0
        {
896
0
            pDropMarker.reset( new SdrDropMarkerOverlay(*this, *pDropMarkObj) );
897
0
        }
898
0
    }
899
0
}
900
901
// In order to counteract the effects of rounding due to the nature of how the
902
// grid positions are calculated and drawn we calculate the offset needed at the
903
// current zoom to be applied to an SrdObject when it is drawn in order to make
904
// sure that it's position relative to the nearest cell anchor doesn't change.
905
// Of course not all shape(s)/control(s) are cell anchored, if the
906
// object doesn't have a cell anchor we synthesise a temporary anchor.
907
void ScDrawView::SyncForGrid( SdrObject* pObj )
908
0
{
909
    // process members of a group shape separately
910
0
    if ( auto pObjGroup = dynamic_cast<const SdrObjGroup*>( pObj) )
911
0
    {
912
0
        SdrObjList *pLst = pObjGroup->GetSubList();
913
0
        for (const rtl::Reference<SdrObject>& pChild : *pLst)
914
0
            SyncForGrid( pChild.get() );
915
0
    }
916
917
0
    ScSplitPos eWhich = rViewData.GetActivePart();
918
0
    ScGridWindow* pGridWin = rViewData.GetActiveWin();
919
0
    ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
920
0
    if ( !pGridWin )
921
0
        return;
922
923
0
    ScAddress aOldStt;
924
0
    if( pData && pData->maStart.IsValid())
925
0
    {
926
0
        aOldStt = pData->maStart;
927
0
    }
928
0
    else
929
0
    {
930
        // Page anchored object so...
931
        // synthesise an anchor ( but don't attach it to
932
        // the object as we want to maintain page anchoring )
933
0
        ScDrawObjData aAnchor;
934
0
        const tools::Rectangle aObjRect(pObj->GetLogicRect());
935
0
        ScDrawLayer::GetCellAnchorFromPosition(
936
0
            aObjRect,
937
0
            aAnchor,
938
0
            rDoc,
939
0
            GetTab());
940
0
        aOldStt = aAnchor.maStart;
941
0
    }
942
0
    MapMode aDrawMode = pGridWin->GetDrawMapMode();
943
    // find pos anchor position
944
0
    Point aOldPos( rDoc.GetColOffset( aOldStt.Col(), aOldStt.Tab()  ), rDoc.GetRowOffset( aOldStt.Row(), aOldStt.Tab() ) );
945
0
    aOldPos = convertTwipToMm100(aOldPos);
946
    // find position of same point on the screen ( e.g. grid )
947
0
    Point aCurPos =  rViewData.GetScrPos(  aOldStt.Col(), aOldStt.Row(), eWhich, true );
948
0
    Point aCurPosHmm = pGridWin->PixelToLogic(aCurPos, aDrawMode );
949
0
    Point aGridOff = aCurPosHmm - aOldPos;
950
    // fdo#63878 Fix the X position for RTL Sheet
951
0
    if( rDoc.IsNegativePage( GetTab() ) && !comphelper::LibreOfficeKit::isActive() )
952
0
        aGridOff.setX( aCurPosHmm.getX() + aOldPos.getX() );
953
0
}
954
955
void ScDrawView::resetGridOffsetsForAllSdrPageViews()
956
0
{
957
0
    if (SdrPageView* pPageView = GetSdrPageView())
958
0
        pPageView->resetGridOffsetsOfAllPageWindows();
959
0
}
960
961
bool ScDrawView::calculateGridOffsetForSdrObject(
962
    SdrObject& rSdrObject,
963
    basegfx::B2DVector& rTarget) const
964
0
{
965
0
    if (comphelper::LibreOfficeKit::isActive() &&
966
0
            !comphelper::LibreOfficeKit::isCompatFlagSet(
967
0
                    comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
968
0
        return false;
969
970
0
    ScGridWindow* pGridWin(rViewData.GetActiveWin());
971
972
0
    if(nullptr == pGridWin)
973
0
    {
974
0
        return false;
975
0
    }
976
977
0
    ScDrawObjData* pData(ScDrawLayer::GetObjData(&rSdrObject));
978
0
    ScAddress aOldStt;
979
980
0
    if(nullptr != pData && pData->maStart.IsValid())
981
0
    {
982
0
        aOldStt = pData->maStart;
983
0
    }
984
0
    else
985
0
    {
986
        // Page anchored object so...
987
        // synthesise an anchor ( but don't attach it to
988
        // the object as we want to maintain page anchoring )
989
0
        ScDrawObjData aAnchor;
990
0
        const tools::Rectangle aObjRect(rSdrObject.GetLogicRect());
991
0
        ScDrawLayer::GetCellAnchorFromPosition(
992
0
            aObjRect,
993
0
            aAnchor,
994
0
            rDoc,
995
0
            GetTab());
996
0
        aOldStt = aAnchor.maStart;
997
0
    }
998
999
0
    MapMode aDrawMode = pGridWin->GetDrawMapMode();
1000
1001
    // find pos anchor position
1002
0
    Point aOldPos(rDoc.GetColOffset(aOldStt.Col(), aOldStt.Tab()), rDoc.GetRowOffset(aOldStt.Row(), aOldStt.Tab()));
1003
0
    aOldPos = convertTwipToMm100(aOldPos);
1004
1005
    // find position of same point on the screen ( e.g. grid )
1006
0
    ScSplitPos eWhich(rViewData.GetActivePart());
1007
0
    Point aCurPos(rViewData.GetScrPos(aOldStt.Col(), aOldStt.Row(), eWhich, true));
1008
0
    Point aCurPosHmm(pGridWin->PixelToLogic(aCurPos, aDrawMode));
1009
0
    Point aGridOff(aCurPosHmm - aOldPos);
1010
1011
0
    bool bLOKActive = comphelper::LibreOfficeKit::isActive();
1012
0
    bool bNegativePage = rDoc.IsNegativePage(GetTab());
1013
1014
    // fdo#63878 Fix the X position for RTL Sheet
1015
0
    if(bNegativePage && !bLOKActive)
1016
0
    {
1017
0
        aGridOff.setX(aCurPosHmm.getX() + aOldPos.getX());
1018
0
    }
1019
1020
0
    rTarget.setX(bNegativePage && bLOKActive ? -aGridOff.X() : aGridOff.X());
1021
0
    rTarget.setY(aGridOff.Y());
1022
0
    return true;
1023
0
}
1024
1025
bool ScDrawView::calculateGridOffsetForB2DRange(
1026
    const basegfx::B2DRange& rB2DRange,
1027
    basegfx::B2DVector& rTarget) const
1028
0
{
1029
0
    ScGridWindow* pGridWin(rViewData.GetActiveWin());
1030
1031
0
    if(nullptr == pGridWin || rB2DRange.isEmpty())
1032
0
    {
1033
0
        return false;
1034
0
    }
1035
1036
    // No SdrObject, so synthesise an anchor ( but don't attach it to
1037
    // the object as we want to maintain page anchoring )
1038
0
    ScDrawObjData aAnchor;
1039
0
    const tools::Rectangle aRectangle(
1040
0
        basegfx::fround<tools::Long>(rB2DRange.getMinX()), basegfx::fround<tools::Long>(rB2DRange.getMinY()),
1041
0
        basegfx::fround<tools::Long>(rB2DRange.getMaxX()), basegfx::fround<tools::Long>(rB2DRange.getMaxY()));
1042
0
    ScDrawLayer::GetCellAnchorFromPosition(
1043
0
        aRectangle,
1044
0
        aAnchor,
1045
0
        rDoc,
1046
0
        GetTab());
1047
0
    ScAddress aOldStt(aAnchor.maStart);
1048
1049
0
    MapMode aDrawMode = pGridWin->GetDrawMapMode();
1050
1051
    // find pos anchor position
1052
0
    Point aOldPos(rDoc.GetColOffset(aOldStt.Col(), aOldStt.Tab()), rDoc.GetRowOffset(aOldStt.Row(), aOldStt.Tab()));
1053
0
    aOldPos = convertTwipToMm100(aOldPos);
1054
1055
    // find position of same point on the screen ( e.g. grid )
1056
0
    ScSplitPos eWhich(rViewData.GetActivePart());
1057
0
    Point aCurPos(rViewData.GetScrPos(aOldStt.Col(), aOldStt.Row(), eWhich, true));
1058
0
    Point aCurPosHmm(pGridWin->PixelToLogic(aCurPos, aDrawMode));
1059
0
    Point aGridOff(aCurPosHmm - aOldPos);
1060
1061
0
    bool bLOKActive = comphelper::LibreOfficeKit::isActive();
1062
0
    bool bNegativePage = rDoc.IsNegativePage(GetTab());
1063
1064
    // fdo#63878 Fix the X position for RTL Sheet
1065
0
    if(bNegativePage && !bLOKActive)
1066
0
    {
1067
0
        aGridOff.setX(aCurPosHmm.getX() + aOldPos.getX());
1068
0
    }
1069
1070
0
    rTarget.setX(bLOKActive && bNegativePage ? -aGridOff.X() : aGridOff.X());
1071
0
    rTarget.setY(aGridOff.Y());
1072
0
    return true;
1073
0
}
1074
1075
// Create a new view-local UndoManager manager for Calc
1076
std::unique_ptr<SdrUndoManager> ScDrawView::createLocalTextUndoManager()
1077
0
{
1078
0
    std::unique_ptr<SdrUndoManager> pUndoManager(new SdrUndoManager);
1079
0
    ScDocShell* pDocShell = rViewData.GetDocShell();
1080
0
    pUndoManager->SetDocShell(pDocShell);
1081
0
    return pUndoManager;
1082
0
}
1083
1084
// #i123922# helper to apply a Graphic to an existing SdrObject
1085
SdrObject* ScDrawView::ApplyGraphicToObject(
1086
    SdrObject& rHitObject,
1087
    const Graphic& rGraphic,
1088
    const OUString& rBeginUndoText,
1089
    const OUString& rFile)
1090
0
{
1091
0
    if(auto pGrafHitObj = dynamic_cast< SdrGrafObj* >(&rHitObject))
1092
0
    {
1093
0
        rtl::Reference<SdrGrafObj> pNewGrafObj = SdrObject::Clone(*pGrafHitObj, rHitObject.getSdrModelFromSdrObject());
1094
1095
0
        pNewGrafObj->SetGraphic(rGraphic);
1096
0
        BegUndo(rBeginUndoText);
1097
0
        ReplaceObjectAtView(&rHitObject, *GetSdrPageView(), pNewGrafObj.get());
1098
1099
        // set in all cases - the Clone() will have copied an existing link (!)
1100
0
        if (!rFile.isEmpty())
1101
0
            pNewGrafObj->SetGraphicLink(rFile);
1102
1103
0
        EndUndo();
1104
0
        return pNewGrafObj.get();
1105
0
    }
1106
0
    else if(rHitObject.IsClosedObj() && !dynamic_cast< SdrOle2Obj* >(&rHitObject))
1107
0
    {
1108
0
        AddUndo(std::make_unique<SdrUndoAttrObj>(rHitObject));
1109
1110
0
        SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<XATTR_FILLSTYLE, XATTR_FILLBITMAP>(GetModel().GetItemPool()));
1111
1112
0
        aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
1113
0
        aSet.Put(XFillBitmapItem(OUString(), rGraphic));
1114
0
        rHitObject.SetMergedItemSetAndBroadcast(aSet);
1115
0
        return &rHitObject;
1116
0
    }
1117
1118
0
    return nullptr;
1119
0
}
1120
1121
// Own derivation of ObjectContact to allow on-demand calculation of
1122
// GridOffset for non-linear ViewToDevice transformation (calc)
1123
namespace sdr::contact
1124
{
1125
        namespace {
1126
1127
        class ObjectContactOfScDrawView final : public ObjectContactOfPageView
1128
        {
1129
        private:
1130
            // The ScDrawView to work on
1131
            const ScDrawView&       mrScDrawView;
1132
1133
        public:
1134
            explicit ObjectContactOfScDrawView(
1135
                const ScDrawView& rScDrawView,
1136
                SdrPageWindow& rPageWindow,
1137
                const char* pDebugName);
1138
1139
            virtual bool supportsGridOffsets() const override;
1140
            virtual void calculateGridOffsetForViewObjectContact(
1141
                basegfx::B2DVector& rTarget,
1142
                const ViewObjectContact& rClient) const override;
1143
            virtual void calculateGridOffsetForB2DRange(
1144
                basegfx::B2DVector& rTarget,
1145
                const basegfx::B2DRange& rB2DRange) const override;
1146
        };
1147
1148
        }
1149
1150
        ObjectContactOfScDrawView::ObjectContactOfScDrawView(
1151
            const ScDrawView& rScDrawView,
1152
            SdrPageWindow& rPageWindow,
1153
            const char* pDebugName)
1154
0
        :   ObjectContactOfPageView(rPageWindow, pDebugName),
1155
0
            mrScDrawView(rScDrawView)
1156
0
        {
1157
0
        }
1158
1159
        bool ObjectContactOfScDrawView::supportsGridOffsets() const
1160
0
        {
1161
            // Except when scPrintTwipsMsgs flag is active,
1162
            // Calc in LOK mode directly sets pixel-aligned logical coordinates for draw-objects.
1163
0
            if (comphelper::LibreOfficeKit::isActive() &&
1164
0
                !comphelper::LibreOfficeKit::isCompatFlagSet(
1165
0
                    comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
1166
0
                return false;
1167
1168
            // no GridOffset support for printer
1169
0
            if(isOutputToPrinter())
1170
0
            {
1171
0
                return false;
1172
0
            }
1173
1174
            // no GridOffset support for PDF export
1175
0
            if(isOutputToPDFFile())
1176
0
            {
1177
0
                return false;
1178
0
            }
1179
1180
            // yes - we support it
1181
0
            return true;
1182
0
        }
1183
1184
        void ObjectContactOfScDrawView::calculateGridOffsetForViewObjectContact(
1185
            basegfx::B2DVector& rTarget,
1186
            const ViewObjectContact& rClient) const
1187
0
        {
1188
            // Here the on-demand calculation happens. Try to access the SdrObject involved
1189
0
            SdrObject* pTargetSdrObject(rClient.GetViewContact().TryToGetSdrObject());
1190
1191
0
            if(nullptr != pTargetSdrObject)
1192
0
            {
1193
0
                mrScDrawView.calculateGridOffsetForSdrObject(
1194
0
                    *pTargetSdrObject,
1195
0
                    rTarget);
1196
0
            }
1197
0
        }
1198
1199
        void ObjectContactOfScDrawView::calculateGridOffsetForB2DRange(
1200
            basegfx::B2DVector& rTarget,
1201
            const basegfx::B2DRange& rB2DRange) const
1202
0
        {
1203
            // Here the on-demand calculation happens. Try to access the SdrObject involved
1204
0
            if(!rB2DRange.isEmpty())
1205
0
            {
1206
0
                mrScDrawView.calculateGridOffsetForB2DRange(
1207
0
                    rB2DRange,
1208
0
                    rTarget);
1209
0
            }
1210
0
        }
1211
}
1212
1213
// Create own derivation of ObjectContact for calc
1214
sdr::contact::ObjectContact* ScDrawView::createViewSpecificObjectContact(
1215
    SdrPageWindow& rPageWindow,
1216
    const char* pDebugName) const
1217
0
{
1218
0
    return new sdr::contact::ObjectContactOfScDrawView(
1219
0
        *this,
1220
0
        rPageWindow,
1221
0
        pDebugName);
1222
0
}
1223
1224
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */