Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/drawvie3.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 <sal/config.h>
21
22
#include <cstdlib>
23
24
#include <svx/svdograf.hxx>
25
#include <svx/svdoole2.hxx>
26
#include <svx/ImageMapInfo.hxx>
27
#include <sfx2/viewfrm.hxx>
28
#include <comphelper/lok.hxx>
29
#include <officecfg/Office/Common.hxx>
30
31
#include <strings.hrc>
32
#include <scresid.hxx>
33
#include <drawview.hxx>
34
#include <drwlayer.hxx>
35
#include "imapwrap.hxx"
36
#include <viewdata.hxx>
37
#include <document.hxx>
38
#include <userdat.hxx>
39
#include <tabvwsh.hxx>
40
#include <docsh.hxx>
41
42
ScDrawView::ScDrawView(
43
    OutputDevice* pOut,
44
    ScViewData& rData )
45
0
:   FmFormView(*rData.GetDocument().GetDrawLayer(), pOut),
46
0
    rViewData( rData ),
47
0
    pDev( pOut ),
48
0
    rDoc( rData.GetDocument() ),
49
0
    nTab( rData.CurrentTabForData() ),
50
0
    pDropMarkObj( nullptr ),
51
0
    bInConstruct( true )
52
0
{
53
0
    SetNegativeX(comphelper::LibreOfficeKit::isActive() && rDoc.IsLayoutRTL(nTab));
54
    // #i73602# Use default from the configuration
55
0
    SetBufferedOverlayAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_Calc::get());
56
57
    // #i74769#, #i75172# Use default from the configuration
58
0
    SetBufferedOutputAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::PaintBuffer_Calc::get());
59
60
0
    Construct();
61
0
}
62
63
// set anchor
64
65
void ScDrawView::SetPageAnchored()
66
0
{
67
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
68
0
    if( rMarkList.GetMarkCount() == 0 )
69
0
        return;
70
71
0
    const size_t nCount = rMarkList.GetMarkCount();
72
73
0
    BegUndo(ScResId(SCSTR_UNDO_PAGE_ANCHOR));
74
0
    for( size_t i=0; i<nCount; ++i )
75
0
    {
76
0
        SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
77
0
        AddUndo (std::make_unique<ScUndoAnchorData>( pObj, &rDoc, nTab ));
78
0
        ScDrawLayer::SetPageAnchored( *pObj );
79
0
    }
80
0
    EndUndo();
81
82
0
    rViewData.GetDocShell()->SetDrawModified();
83
84
    // Remove the anchor object.
85
0
    maHdlList.RemoveAllByKind(SdrHdlKind::Anchor);
86
0
    maHdlList.RemoveAllByKind(SdrHdlKind::Anchor_TR);
87
0
}
88
89
void ScDrawView::SetCellAnchored(bool bResizeWithCell)
90
0
{
91
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
92
0
    if( rMarkList.GetMarkCount() == 0 )
93
0
        return;
94
95
0
    const size_t nCount = rMarkList.GetMarkCount();
96
97
0
    BegUndo(ScResId(SCSTR_UNDO_CELL_ANCHOR));
98
0
    for( size_t i=0; i<nCount; ++i )
99
0
    {
100
0
        SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
101
0
        AddUndo (std::make_unique<ScUndoAnchorData>( pObj, &rDoc, nTab ));
102
0
        ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, nTab, bResizeWithCell);
103
0
    }
104
0
    EndUndo();
105
106
0
    rViewData.GetDocShell()->SetDrawModified();
107
108
    // Set the anchor object.
109
0
    AddCustomHdl();
110
0
}
111
112
ScAnchorType ScDrawView::GetAnchorType() const
113
0
{
114
0
    bool bPage = false;
115
0
    bool bCell = false;
116
0
    bool bCellResize = false;
117
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
118
0
    if( rMarkList.GetMarkCount() != 0 )
119
0
    {
120
0
        const size_t nCount = rMarkList.GetMarkCount();
121
0
        for( size_t i=0; i<nCount; ++i )
122
0
        {
123
0
            const SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
124
0
            const ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType( *pObj );
125
0
            if( aAnchorType == SCA_CELL )
126
0
                bCell =true;
127
0
            else if (aAnchorType == SCA_CELL_RESIZE)
128
0
                bCellResize = true;
129
0
            else
130
0
                bPage = true;
131
0
        }
132
0
    }
133
0
    if( bPage && !bCell && !bCellResize )
134
0
        return SCA_PAGE;
135
0
    if( !bPage && bCell && !bCellResize )
136
0
        return SCA_CELL;
137
0
    if( !bPage && !bCell && bCellResize )
138
0
        return SCA_CELL_RESIZE;
139
0
    return SCA_DONTKNOW;
140
0
}
141
142
namespace {
143
144
bool lcl_AreRectanglesApproxEqual(const tools::Rectangle& rRectA, const tools::Rectangle& rRectB)
145
0
{
146
    // Twips <-> Hmm conversions introduce +-1 differences although the rectangles should actually
147
    // be equal. Therefore test with == is not appropriate in some cases.
148
0
    if (std::abs(rRectA.Left() - rRectB.Left()) > 1)
149
0
        return false;
150
0
    if (std::abs(rRectA.Top() - rRectB.Top()) > 1)
151
0
        return false;
152
0
    if (std::abs(rRectA.Right() - rRectB.Right()) > 1)
153
0
        return false;
154
0
    if (std::abs(rRectA.Bottom() - rRectB.Bottom()) > 1)
155
0
        return false;
156
0
    return true;
157
0
}
158
159
/**
160
 * Updated the anchors of any non-note object that is cell anchored which
161
 * has been moved since the last anchors for its position was calculated.
162
 */
163
void adjustAnchoredPosition(const SdrHint& rHint, const ScDocument& rDoc, SCTAB nTab)
164
0
{
165
0
    if (rHint.GetKind() != SdrHintKind::ObjectChange && rHint.GetKind() != SdrHintKind::ObjectInserted)
166
0
        return;
167
168
0
    SdrObject* pObj = const_cast<SdrObject*>(rHint.GetObject());
169
0
    if (!pObj)
170
0
        return;
171
172
0
    ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pObj);
173
0
    if (!pAnchor)
174
0
        return;
175
176
0
    if (pAnchor->meType == ScDrawObjData::CellNote)
177
0
        return;
178
179
    // SetCellAnchoredFromPosition has to be called only if shape geometry has been changed, and not
180
    // if only shape visibility has been changed. It is not enough to test shape rect, because e.g. a
181
    // 180deg rotation changes only the logic rect (tdf#139583).
182
0
    ScDrawObjData& rNoRotatedAnchor = *ScDrawLayer::GetNonRotatedObjData(pObj, true /*bCreate*/);
183
0
    if (lcl_AreRectanglesApproxEqual(pAnchor->getShapeRect(), pObj->GetSnapRect())
184
0
        && lcl_AreRectanglesApproxEqual(rNoRotatedAnchor.getShapeRect(), pObj->GetLogicRect()))
185
0
        return;
186
187
0
    if (pAnchor->maStart.Tab() != nTab)
188
        // The object is not anchored on the current sheet.  Skip it.
189
        // TODO: In the future, we may want to adjust objects that are
190
        // anchored on all selected sheets.
191
0
        return;
192
193
0
    ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, pAnchor->maStart.Tab(), pAnchor->mbResizeWithCell);
194
0
}
195
196
}
197
198
void ScDrawView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
199
0
{
200
0
    if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
201
0
    {
202
0
        const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint );
203
0
        adjustAnchoredPosition(*pSdrHint, rDoc, nTab);
204
0
        FmFormView::Notify( rBC,rHint );
205
0
    }
206
0
    else if (rHint.GetId() == SfxHintId::ScTabDeleted) // Sheet has been deleted
207
0
    {
208
0
        auto pDeletedHint = static_cast<const ScTabDeletedHint*>(&rHint);
209
0
        SCTAB nDelTab = pDeletedHint->GetTab();
210
0
        if (ValidTab(nDelTab))
211
0
        {
212
            // used to be: HidePagePgNum(nDelTab) - hide only if the deleted sheet is shown here
213
0
            if ( nDelTab == nTab )
214
0
                HideSdrPage();
215
0
        }
216
0
    }
217
0
    else if (rHint.GetId() == SfxHintId::ScTabSizeChanged) // Size has been changed
218
0
    {
219
0
        auto pChangedHint = static_cast<const ScTabSizeChangedHint*>(&rHint);
220
0
        if ( nTab == pChangedHint->GetTab() )
221
0
            UpdateWorkArea();
222
0
    }
223
0
    else
224
0
        FmFormView::Notify( rBC,rHint );
225
0
}
226
227
void ScDrawView::UpdateIMap( SdrObject* pObj )
228
0
{
229
0
    if ( rViewData.GetViewShell()->GetViewFrame().HasChildWindow( ScIMapChildWindowId() ) &&
230
0
         pObj && ( dynamic_cast<const SdrGrafObj*>( pObj) != nullptr || dynamic_cast<const SdrOle2Obj*>( pObj) != nullptr ) )
231
0
        return;
232
233
0
    Graphic     aGraphic;
234
0
    TargetList  aTargetList;
235
0
    SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo( pObj );
236
0
    const ImageMap* pImageMap = nullptr;
237
0
    if ( pIMapInfo )
238
0
        pImageMap = &pIMapInfo->GetImageMap();
239
240
    // handle target list
241
0
    SfxViewFrame::GetTargetList( aTargetList );
242
243
    // handle graphics from object
244
0
    if ( auto pGrafObj = dynamic_cast<SdrGrafObj*>( pObj) )
245
0
        aGraphic = pGrafObj->GetGraphic();
246
0
    else
247
0
    {
248
0
        const Graphic* pGraphic = static_cast<const SdrOle2Obj*>(pObj)->GetGraphic();
249
0
        if ( pGraphic )
250
0
            aGraphic = *pGraphic;
251
0
    }
252
253
0
    ScIMapDlgSet( aGraphic, pImageMap, &aTargetList, pObj );    // from imapwrap
254
0
}
255
256
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */