Bug Summary

File:home/maarten/src/libreoffice/core/sc/source/ui/view/drawview.cxx
Warning:line 950, column 41
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

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