Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/gridwin3.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 <svx/svdpagv.hxx>
21
#include <svx/svxids.hrc>
22
#include <editeng/sizeitem.hxx>
23
#include <sfx2/bindings.hxx>
24
#include <svl/ptitem.hxx>
25
#include <osl/diagnose.h>
26
#include <vcl/ptrstyle.hxx>
27
28
#include <tabvwsh.hxx>
29
#include <gridwin.hxx>
30
#include <dbfunc.hxx>
31
#include <viewdata.hxx>
32
#include <output.hxx>
33
#include <drawview.hxx>
34
#include <fupoor.hxx>
35
#include <fusel.hxx>
36
#include <scmod.hxx>
37
#include <appoptio.hxx>
38
39
#include <drawutil.hxx>
40
#include <document.hxx>
41
#include <comphelper/lok.hxx>
42
43
static bool lcl_HasSelectionChanged(const SdrMarkList & rBeforeList, const SdrMarkList & rAfterList)
44
0
{
45
0
    if (rBeforeList.GetMarkCount() != rAfterList.GetMarkCount())
46
0
        return true;
47
0
    for (size_t nObject = 0; nObject < rBeforeList.GetMarkCount(); ++nObject)
48
0
    {
49
0
        if (rBeforeList.GetMark(nObject)->GetMarkedSdrObj() !=
50
0
            rAfterList.GetMark(nObject)->GetMarkedSdrObj())
51
0
            return true;
52
0
    }
53
0
    return false;
54
0
}
55
56
bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt)
57
0
{
58
    // Keep track of the mouse position when the left button was pressed so we can detect if it was
59
    // moved on mouse up
60
0
    if (rMEvt.IsLeft())
61
0
        aDrawMouseDownPos = rMEvt.GetPosPixel();
62
63
0
    bool bRet = false;
64
0
    FuPoor* pDraw = mrViewData.GetView()->GetDrawFuncPtr();
65
0
    if (pDraw)
66
0
        pDraw->ResetSelectionHasChanged();
67
0
    ScDrawView* pDrView = mrViewData.GetScDrawView();
68
0
    if (pDraw && !mrViewData.IsRefMode())
69
0
    {
70
0
        MapMode aDrawMode = GetDrawMapMode();
71
0
        MapMode aOldMode = GetMapMode();
72
0
        if ( comphelper::LibreOfficeKit::isActive() && aOldMode != aDrawMode )
73
0
            SetMapMode( aDrawMode );
74
75
0
        pDraw->SetWindow( this );
76
0
        Point aLogicPos = PixelToLogic(rMEvt.GetPosPixel());
77
78
0
        if ( pDraw->IsDetectiveHit( aLogicPos ) )
79
0
        {
80
            // nothing on detective arrows (double click is evaluated on ButtonUp)
81
0
            bRet = true;
82
0
        }
83
0
        else
84
0
        {
85
0
            SdrMarkList aPreMarkList = pDrView->GetMarkedObjectList();
86
0
            bRet = pDraw->MouseButtonDown( rMEvt );
87
0
            if (bRet)
88
0
            {
89
0
                if (lcl_HasSelectionChanged(aPreMarkList, pDrView->GetMarkedObjectList()))
90
0
                    pDraw->SetSelectionHasChanged();
91
0
                UpdateStatusPosSize();
92
0
            }
93
0
        }
94
95
0
        if ( comphelper::LibreOfficeKit::isActive() && aOldMode != aDrawMode )
96
0
            SetMapMode( aOldMode );
97
0
    }
98
99
    // cancel draw with right key
100
0
    if ( pDrView && !rMEvt.IsLeft() && !bRet )
101
0
    {
102
0
        pDrView->BrkAction();
103
0
        bRet = true;
104
0
    }
105
0
    return bRet;
106
0
}
107
108
namespace
109
{
110
bool lcl_MouseUnmoved(ScDrawView* pDrView, const MouseEvent& rMEvt, const Point& aDownPos)
111
0
{
112
0
    sal_Int32 nThreshold = pDrView->GetDragThresholdPixels();
113
0
    const Point& aMousePos = rMEvt.GetPosPixel();
114
115
0
    return std::abs(aMousePos.getX() - aDownPos.getX()) < nThreshold &&
116
0
        std::abs(aMousePos.getY() - aDownPos.getY()) < nThreshold;
117
0
}
118
}
119
120
bool ScGridWindow::DrawMouseButtonUp(const MouseEvent& rMEvt)
121
0
{
122
0
    ScViewFunc* pView = mrViewData.GetView();
123
0
    bool bRet = false;
124
0
    bool bLOKitActive = comphelper::LibreOfficeKit::isActive();
125
0
    FuPoor* pDraw = pView->GetDrawFuncPtr();
126
0
    if (pDraw && !mrViewData.IsRefMode())
127
0
    {
128
0
        MapMode aDrawMode = GetDrawMapMode();
129
0
        MapMode aOldMode = GetMapMode();
130
0
        if ( bLOKitActive && aOldMode != aDrawMode )
131
0
            SetMapMode( aDrawMode );
132
133
0
        pDraw->SetWindow( this );
134
0
        bRet = pDraw->MouseButtonUp( rMEvt );
135
136
        // execute "format paint brush" for drawing objects
137
0
        SfxItemSet* pDrawBrush = pView->GetDrawBrushSet();
138
0
        ScDrawView* pDrView = mrViewData.GetScDrawView();
139
0
        if ( pDrawBrush )
140
0
        {
141
0
            if ( pDrView )
142
0
            {
143
0
                pDrView->SetAttrToMarked(*pDrawBrush, true/*bReplaceAll*/);
144
0
            }
145
146
0
            if ( !pView->IsPaintBrushLocked() )
147
0
                pView->ResetBrushDocument(); // end paint brush mode if not locked
148
0
        }
149
0
        else if (!bLOKitActive && pDrView->GetMarkedObjectList().GetMarkCount() > 0
150
0
                 && rMEvt.IsLeft()
151
0
                 && rMEvt.GetClicks() == 1
152
0
            && ScModule::get()->GetAppOptions().IsClickChangeRotation()
153
0
            && !pDraw->HasSelectionChanged()
154
0
            && dynamic_cast<FuSelection*>(pDraw)
155
0
            && lcl_MouseUnmoved(pDrView, rMEvt, aDrawMouseDownPos))
156
0
        {
157
0
            mrViewData.GetView()->SwitchRotateMode();
158
0
        }
159
160
0
        if ( bLOKitActive && aOldMode != aDrawMode )
161
0
            SetMapMode( aOldMode );
162
0
    }
163
164
0
    return bRet;
165
0
}
166
167
bool ScGridWindow::DrawMouseMove(const MouseEvent& rMEvt)
168
0
{
169
0
    FuPoor* pDraw = mrViewData.GetView()->GetDrawFuncPtr();
170
0
    if (pDraw && !mrViewData.IsRefMode())
171
0
    {
172
0
        MapMode aDrawMode = GetDrawMapMode();
173
0
        MapMode aOldMode = GetMapMode();
174
0
        if ( comphelper::LibreOfficeKit::isActive() && aOldMode != aDrawMode )
175
0
            SetMapMode( aDrawMode );
176
177
0
        pDraw->SetWindow( this );
178
0
        bool bRet = pDraw->MouseMove( rMEvt );
179
0
        if ( bRet )
180
0
            UpdateStatusPosSize();
181
182
0
        if ( comphelper::LibreOfficeKit::isActive() && aOldMode != aDrawMode )
183
0
            SetMapMode( aOldMode );
184
185
0
        return bRet;
186
0
    }
187
0
    else
188
0
    {
189
0
        SetPointer( PointerStyle::Arrow );
190
0
        return false;
191
0
    }
192
0
}
193
194
void ScGridWindow::DrawEndAction()
195
0
{
196
0
    ScDrawView* pDrView = mrViewData.GetScDrawView();
197
0
    if ( pDrView && pDrView->IsAction() )
198
0
        pDrView->BrkAction();
199
200
0
    FuPoor* pDraw = mrViewData.GetView()->GetDrawFuncPtr();
201
0
    if (pDraw)
202
0
        pDraw->StopDragTimer();
203
204
    //  ReleaseMouse on call
205
0
}
206
207
bool ScGridWindow::DrawCommand(const CommandEvent& rCEvt)
208
0
{
209
0
    ScDrawView* pDrView = mrViewData.GetScDrawView();
210
0
    FuPoor* pDraw = mrViewData.GetView()->GetDrawFuncPtr();
211
0
    if (pDrView && pDraw && !mrViewData.IsRefMode())
212
0
    {
213
0
        pDraw->SetWindow( this );
214
0
        sal_uInt8 nUsed = pDraw->Command( rCEvt );
215
0
        if( nUsed == SC_CMD_USED )
216
0
            nButtonDown = 0;  // MouseButtonUp is swallowed...
217
0
        if( nUsed || pDrView->IsAction() )
218
0
            return true;
219
0
    }
220
221
0
    return false;
222
0
}
223
224
bool ScGridWindow::DrawKeyInput(const KeyEvent& rKEvt, vcl::Window* pWin)
225
0
{
226
0
    ScDrawView* pDrView = mrViewData.GetScDrawView();
227
0
    FuPoor* pDraw = mrViewData.GetView()->GetDrawFuncPtr();
228
229
230
0
    if (pDrView && pDrView->KeyInput(rKEvt, pWin))
231
0
        return true;
232
233
0
    if (pDrView && pDraw && !mrViewData.IsRefMode())
234
0
    {
235
0
        pDraw->SetWindow( this );
236
0
        const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
237
0
        bool bOldMarked = rMarkList.GetMarkCount() != 0;
238
0
        if (pDraw->KeyInput( rKEvt ))
239
0
        {
240
0
            bool bLeaveDraw = false;
241
0
            bool bUsed = true;
242
0
            bool bNewMarked = rMarkList.GetMarkCount() != 0;
243
0
            if ( !mrViewData.GetView()->IsDrawSelMode() )
244
0
                if ( !bNewMarked )
245
0
                {
246
0
                    mrViewData.GetViewShell()->SetDrawShell( false );
247
0
                    bLeaveDraw = true;
248
0
                    if ( !bOldMarked &&
249
0
                        rKEvt.GetKeyCode().GetCode() == KEY_DELETE )
250
0
                        bUsed = false; // nothing deleted
251
0
                    if(bOldMarked)
252
0
                        GetFocus();
253
0
                }
254
0
            if (!bLeaveDraw)
255
0
                UpdateStatusPosSize(); // for moving/resizing etc. by keyboard
256
0
            return bUsed;
257
0
        }
258
0
    }
259
260
0
    return false;
261
0
}
262
263
void ScGridWindow::DrawRedraw( ScOutputData& rOutputData, SdrLayerID nLayer )
264
0
{
265
0
    const ScViewOptions& rOpts = mrViewData.GetOptions();
266
267
    // use new flags at SdrPaintView for hiding objects
268
0
    const bool bDrawOle(VOBJ_MODE_SHOW == rOpts.GetObjMode(sc::ViewObjectType::OLE));
269
0
    const bool bDrawChart(VOBJ_MODE_SHOW == rOpts.GetObjMode(sc::ViewObjectType::CHART));
270
0
    const bool bDrawDraw(VOBJ_MODE_SHOW == rOpts.GetObjMode(sc::ViewObjectType::DRAW));
271
272
0
    if(!(bDrawOle || bDrawChart || bDrawDraw))
273
0
        return;
274
275
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
276
277
0
    if(pDrView)
278
0
    {
279
0
        pDrView->setHideOle(!bDrawOle);
280
0
        pDrView->setHideChart(!bDrawChart);
281
0
        pDrView->setHideDraw(!bDrawDraw);
282
0
        pDrView->setHideFormControl(!bDrawDraw);
283
0
    }
284
285
0
    rOutputData.DrawSelectiveObjects(nLayer);
286
0
}
287
288
void ScGridWindow::DrawSdrGrid( const tools::Rectangle& rDrawingRect, OutputDevice* pContentDev )
289
0
{
290
    // Draw grid lines
291
292
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
293
0
    if ( pDrView && pDrView->IsGridVisible() )
294
0
    {
295
0
        SdrPageView* pPV = pDrView->GetSdrPageView();
296
0
        OSL_ENSURE(pPV, "PageView not available");
297
0
        if (pPV)
298
0
        {
299
0
            pContentDev->SetLineColor(COL_GRAY);
300
301
0
            pPV->DrawPageViewGrid( *pContentDev, rDrawingRect );
302
0
        }
303
0
    }
304
0
}
305
306
MapMode ScGridWindow::GetDrawMapMode( bool bForce )
307
0
{
308
0
    ScDocument& rDoc = mrViewData.GetDocument();
309
310
    // FIXME this shouldn't be necessary once we change the entire Calc to
311
    // work in the logic coordinates (ideally 100ths of mm - so that it is
312
    // the same as editeng and drawinglayer), and get rid of all the
313
    // SetMapMode's and other unnecessary fun we have with pixels
314
0
    if (comphelper::LibreOfficeKit::isActive())
315
0
    {
316
0
        return mrViewData.GetLogicMode();
317
0
    }
318
319
0
    SCTAB nTab = mrViewData.CurrentTabForData();
320
0
    bool bNegativePage = rDoc.IsNegativePage( nTab );
321
322
0
    MapMode aDrawMode = mrViewData.GetLogicMode();
323
324
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
325
0
    if ( pDrView || bForce )
326
0
    {
327
0
        double fScaleX;
328
0
        double fScaleY;
329
0
        if (pDrView)
330
0
            pDrView->GetScale( fScaleX, fScaleY );
331
0
        else
332
0
        {
333
0
            SCCOL nEndCol = 0;
334
0
            SCROW nEndRow = 0;
335
0
            rDoc.GetTableArea( nTab, nEndCol, nEndRow );
336
0
            if (nEndCol<20) nEndCol = 20;
337
0
            if (nEndRow<20) nEndRow = 1000;
338
0
            ScDrawUtil::CalcScale( rDoc, nTab, 0,0, nEndCol,nEndRow, GetOutDev(),
339
0
                                   mrViewData.GetZoomX(),mrViewData.GetZoomY(),
340
0
                                   mrViewData.GetPPTX(),mrViewData.GetPPTY(),
341
0
                                   fScaleX,fScaleY );
342
0
        }
343
0
        aDrawMode.SetScaleX(fScaleX);
344
0
        aDrawMode.SetScaleY(fScaleY);
345
0
    }
346
0
    aDrawMode.SetOrigin(Point());
347
0
    Point aStartPos = mrViewData.GetPixPos(eWhich);
348
0
    if ( bNegativePage )
349
0
    {
350
        //  RTL uses negative positions for drawing objects
351
0
        aStartPos.setX( -aStartPos.X() + GetOutputSizePixel().Width() - 1 );
352
0
    }
353
0
    aDrawMode.SetOrigin( PixelToLogic( aStartPos, aDrawMode ) );
354
355
0
    return aDrawMode;
356
0
}
357
358
void ScGridWindow::DrawAfterScroll()
359
0
{
360
0
    PaintImmediately(); // always, so the behaviour with and without DrawingLayer is the same
361
362
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
363
0
    if (pDrView)
364
0
    {
365
0
        OutlinerView* pOlView = pDrView->GetTextEditOutlinerView();
366
0
        if (pOlView && pOlView->GetWindow() == this)
367
0
            pOlView->ShowCursor(false); // was removed at scrolling
368
0
    }
369
0
}
370
371
void ScGridWindow::CreateAnchorHandle(SdrHdlList& rHdl, const ScAddress& rAddress)
372
0
{
373
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
374
0
    if (pDrView)
375
0
    {
376
0
        const ScViewOptions& rOpts = mrViewData.GetOptions();
377
0
        if(rOpts.GetOption(sc::ViewOption::ANCHOR))
378
0
        {
379
0
            bool bNegativePage = mrViewData.GetDocument().IsNegativePage( mrViewData.CurrentTabForData() );
380
0
            Point aPos = mrViewData.GetScrPos( rAddress.Col(), rAddress.Row(), eWhich, true );
381
0
            aPos = PixelToLogic(aPos);
382
0
            rHdl.AddHdl(std::make_unique<SdrHdl>(aPos, bNegativePage ? SdrHdlKind::Anchor_TR : SdrHdlKind::Anchor));
383
0
        }
384
0
    }
385
0
}
386
387
void ScGridWindow::UpdateStatusPosSize()
388
0
{
389
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
390
0
    if (!pDrView)
391
0
        return; // shouldn't be called in that case
392
393
0
    SdrPageView* pPV = pDrView->GetSdrPageView();
394
0
    if (!pPV)
395
0
        return; // shouldn't be called in that case either
396
397
0
    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<SID_ATTR_POSITION, SID_ATTR_SIZE>(mrViewData.GetViewShell()->GetPool()));
398
399
    //  Fill items for position and size:
400
    //  show action rectangle during action,
401
    //  position and size of selected object(s) if something is selected,
402
    //  mouse position otherwise
403
404
0
    bool bActionItem = false;
405
0
    if ( pDrView->IsAction() ) // action rectangle
406
0
    {
407
0
        tools::Rectangle aRect;
408
0
        pDrView->TakeActionRect( aRect );
409
0
        if ( !aRect.IsEmpty() )
410
0
        {
411
0
            pPV->LogicToPagePos(aRect);
412
0
            aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
413
0
            aSet.Put( SvxSizeItem( SID_ATTR_SIZE,
414
0
                    Size( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() ) ) );
415
0
            bActionItem = true;
416
0
        }
417
0
    }
418
0
    if ( !bActionItem )
419
0
    {
420
0
        const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
421
0
        if ( rMarkList.GetMarkCount() != 0 ) // selected objects
422
0
        {
423
0
            tools::Rectangle aRect = pDrView->GetAllMarkedRect();
424
0
            pPV->LogicToPagePos(aRect);
425
0
            aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
426
0
            aSet.Put( SvxSizeItem( SID_ATTR_SIZE,
427
0
                    Size( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() ) ) );
428
0
        }
429
0
        else // mouse position
430
0
        {
431
0
            Point aPos = PixelToLogic(aCurMousePos);
432
0
            pPV->LogicToPagePos(aPos);
433
0
            aSet.Put( SfxPointItem( SID_ATTR_POSITION, aPos ) );
434
0
            aSet.Put( SvxSizeItem( SID_ATTR_SIZE, Size( 0, 0 ) ) );
435
0
        }
436
0
    }
437
438
0
    mrViewData.GetBindings().SetState(aSet);
439
0
}
440
441
bool ScGridWindow::DrawHasMarkedObj()
442
0
{
443
0
    ScDrawView* p = mrViewData.GetScDrawView();
444
0
    return p && p->GetMarkedObjectList().GetMarkCount() != 0;
445
0
}
446
447
void ScGridWindow::DrawMarkDropObj( SdrObject* pObj )
448
0
{
449
0
    ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
450
0
    if (pDrView)
451
0
        pDrView->MarkDropObj(pObj);
452
0
}
453
454
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */