Coverage Report

Created: 2026-02-14 09:37

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