1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/embed/XEmbeddedObject.hpp>
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/UnitConversion.hxx>
45 #include <osl/diagnose.h>
47 #include <drawview.hxx>
49 #include <viewdata.hxx>
50 #include <document.hxx>
51 #include <drawutil.hxx>
52 #include <globstr.hrc>
53 #include <scresid.hxx>
54 #include <tabvwsh.hxx>
57 #include <drwlayer.hxx>
59 #include <viewuno.hxx>
60 #include <userdat.hxx>
62 #include <undocell.hxx>
63 #include <gridwin.hxx>
67 using namespace com::sun::star
;
69 #define SC_HANDLESIZE_BIG 9
71 void ScDrawView::Construct()
73 EnableExtendedKeyInputDispatcher(false);
74 EnableExtendedMouseEventDispatcher(false);
76 SetFrameDragSingles();
78 SetMinMoveDistancePixel( 2 );
79 SetHitTolerancePixel( 2 );
83 SCTAB nViewTab
= pViewData
->GetTabNo();
84 ShowSdrPage(GetModel().GetPage(nViewTab
));
86 bool bEx
= pViewData
->GetViewShell()->IsDrawSelMode();
87 bool bProt
= rDoc
.IsTabProtected( nViewTab
) ||
88 pViewData
->GetSfxDocShell()->IsReadOnly();
91 SdrLayerAdmin
& rAdmin
= GetModel().GetLayerAdmin();
92 pLayer
= rAdmin
.GetLayerPerID(SC_LAYER_BACK
);
94 SetLayerLocked( pLayer
->GetName(), bProt
|| !bEx
);
95 pLayer
= rAdmin
.GetLayerPerID(SC_LAYER_INTERN
);
97 SetLayerLocked( pLayer
->GetName() );
98 pLayer
= rAdmin
.GetLayerPerID(SC_LAYER_FRONT
);
101 SetLayerLocked( pLayer
->GetName(), bProt
);
102 SetActiveLayer( pLayer
->GetName() ); // set active layer to FRONT
104 pLayer
= rAdmin
.GetLayerPerID(SC_LAYER_CONTROLS
);
106 SetLayerLocked( pLayer
->GetName(), bProt
);
107 pLayer
= rAdmin
.GetLayerPerID(SC_LAYER_HIDDEN
);
110 SetLayerLocked( pLayer
->GetName(), bProt
);
111 SetLayerVisible( pLayer
->GetName(), false);
118 ShowSdrPage(GetModel().GetPage(nTab
));
121 UpdateUserViewOptions();
125 bInConstruct
= false;
128 void ScDrawView::ImplClearCalcDropMarker()
133 ScDrawView::~ScDrawView()
135 ImplClearCalcDropMarker();
138 void ScDrawView::AddCustomHdl()
140 const SdrMarkList
&rMarkList
= GetMarkedObjectList();
141 const size_t nCount
= rMarkList
.GetMarkCount();
142 for(size_t nPos
=0; nPos
<nCount
; ++nPos
)
144 SdrObject
* pObj
= rMarkList
.GetMark(nPos
)->GetMarkedSdrObj();
145 if (ScDrawObjData
*pAnchor
= ScDrawLayer::GetObjDataTab(pObj
, nTab
))
147 if (ScTabView
* pView
= pViewData
->GetView())
148 pView
->CreateAnchorHandles(maHdlList
, pAnchor
->maStart
);
153 void ScDrawView::InvalidateAttribs()
155 if (!pViewData
) return;
156 SfxBindings
& rBindings
= pViewData
->GetBindings();
158 // true status values:
159 rBindings
.InvalidateAll( true );
162 void ScDrawView::InvalidateDrawTextAttrs()
164 if (!pViewData
) return;
165 SfxBindings
& rBindings
= pViewData
->GetBindings();
167 // cjk/ctl font items have no configured slots,
168 // need no invalidate
170 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
171 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
172 rBindings
.Invalidate( SID_ATTR_CHAR_WEIGHT
);
173 rBindings
.Invalidate( SID_ATTR_CHAR_POSTURE
);
174 rBindings
.Invalidate( SID_ATTR_CHAR_UNDERLINE
);
175 rBindings
.Invalidate( SID_ULINE_VAL_NONE
);
176 rBindings
.Invalidate( SID_ULINE_VAL_SINGLE
);
177 rBindings
.Invalidate( SID_ULINE_VAL_DOUBLE
);
178 rBindings
.Invalidate( SID_ULINE_VAL_DOTTED
);
179 rBindings
.Invalidate( SID_ATTR_CHAR_OVERLINE
);
180 rBindings
.Invalidate( SID_ATTR_CHAR_COLOR
);
181 rBindings
.Invalidate( SID_ATTR_CHAR_BACK_COLOR
);
182 rBindings
.Invalidate( SID_ATTR_PARA_ADJUST_LEFT
);
183 rBindings
.Invalidate( SID_ATTR_PARA_ADJUST_RIGHT
);
184 rBindings
.Invalidate( SID_ATTR_PARA_ADJUST_BLOCK
);
185 rBindings
.Invalidate( SID_ATTR_PARA_ADJUST_CENTER
);
186 rBindings
.Invalidate( SID_ALIGNLEFT
);
187 rBindings
.Invalidate( SID_ALIGNCENTERHOR
);
188 rBindings
.Invalidate( SID_ALIGNRIGHT
);
189 rBindings
.Invalidate( SID_ALIGNBLOCK
);
190 rBindings
.Invalidate( SID_ATTR_PARA_LINESPACE_10
);
191 rBindings
.Invalidate( SID_ATTR_PARA_LINESPACE_15
);
192 rBindings
.Invalidate( SID_ATTR_PARA_LINESPACE_20
);
193 rBindings
.Invalidate( SID_SET_SUPER_SCRIPT
);
194 rBindings
.Invalidate( SID_SET_SUB_SCRIPT
);
195 rBindings
.Invalidate( SID_ATTR_CHAR_KERNING
);
196 rBindings
.Invalidate( SID_ATTR_CHAR_STRIKEOUT
);
197 rBindings
.Invalidate( SID_ATTR_CHAR_SHADOWED
);
198 rBindings
.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT
);
199 rBindings
.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM
);
200 rBindings
.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT
);
201 rBindings
.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT
);
202 rBindings
.Invalidate( SID_TABLE_VERT_NONE
);
203 rBindings
.Invalidate( SID_TABLE_VERT_CENTER
);
204 rBindings
.Invalidate( SID_TABLE_VERT_BOTTOM
);
205 // pseudo slots for Format menu
206 rBindings
.Invalidate( SID_ALIGN_ANY_LEFT
);
207 rBindings
.Invalidate( SID_ALIGN_ANY_HCENTER
);
208 rBindings
.Invalidate( SID_ALIGN_ANY_RIGHT
);
209 rBindings
.Invalidate( SID_ALIGN_ANY_JUSTIFIED
);
212 void ScDrawView::SetMarkedToLayer( SdrLayerID nLayerNo
)
214 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
215 if (rMarkList
.GetMarkCount() == 0)
218 // #i11702# use SdrUndoObjectLayerChange for undo
219 // STR_UNDO_SELATTR is "Attributes" - should use a different text later
220 BegUndo( ScResId( STR_UNDO_SELATTR
) );
222 const SdrMarkList
& rMark
= GetMarkedObjectList();
223 const size_t nCount
= rMark
.GetMarkCount();
224 for (size_t i
=0; i
<nCount
; ++i
)
226 SdrObject
* pObj
= rMark
.GetMark(i
)->GetMarkedSdrObj();
228 if ( dynamic_cast<const SdrUnoObj
*>( pObj
) == nullptr && (pObj
->GetLayer() != SC_LAYER_INTERN
) )
230 AddUndo( std::make_unique
<SdrUndoObjectLayerChange
>( *pObj
, pObj
->GetLayer(), nLayerNo
) );
231 pObj
->SetLayer( nLayerNo
);
237 // repaint is done in SetLayer
239 pViewData
->GetDocShell()->SetDrawModified();
241 // check mark list now instead of later in a timer
243 MarkListHasChanged();
246 bool ScDrawView::HasMarkedControl() const
248 SdrObjListIter
aIter( GetMarkedObjectList() );
249 for( SdrObject
* pObj
= aIter
.Next(); pObj
; pObj
= aIter
.Next() )
250 if( dynamic_cast<const SdrUnoObj
*>( pObj
) != nullptr )
255 bool ScDrawView::HasMarkedInternal() const
257 // internal objects should not be inside a group, but who knows...
258 SdrObjListIter
aIter( GetMarkedObjectList() );
259 for( SdrObject
* pObj
= aIter
.Next(); pObj
; pObj
= aIter
.Next() )
260 if( pObj
->GetLayer() == SC_LAYER_INTERN
)
265 void ScDrawView::UpdateWorkArea()
267 SdrPage
* pPage
= GetModel().GetPage(static_cast<sal_uInt16
>(nTab
));
270 Size
aPageSize( pPage
->GetSize() );
271 tools::Rectangle
aNewArea( Point(), aPageSize
);
272 if ( aPageSize
.Width() < 0 )
274 // RTL: from max.negative (left) to zero (right)
275 aNewArea
.SetRight( 0 );
276 aNewArea
.SetLeft( aPageSize
.Width() + 1 );
278 SetWorkArea( aNewArea
);
282 OSL_FAIL("Page not found");
286 void ScDrawView::DoCut()
289 BegUndo( ScResId( STR_UNDO_CUT
) );
290 DeleteMarked(); // In this View - not affected by 505f change
294 void ScDrawView::GetScale( Fraction
& rFractX
, Fraction
& rFractY
) const
300 void ScDrawView::RecalcScale()
304 Fraction
aZoomX(1,1);
305 Fraction
aZoomY(1,1);
309 nTab
= pViewData
->GetTabNo();
310 nPPTX
= pViewData
->GetPPTX();
311 nPPTY
= pViewData
->GetPPTY();
312 aZoomX
= pViewData
->GetZoomX();
313 aZoomY
= pViewData
->GetZoomY();
317 Point aLogic
= pDev
->LogicToPixel(Point(1000,1000), MapMode(MapUnit::MapTwip
));
318 nPPTX
= aLogic
.X() / 1000.0;
319 nPPTY
= aLogic
.Y() / 1000.0;
320 //! Zoom, handed over ???
325 rDoc
.GetTableArea( nTab
, nEndCol
, nEndRow
);
331 ScDrawUtil::CalcScale(
332 rDoc
, nTab
, 0, 0, nEndCol
, nEndRow
, pDev
, aZoomX
, aZoomY
, nPPTX
, nPPTY
,
335 // clear all evtl existing GridOffset vectors
336 resetGridOffsetsForAllSdrPageViews();
338 SdrPageView
* pPV
= GetSdrPageView();
339 if ( !(pViewData
&& pPV
) )
342 if ( SdrPage
* pPage
= pPV
->GetPage() )
344 for (const rtl::Reference
<SdrObject
>& pObj
: *pPage
)
345 // Align objects to nearest grid position
346 SyncForGrid( pObj
.get() );
350 void ScDrawView::DoConnect(SdrOle2Obj
* pOleObj
)
353 pViewData
->GetViewShell()->ConnectObject( pOleObj
);
356 void ScDrawView::MarkListHasChanged()
358 FmFormView::MarkListHasChanged();
360 ScTabViewShell
* pViewSh
= pViewData
->GetViewShell();
361 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
362 ScModule
* pScMod
= ScModule::get();
364 // #i110829# remove the cell selection only if drawing objects are selected
365 if ( !bInConstruct
&& rMarkList
.GetMarkCount() )
367 pViewSh
->Unmark(); // remove cell selection
369 // end cell edit mode if drawing objects are selected
370 pScMod
->InputEnterHandler();
375 bool bUnoRefDialog
= pScMod
->IsRefDialogOpen() && pScMod
->GetCurRefDlgId() == WID_SIMPLE_REF
;
377 ScClient
* pClient
= static_cast<ScClient
*>( pViewSh
->GetIPClient() );
378 if ( pClient
&& pClient
->IsObjectInPlaceActive() && !bUnoRefDialog
)
380 // do not display the handles for ViewShell::Activate from the Reset2Open
381 pClient
->DeactivateObject();
382 // replacing image ole graphics is now done in ScClient::UIActivate
385 // Select Ole object?
387 SdrOle2Obj
* pOle2Obj
= nullptr;
388 SdrGrafObj
* pGrafObj
= nullptr;
390 const size_t nMarkCount
= rMarkList
.GetMarkCount();
392 if ( nMarkCount
== 0 && !pViewData
->GetViewShell()->IsDrawSelMode() && !bInConstruct
)
394 // relock layers that may have been unlocked before
395 LockBackgroundLayer(true);
399 bool bSubShellSet
= false;
402 SdrObject
* pObj
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
403 if (pObj
->GetObjIdentifier() == SdrObjKind::OLE2
)
405 pOle2Obj
= static_cast<SdrOle2Obj
*>(pObj
);
406 if (!ScDocument::IsChart(pObj
) )
407 pViewSh
->SetOleObjectShell(true);
409 pViewSh
->SetChartShell(true);
412 else if (pObj
->GetObjIdentifier() == SdrObjKind::Graphic
)
414 pGrafObj
= static_cast<SdrGrafObj
*>(pObj
);
415 pViewSh
->SetGraphicShell(true);
418 else if (pObj
->GetObjIdentifier() == SdrObjKind::Media
)
420 pViewSh
->SetMediaShell(true);
423 else if (pObj
->GetObjIdentifier() != SdrObjKind::Text
// prevent switching to the drawing shell
424 || !pViewSh
->IsDrawTextShell()) // when creating a text object @#70206#
426 pViewSh
->SetDrawShell(true);
430 if ( nMarkCount
&& !bSubShellSet
)
432 bool bOnlyControls
= true;
433 bool bOnlyGraf
= true;
434 for (size_t i
=0; i
<nMarkCount
; ++i
)
436 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
437 if ( auto pObjGroup
= dynamic_cast<const SdrObjGroup
*>( pObj
) )
439 const SdrObjList
*pLst
= pObjGroup
->GetSubList();
440 const size_t nListCount
= pLst
->GetObjCount();
441 if ( nListCount
== 0 )
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;
448 for ( size_t j
= 0; j
< nListCount
; ++j
)
450 SdrObject
*pSubObj
= pLst
->GetObj( j
);
453 if (dynamic_cast<const SdrUnoObj
*>( pSubObj
) == nullptr)
454 bOnlyControls
= false;
455 if (pSubObj
->GetObjIdentifier() != SdrObjKind::Graphic
)
458 if ( !bOnlyControls
&& !bOnlyGraf
) break;
463 if (dynamic_cast<const SdrUnoObj
*>( pObj
) == nullptr)
464 bOnlyControls
= false;
465 if (pObj
->GetObjIdentifier() != SdrObjKind::Graphic
)
469 if ( !bOnlyControls
&& !bOnlyGraf
) break;
474 pViewSh
->SetDrawFormShell(true); // now UNO controls
478 pViewSh
->SetGraphicShell(true);
480 else if(nMarkCount
>1)
482 pViewSh
->SetDrawShell(true);
488 SfxViewFrame
& rViewFrame
= pViewSh
->GetViewFrame();
489 bool bOle
= pViewSh
->GetViewFrame().GetFrame().IsInPlace();
490 uno::Sequence
< embed::VerbDescriptor
> aVerbs
;
491 if ( pOle2Obj
&& !bOle
)
493 const uno::Reference
< embed::XEmbeddedObject
>& xObj
= pOle2Obj
->GetObjRef();
494 OSL_ENSURE( xObj
.is(), "SdrOle2Obj without ObjRef" );
496 aVerbs
= xObj
->getSupportedVerbs();
498 pViewSh
->SetVerbs( aVerbs
);
503 UpdateIMap( pOle2Obj
);
505 UpdateIMap( pGrafObj
);
507 InvalidateAttribs(); // after the image map editor update
508 InvalidateDrawTextAttrs();
510 for(sal_uInt32
a(0); a
< PaintWindowCount(); a
++)
512 SdrPaintWindow
* pPaintWindow
= GetPaintWindow(a
);
513 OutputDevice
& rOutDev
= pPaintWindow
->GetOutputDevice();
515 if(OUTDEV_WINDOW
== rOutDev
.GetOutDevType())
517 rOutDev
.GetOwnerWindow()->PaintImmediately();
521 // uno object for view returns drawing objects as selection,
522 // so it must notify its SelectionChangeListeners
524 SfxFrame
& rFrame
= rViewFrame
.GetFrame();
525 uno::Reference
<frame::XController
> xController
= rFrame
.GetController();
526 if (xController
.is())
528 ScTabViewObj
* pImp
= dynamic_cast<ScTabViewObj
*>( xController
.get() );
530 pImp
->SelectionChanged();
533 // update selection transfer object
535 pViewSh
->CheckSelectionTransfer();
539 bool ScDrawView::SdrBeginTextEdit(
544 SdrOutliner
* pGivenOutliner
,
545 OutlinerView
* pGivenOutlinerView
,
546 bool bDontDeleteOutliner
,
550 const bool bRet
= FmFormView::SdrBeginTextEdit(
551 pObj
, pPV
, pWinL
, bIsNewObj
,
552 pGivenOutliner
, pGivenOutlinerView
, bDontDeleteOutliner
,
553 bOnlyOneView
, bGrabFocus
);
555 ScTabViewShell
* pViewSh
= pViewData
->GetViewShell();
557 if (comphelper::LibreOfficeKit::isActive())
559 if (OutlinerView
* pView
= GetTextEditOutlinerView())
561 tools::Rectangle aRectangle
= pView
->GetOutputArea();
562 if (pWinL
&& pWinL
->GetMapMode().GetMapUnit() == MapUnit::Map100thMM
)
564 aRectangle
= o3tl::convert(aRectangle
, o3tl::Length::mm100
, o3tl::Length::twip
);
566 OString sRectangle
= aRectangle
.toString();
567 SfxLokHelper::notifyOtherViews(pViewSh
, LOK_CALLBACK_VIEW_LOCK
, "rectangle", sRectangle
);
571 SfxFrame
& rFrame
= pViewSh
->GetViewFrame().GetFrame();
572 uno::Reference
< frame::XController
> xController
= rFrame
.GetController();
573 if (xController
.is())
575 ScTabViewObj
* pImp
= dynamic_cast<ScTabViewObj
*>( xController
.get() );
577 pImp
->SelectionChanged();
583 SdrEndTextEditKind
ScDrawView::SdrEndTextEdit( bool bDontDeleteReally
)
585 const SdrEndTextEditKind eRet
= FmFormView::SdrEndTextEdit( bDontDeleteReally
);
587 ScTabViewShell
* pViewSh
= pViewData
->GetViewShell();
589 if (comphelper::LibreOfficeKit::isActive())
590 SfxLokHelper::notifyOtherViews(pViewSh
, LOK_CALLBACK_VIEW_LOCK
, "rectangle", "EMPTY"_ostr
);
592 SfxFrame
& rFrame
= pViewSh
->GetViewFrame().GetFrame();
593 uno::Reference
< frame::XController
> xController
= rFrame
.GetController();
594 if (xController
.is())
596 ScTabViewObj
* pImp
= dynamic_cast<ScTabViewObj
*>( xController
.get() );
598 pImp
->SelectionChanged();
604 void ScDrawView::ModelHasChanged()
606 SdrObject
* pEditObj
= GetTextEditObject();
607 if ( pEditObj
&& !pEditObj
->IsInserted() && pViewData
)
609 // SdrObjEditView::ModelHasChanged will end text edit in this case,
610 // so make sure the EditEngine's undo manager is no longer used.
611 pViewData
->GetViewShell()->SetDrawTextUndo(nullptr);
612 SetCreateMode(); // don't leave FuText in a funny state
615 FmFormView::ModelHasChanged();
618 void ScDrawView::UpdateUserViewOptions()
623 const ScViewOptions
& rOpt
= pViewData
->GetOptions();
624 const ScGridOptions
& rGrid
= rOpt
.GetGridOptions();
626 SetDragStripes( rOpt
.GetOption( VOPT_HELPLINES
) );
627 SetMarkHdlSizePixel( SC_HANDLESIZE_BIG
);
629 SetGridVisible( rGrid
.GetGridVisible() );
630 SetSnapEnabled( rGrid
.GetUseGridSnap() );
631 SetGridSnap( rGrid
.GetUseGridSnap() );
633 Fraction
aFractX( rGrid
.GetFieldDrawX(), rGrid
.GetFieldDivisionX() + 1 );
634 Fraction
aFractY( rGrid
.GetFieldDrawY(), rGrid
.GetFieldDivisionY() + 1 );
635 SetSnapGridWidth( aFractX
, aFractY
);
637 SetGridCoarse( Size( rGrid
.GetFieldDrawX(), rGrid
.GetFieldDrawY() ) );
638 SetGridFine( Size( rGrid
.GetFieldDrawX() / (rGrid
.GetFieldDivisionX() + 1),
639 rGrid
.GetFieldDrawY() / (rGrid
.GetFieldDivisionY() + 1) ) );
642 SdrObject
* ScDrawView::GetObjectByName(std::u16string_view rName
)
644 ScDocShell
* pShell
= rDoc
.GetDocumentShell();
647 SdrModel
& rDrawLayer
= GetModel();
648 sal_uInt16 nTabCount
= rDoc
.GetTableCount();
649 for (sal_uInt16 i
=0; i
<nTabCount
; i
++)
651 SdrPage
* pPage
= rDrawLayer
.GetPage(i
);
652 DBG_ASSERT(pPage
,"Page ?");
655 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepNoGroups
);
656 SdrObject
* pObject
= aIter
.Next();
659 if ( ScDrawLayer::GetVisibleName( pObject
) == rName
)
663 pObject
= aIter
.Next();
671 //realize multi-selection of objects
673 void ScDrawView::SelectCurrentViewObject( std::u16string_view rName
)
675 sal_uInt16 nObjectTab
= 0;
676 SdrObject
* pFound
= nullptr;
677 ScDocShell
* pShell
= rDoc
.GetDocumentShell();
680 SdrModel
& rDrawLayer
= GetModel();
681 sal_uInt16 nTabCount
= rDoc
.GetTableCount();
682 for (sal_uInt16 i
=0; i
<nTabCount
&& !pFound
; i
++)
684 SdrPage
* pPage
= rDrawLayer
.GetPage(i
);
685 DBG_ASSERT(pPage
,"Page ?");
688 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepWithGroups
);
689 SdrObject
* pObject
= aIter
.Next();
690 while (pObject
&& !pFound
)
692 if ( ScDrawLayer::GetVisibleName( pObject
) == rName
)
697 pObject
= aIter
.Next();
705 ScTabView
* pView
= pViewData
->GetView();
706 if ( nObjectTab
!= nTab
) // switch sheet
707 pView
->SetTabNo( nObjectTab
);
708 DBG_ASSERT( nTab
== nObjectTab
, "Switching sheets did not work" );
709 pView
->ScrollToObject( pFound
);
710 if ( pFound
->GetLayer() == SC_LAYER_BACK
&&
711 !pViewData
->GetViewShell()->IsDrawSelMode() &&
712 !rDoc
.IsTabProtected( nTab
) &&
713 !pViewData
->GetSfxDocShell()->IsReadOnly() )
715 SdrLayer
* pLayer
= GetModel().GetLayerAdmin().GetLayerPerID(SC_LAYER_BACK
);
717 SetLayerLocked( pLayer
->GetName(), false );
719 SdrPageView
* pPV
= GetSdrPageView();
720 const bool bUnMark
= IsObjMarked(pFound
);
721 MarkObj( pFound
, pPV
, bUnMark
);
724 bool ScDrawView::SelectObject( std::u16string_view rName
)
728 SCTAB nObjectTab
= 0;
729 SdrObject
* pFound
= nullptr;
731 ScDocShell
* pShell
= rDoc
.GetDocumentShell();
734 SdrModel
& rDrawLayer
= GetModel();
735 SCTAB nTabCount
= rDoc
.GetTableCount();
736 for (SCTAB i
=0; i
<nTabCount
&& !pFound
; i
++)
738 SdrPage
* pPage
= rDrawLayer
.GetPage(static_cast<sal_uInt16
>(i
));
739 OSL_ENSURE(pPage
,"Page ?");
742 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepWithGroups
);
743 SdrObject
* pObject
= aIter
.Next();
744 while (pObject
&& !pFound
)
746 if ( ScDrawLayer::GetVisibleName( pObject
) == rName
)
751 pObject
= aIter
.Next();
759 ScTabView
* pView
= pViewData
->GetView();
760 if ( nObjectTab
!= nTab
) // switch sheet
761 pView
->SetTabNo( nObjectTab
);
763 OSL_ENSURE( nTab
== nObjectTab
, "Switching sheets did not work" );
765 pView
->ScrollToObject( pFound
);
767 /* To select an object on the background layer, the layer has to
768 be unlocked even if exclusive drawing selection mode is not active
769 (this is reversed in MarkListHasChanged when nothing is selected) */
770 if ( pFound
->GetLayer() == SC_LAYER_BACK
&&
771 !pViewData
->GetViewShell()->IsDrawSelMode() &&
772 !rDoc
.IsTabProtected( nTab
) &&
773 !pViewData
->GetSfxDocShell()->IsReadOnly() )
775 LockBackgroundLayer(false);
778 SdrPageView
* pPV
= GetSdrPageView();
779 MarkObj( pFound
, pPV
);
782 return ( pFound
!= nullptr );
785 //If object is marked , return true , else return false .
786 bool ScDrawView::GetObjectIsMarked( const SdrObject
* pObject
)
788 bool bisMarked
= false;
791 bisMarked
= IsObjMarked(pObject
);
796 bool ScDrawView::InsertObjectSafe(SdrObject
* pObj
, SdrPageView
& rPV
)
798 SdrInsertFlags nOptions
=SdrInsertFlags::NONE
;
799 // Do not change marks when the ole object is active
800 // (for Drop from ole object would otherwise be deactivated in the middle of ExecuteDrag!)
804 SfxInPlaceClient
* pClient
= pViewData
->GetViewShell()->GetIPClient();
805 if ( pClient
&& pClient
->IsObjectInPlaceActive() )
806 nOptions
|= SdrInsertFlags::DONTMARK
;
809 return InsertObjectAtView(pObj
, rPV
, nOptions
);
812 SdrObject
* ScDrawView::GetMarkedNoteCaption( ScDrawObjData
** ppCaptData
)
814 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
815 if( pViewData
&& (rMarkList
.GetMarkCount() == 1) )
817 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
818 if( ScDrawObjData
* pCaptData
= ScDrawLayer::GetNoteCaptionData( pObj
, pViewData
->GetTabNo() ) )
820 if( ppCaptData
) *ppCaptData
= pCaptData
;
827 void ScDrawView::LockCalcLayer( SdrLayerID nLayer
, bool bLock
)
829 SdrLayer
* pLockLayer
= GetModel().GetLayerAdmin().GetLayerPerID( nLayer
);
830 if( pLockLayer
&& (IsLayerLocked( pLockLayer
->GetName() ) != bLock
) )
831 SetLayerLocked( pLockLayer
->GetName(), bLock
);
834 void ScDrawView::MakeVisible( const tools::Rectangle
& rRect
, vcl::Window
& rWin
)
836 //! Evaluate rWin properly
837 //! change zoom if necessary
839 if ( pViewData
&& pViewData
->GetActiveWin() == &rWin
)
840 pViewData
->GetView()->MakeVisible( rRect
);
843 SfxViewShell
* ScDrawView::GetSfxViewShell() const
845 return pViewData
->GetViewShell();
848 void ScDrawView::DeleteMarked()
850 // try to delete a note caption object with its cell note in the Calc document
851 ScDrawObjData
* pCaptData
= nullptr;
852 if( SdrObject
* pCaptObj
= GetMarkedNoteCaption( &pCaptData
) )
854 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
855 ScDocShell
* pDocShell
= pViewData
? pViewData
->GetDocShell() : nullptr;
856 SfxUndoManager
* pUndoMgr
= pDocShell
? pDocShell
->GetUndoManager() : nullptr;
857 bool bUndo
= pDrawLayer
&& pDocShell
&& pUndoMgr
&& rDoc
.IsUndoEnabled();
859 // remove the cell note from document, we are its owner now
860 std::unique_ptr
<ScPostIt
> pNote
= rDoc
.ReleaseNote( pCaptData
->maStart
);
861 OSL_ENSURE( pNote
, "ScDrawView::DeleteMarked - cell note missing in document" );
864 // rescue note data for undo (with pointer to caption object)
865 ScNoteData aNoteData
= pNote
->GetNoteData();
866 OSL_ENSURE( aNoteData
.mxCaption
.get() == pCaptObj
, "ScDrawView::DeleteMarked - caption object does not match" );
867 // collect the drawing undo action created while deleting the note
869 pDrawLayer
->BeginCalcUndo(false);
870 // delete the note (already removed from document above)
872 // add the undo action for the note
874 pUndoMgr
->AddUndoAction( std::make_unique
<ScUndoReplaceNote
>( *pDocShell
, pCaptData
->maStart
, aNoteData
, false, pDrawLayer
->GetCalcUndo() ) );
875 // repaint the cell to get rid of the note marker
877 pDocShell
->PostPaintCell( pCaptData
->maStart
);
878 // done, return now to skip call of FmFormView::DeleteMarked()
883 FmFormView::DeleteMarked();
886 SdrEndTextEditKind
ScDrawView::ScEndTextEdit()
888 bool bIsTextEdit
= IsTextEdit();
889 SdrEndTextEditKind eKind
= SdrEndTextEdit();
892 pViewData
->GetViewShell()->SetDrawTextUndo(nullptr); // the "normal" undo manager
897 void ScDrawView::MarkDropObj( SdrObject
* pObj
)
899 if ( pDropMarkObj
!= pObj
)
902 ImplClearCalcDropMarker();
906 pDropMarker
.reset( new SdrDropMarkerOverlay(*this, *pDropMarkObj
) );
911 // In order to counteract the effects of rounding due to the nature of how the
912 // grid positions are calculated and drawn we calculate the offset needed at the
913 // current zoom to be applied to an SrdObject when it is drawn in order to make
914 // sure that it's position relative to the nearest cell anchor doesn't change.
915 // Of course not all shape(s)/control(s) are cell anchored, if the
916 // object doesn't have a cell anchor we synthesise a temporary anchor.
917 void ScDrawView::SyncForGrid( SdrObject
* pObj
)
919 // process members of a group shape separately
920 if ( auto pObjGroup
= dynamic_cast<const SdrObjGroup
*>( pObj
) )
922 SdrObjList
*pLst
= pObjGroup
->GetSubList();
923 for (const rtl::Reference
<SdrObject
>& pChild
: *pLst
)
924 SyncForGrid( pChild
.get() );
927 ScSplitPos eWhich
= pViewData
->GetActivePart();
928 ScGridWindow
* pGridWin
= pViewData
->GetActiveWin();
929 ScDrawObjData
* pData
= ScDrawLayer::GetObjData( pObj
);
934 if( pData
&& pData
->maStart
.IsValid())
936 aOldStt
= pData
->maStart
;
940 // Page anchored object so...
941 // synthesise an anchor ( but don't attach it to
942 // the object as we want to maintain page anchoring )
943 ScDrawObjData aAnchor
;
944 const tools::Rectangle
aObjRect(pObj
->GetLogicRect());
945 ScDrawLayer::GetCellAnchorFromPosition(
950 aOldStt
= aAnchor
.maStart
;
952 MapMode aDrawMode
= pGridWin
->GetDrawMapMode();
953 // find pos anchor position
954 Point
aOldPos( rDoc
.GetColOffset( aOldStt
.Col(), aOldStt
.Tab() ), rDoc
.GetRowOffset( aOldStt
.Row(), aOldStt
.Tab() ) );
955 aOldPos
= convertTwipToMm100(aOldPos
);
956 // find position of same point on the screen ( e.g. grid )
957 Point aCurPos
= pViewData
->GetScrPos( aOldStt
.Col(), aOldStt
.Row(), eWhich
, true );
958 Point aCurPosHmm
= pGridWin
->PixelToLogic(aCurPos
, aDrawMode
);
959 Point aGridOff
= aCurPosHmm
- aOldPos
;
960 // fdo#63878 Fix the X position for RTL Sheet
961 if( rDoc
.IsNegativePage( GetTab() ) && !comphelper::LibreOfficeKit::isActive() )
962 aGridOff
.setX( aCurPosHmm
.getX() + aOldPos
.getX() );
965 void ScDrawView::resetGridOffsetsForAllSdrPageViews()
967 SdrPageView
* pPageView(GetSdrPageView());
969 if(nullptr == pPageView
)
972 for(sal_uInt32
a(0); a
< pPageView
->PageWindowCount(); a
++)
974 SdrPageWindow
* pPageWindow(pPageView
->GetPageWindow(a
));
975 assert(pPageWindow
&& "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
977 if(nullptr != pPageWindow
)
979 sdr::contact::ObjectContact
& rObjectContact(pPageWindow
->GetObjectContact());
981 if(rObjectContact
.supportsGridOffsets())
983 rObjectContact
.resetAllGridOffsets();
989 bool ScDrawView::calculateGridOffsetForSdrObject(
990 SdrObject
& rSdrObject
,
991 basegfx::B2DVector
& rTarget
) const
993 if (comphelper::LibreOfficeKit::isActive() &&
994 !comphelper::LibreOfficeKit::isCompatFlagSet(
995 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
998 ScGridWindow
* pGridWin(pViewData
->GetActiveWin());
1000 if(nullptr == pGridWin
)
1005 ScDrawObjData
* pData(ScDrawLayer::GetObjData(&rSdrObject
));
1008 if(nullptr != pData
&& pData
->maStart
.IsValid())
1010 aOldStt
= pData
->maStart
;
1014 // Page anchored object so...
1015 // synthesise an anchor ( but don't attach it to
1016 // the object as we want to maintain page anchoring )
1017 ScDrawObjData aAnchor
;
1018 const tools::Rectangle
aObjRect(rSdrObject
.GetLogicRect());
1019 ScDrawLayer::GetCellAnchorFromPosition(
1024 aOldStt
= aAnchor
.maStart
;
1027 MapMode aDrawMode
= pGridWin
->GetDrawMapMode();
1029 // find pos anchor position
1030 Point
aOldPos(rDoc
.GetColOffset(aOldStt
.Col(), aOldStt
.Tab()), rDoc
.GetRowOffset(aOldStt
.Row(), aOldStt
.Tab()));
1031 aOldPos
= convertTwipToMm100(aOldPos
);
1033 // find position of same point on the screen ( e.g. grid )
1034 ScSplitPos
eWhich(pViewData
->GetActivePart());
1035 Point
aCurPos(pViewData
->GetScrPos(aOldStt
.Col(), aOldStt
.Row(), eWhich
, true));
1036 Point
aCurPosHmm(pGridWin
->PixelToLogic(aCurPos
, aDrawMode
));
1037 Point
aGridOff(aCurPosHmm
- aOldPos
);
1039 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
1040 bool bNegativePage
= rDoc
.IsNegativePage(GetTab());
1042 // fdo#63878 Fix the X position for RTL Sheet
1043 if(bNegativePage
&& !bLOKActive
)
1045 aGridOff
.setX(aCurPosHmm
.getX() + aOldPos
.getX());
1048 rTarget
.setX(bNegativePage
&& bLOKActive
? -aGridOff
.X() : aGridOff
.X());
1049 rTarget
.setY(aGridOff
.Y());
1053 bool ScDrawView::calculateGridOffsetForB2DRange(
1054 const basegfx::B2DRange
& rB2DRange
,
1055 basegfx::B2DVector
& rTarget
) const
1057 ScGridWindow
* pGridWin(pViewData
->GetActiveWin());
1059 if(nullptr == pGridWin
|| rB2DRange
.isEmpty())
1064 // No SdrObject, so synthesise an anchor ( but don't attach it to
1065 // the object as we want to maintain page anchoring )
1066 ScDrawObjData aAnchor
;
1067 const tools::Rectangle
aRectangle(
1068 basegfx::fround
<tools::Long
>(rB2DRange
.getMinX()), basegfx::fround
<tools::Long
>(rB2DRange
.getMinY()),
1069 basegfx::fround
<tools::Long
>(rB2DRange
.getMaxX()), basegfx::fround
<tools::Long
>(rB2DRange
.getMaxY()));
1070 ScDrawLayer::GetCellAnchorFromPosition(
1075 ScAddress
aOldStt(aAnchor
.maStart
);
1077 MapMode aDrawMode
= pGridWin
->GetDrawMapMode();
1079 // find pos anchor position
1080 Point
aOldPos(rDoc
.GetColOffset(aOldStt
.Col(), aOldStt
.Tab()), rDoc
.GetRowOffset(aOldStt
.Row(), aOldStt
.Tab()));
1081 aOldPos
= convertTwipToMm100(aOldPos
);
1083 // find position of same point on the screen ( e.g. grid )
1084 ScSplitPos
eWhich(pViewData
->GetActivePart());
1085 Point
aCurPos(pViewData
->GetScrPos(aOldStt
.Col(), aOldStt
.Row(), eWhich
, true));
1086 Point
aCurPosHmm(pGridWin
->PixelToLogic(aCurPos
, aDrawMode
));
1087 Point
aGridOff(aCurPosHmm
- aOldPos
);
1089 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
1090 bool bNegativePage
= rDoc
.IsNegativePage(GetTab());
1092 // fdo#63878 Fix the X position for RTL Sheet
1093 if(bNegativePage
&& !bLOKActive
)
1095 aGridOff
.setX(aCurPosHmm
.getX() + aOldPos
.getX());
1098 rTarget
.setX(bLOKActive
&& bNegativePage
? -aGridOff
.X() : aGridOff
.X());
1099 rTarget
.setY(aGridOff
.Y());
1103 // Create a new view-local UndoManager manager for Calc
1104 std::unique_ptr
<SdrUndoManager
> ScDrawView::createLocalTextUndoManager()
1106 std::unique_ptr
<SdrUndoManager
> pUndoManager(new SdrUndoManager
);
1107 ScDocShell
* pDocShell
= pViewData
? pViewData
->GetDocShell() : nullptr;
1108 pUndoManager
->SetDocShell(pDocShell
);
1109 return pUndoManager
;
1112 // #i123922# helper to apply a Graphic to an existing SdrObject
1113 SdrObject
* ScDrawView::ApplyGraphicToObject(
1114 SdrObject
& rHitObject
,
1115 const Graphic
& rGraphic
,
1116 const OUString
& rBeginUndoText
,
1117 const OUString
& rFile
)
1119 if(auto pGrafHitObj
= dynamic_cast< SdrGrafObj
* >(&rHitObject
))
1121 rtl::Reference
<SdrGrafObj
> pNewGrafObj
= SdrObject::Clone(*pGrafHitObj
, rHitObject
.getSdrModelFromSdrObject());
1123 pNewGrafObj
->SetGraphic(rGraphic
);
1124 BegUndo(rBeginUndoText
);
1125 ReplaceObjectAtView(&rHitObject
, *GetSdrPageView(), pNewGrafObj
.get());
1127 // set in all cases - the Clone() will have copied an existing link (!)
1128 pNewGrafObj
->SetGraphicLink( rFile
);
1131 return pNewGrafObj
.get();
1133 else if(rHitObject
.IsClosedObj() && !dynamic_cast< SdrOle2Obj
* >(&rHitObject
))
1135 AddUndo(std::make_unique
<SdrUndoAttrObj
>(rHitObject
));
1137 SfxItemSetFixed
<XATTR_FILLSTYLE
, XATTR_FILLBITMAP
> aSet(GetModel().GetItemPool());
1139 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
1140 aSet
.Put(XFillBitmapItem(OUString(), rGraphic
));
1141 rHitObject
.SetMergedItemSetAndBroadcast(aSet
);
1148 // Own derivation of ObjectContact to allow on-demand calculation of
1149 // GridOffset for non-linear ViewToDevice transformation (calc)
1150 namespace sdr::contact
1154 class ObjectContactOfScDrawView final
: public ObjectContactOfPageView
1157 // The ScDrawView to work on
1158 const ScDrawView
& mrScDrawView
;
1161 explicit ObjectContactOfScDrawView(
1162 const ScDrawView
& rScDrawView
,
1163 SdrPageWindow
& rPageWindow
,
1164 const char* pDebugName
);
1166 virtual bool supportsGridOffsets() const override
;
1167 virtual void calculateGridOffsetForViewObjectContact(
1168 basegfx::B2DVector
& rTarget
,
1169 const ViewObjectContact
& rClient
) const override
;
1170 virtual void calculateGridOffsetForB2DRange(
1171 basegfx::B2DVector
& rTarget
,
1172 const basegfx::B2DRange
& rB2DRange
) const override
;
1177 ObjectContactOfScDrawView::ObjectContactOfScDrawView(
1178 const ScDrawView
& rScDrawView
,
1179 SdrPageWindow
& rPageWindow
,
1180 const char* pDebugName
)
1181 : ObjectContactOfPageView(rPageWindow
, pDebugName
),
1182 mrScDrawView(rScDrawView
)
1186 bool ObjectContactOfScDrawView::supportsGridOffsets() const
1188 // Except when scPrintTwipsMsgs flag is active,
1189 // Calc in LOK mode directly sets pixel-aligned logical coordinates for draw-objects.
1190 if (comphelper::LibreOfficeKit::isActive() &&
1191 !comphelper::LibreOfficeKit::isCompatFlagSet(
1192 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
1195 // no GridOffset support for printer
1196 if(isOutputToPrinter())
1201 // no GridOffset support for PDF export
1202 if(isOutputToPDFFile())
1207 // yes - we support it
1211 void ObjectContactOfScDrawView::calculateGridOffsetForViewObjectContact(
1212 basegfx::B2DVector
& rTarget
,
1213 const ViewObjectContact
& rClient
) const
1215 // Here the on-demand calculation happens. Try to access the SdrObject involved
1216 SdrObject
* pTargetSdrObject(rClient
.GetViewContact().TryToGetSdrObject());
1218 if(nullptr != pTargetSdrObject
)
1220 mrScDrawView
.calculateGridOffsetForSdrObject(
1226 void ObjectContactOfScDrawView::calculateGridOffsetForB2DRange(
1227 basegfx::B2DVector
& rTarget
,
1228 const basegfx::B2DRange
& rB2DRange
) const
1230 // Here the on-demand calculation happens. Try to access the SdrObject involved
1231 if(!rB2DRange
.isEmpty())
1233 mrScDrawView
.calculateGridOffsetForB2DRange(
1240 // Create own derivation of ObjectContact for calc
1241 sdr::contact::ObjectContact
* ScDrawView::createViewSpecificObjectContact(
1242 SdrPageWindow
& rPageWindow
,
1243 const char* pDebugName
) const
1245 return new sdr::contact::ObjectContactOfScDrawView(
1251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */