tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / drawview.cxx
blobb0c5e396322e9c8e4d145fe0bbe5f5a74e0c8085
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
48 #include <global.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>
55 #include <client.hxx>
56 #include <scmod.hxx>
57 #include <drwlayer.hxx>
58 #include <docsh.hxx>
59 #include <viewuno.hxx>
60 #include <userdat.hxx>
61 #include <postit.hxx>
62 #include <undocell.hxx>
63 #include <gridwin.hxx>
65 #include <sc.hrc>
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 );
81 if (pViewData)
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();
90 SdrLayer* pLayer;
91 SdrLayerAdmin& rAdmin = GetModel().GetLayerAdmin();
92 pLayer = rAdmin.GetLayerPerID(SC_LAYER_BACK);
93 if (pLayer)
94 SetLayerLocked( pLayer->GetName(), bProt || !bEx );
95 pLayer = rAdmin.GetLayerPerID(SC_LAYER_INTERN);
96 if (pLayer)
97 SetLayerLocked( pLayer->GetName() );
98 pLayer = rAdmin.GetLayerPerID(SC_LAYER_FRONT);
99 if (pLayer)
101 SetLayerLocked( pLayer->GetName(), bProt );
102 SetActiveLayer( pLayer->GetName() ); // set active layer to FRONT
104 pLayer = rAdmin.GetLayerPerID(SC_LAYER_CONTROLS);
105 if (pLayer)
106 SetLayerLocked( pLayer->GetName(), bProt );
107 pLayer = rAdmin.GetLayerPerID(SC_LAYER_HIDDEN);
108 if (pLayer)
110 SetLayerLocked( pLayer->GetName(), bProt );
111 SetLayerVisible( pLayer->GetName(), false);
114 SetSwapAsynchron();
116 else
118 ShowSdrPage(GetModel().GetPage(nTab));
121 UpdateUserViewOptions();
122 RecalcScale();
123 UpdateWorkArea();
125 bInConstruct = false;
128 void ScDrawView::ImplClearCalcDropMarker()
130 pDropMarker.reset();
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)
216 return;
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();
227 assert(pObj);
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 );
235 EndUndo();
237 // repaint is done in SetLayer
239 pViewData->GetDocShell()->SetDrawModified();
241 // check mark list now instead of later in a timer
242 CheckMarked();
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 )
251 return true;
252 return false;
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 )
261 return true;
262 return false;
265 void ScDrawView::UpdateWorkArea()
267 SdrPage* pPage = GetModel().GetPage(static_cast<sal_uInt16>(nTab));
268 if (pPage)
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 );
280 else
282 OSL_FAIL("Page not found");
286 void ScDrawView::DoCut()
288 DoCopy();
289 BegUndo( ScResId( STR_UNDO_CUT ) );
290 DeleteMarked(); // In this View - not affected by 505f change
291 EndUndo();
294 void ScDrawView::GetScale( Fraction& rFractX, Fraction& rFractY ) const
296 rFractX = aScaleX;
297 rFractY = aScaleY;
300 void ScDrawView::RecalcScale()
302 double nPPTX;
303 double nPPTY;
304 Fraction aZoomX(1,1);
305 Fraction aZoomY(1,1);
307 if (pViewData)
309 nTab = pViewData->GetTabNo();
310 nPPTX = pViewData->GetPPTX();
311 nPPTY = pViewData->GetPPTY();
312 aZoomX = pViewData->GetZoomX();
313 aZoomY = pViewData->GetZoomY();
315 else
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 ???
323 SCCOL nEndCol = 0;
324 SCROW nEndRow = 0;
325 rDoc.GetTableArea( nTab, nEndCol, nEndRow );
326 if (nEndCol<20)
327 nEndCol = 20;
328 if (nEndRow<20)
329 nEndRow = 20;
331 ScDrawUtil::CalcScale(
332 rDoc, nTab, 0, 0, nEndCol, nEndRow, pDev, aZoomX, aZoomY, nPPTX, nPPTY,
333 aScaleX, aScaleY);
335 // clear all evtl existing GridOffset vectors
336 resetGridOffsetsForAllSdrPageViews();
338 SdrPageView* pPV = GetSdrPageView();
339 if ( !(pViewData && pPV) )
340 return;
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)
352 if ( pViewData )
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();
373 // deactivate IP
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);
396 LockInternalLayer();
399 bool bSubShellSet = false;
400 if (nMarkCount == 1)
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);
408 else
409 pViewSh->SetChartShell(true);
410 bSubShellSet = true;
412 else if (pObj->GetObjIdentifier() == SdrObjKind::Graphic)
414 pGrafObj = static_cast<SdrGrafObj*>(pObj);
415 pViewSh->SetGraphicShell(true);
416 bSubShellSet = true;
418 else if (pObj->GetObjIdentifier() == SdrObjKind::Media)
420 pViewSh->SetMediaShell(true);
421 bSubShellSet = 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;
446 bOnlyGraf = false;
448 for ( size_t j = 0; j < nListCount; ++j )
450 SdrObject *pSubObj = pLst->GetObj( j );
451 assert(pSubObj);
453 if (dynamic_cast<const SdrUnoObj*>( pSubObj) == nullptr)
454 bOnlyControls = false;
455 if (pSubObj->GetObjIdentifier() != SdrObjKind::Graphic)
456 bOnlyGraf = false;
458 if ( !bOnlyControls && !bOnlyGraf ) break;
461 else
463 if (dynamic_cast<const SdrUnoObj*>( pObj) == nullptr)
464 bOnlyControls = false;
465 if (pObj->GetObjIdentifier() != SdrObjKind::Graphic)
466 bOnlyGraf = false;
469 if ( !bOnlyControls && !bOnlyGraf ) break;
472 if(bOnlyControls)
474 pViewSh->SetDrawFormShell(true); // now UNO controls
476 else if(bOnlyGraf)
478 pViewSh->SetGraphicShell(true);
480 else if(nMarkCount>1)
482 pViewSh->SetDrawShell(true);
486 // adjust verbs
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" );
495 if (xObj.is())
496 aVerbs = xObj->getSupportedVerbs();
498 pViewSh->SetVerbs( aVerbs );
500 // image map editor
502 if ( pOle2Obj )
503 UpdateIMap( pOle2Obj );
504 else if ( pGrafObj )
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() );
529 if (pImp)
530 pImp->SelectionChanged();
533 // update selection transfer object
535 pViewSh->CheckSelectionTransfer();
539 bool ScDrawView::SdrBeginTextEdit(
540 SdrObject* pObj,
541 SdrPageView* pPV,
542 vcl::Window* pWinL,
543 bool bIsNewObj,
544 SdrOutliner* pGivenOutliner,
545 OutlinerView* pGivenOutlinerView,
546 bool bDontDeleteOutliner,
547 bool bOnlyOneView,
548 bool bGrabFocus )
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() );
576 if (pImp)
577 pImp->SelectionChanged();
580 return bRet;
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() );
597 if (pImp)
598 pImp->SelectionChanged();
601 return eRet;
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()
620 if (!pViewData)
621 return;
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();
645 if (pShell)
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 ?");
653 if (pPage)
655 SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
656 SdrObject* pObject = aIter.Next();
657 while (pObject)
659 if ( ScDrawLayer::GetVisibleName( pObject ) == rName )
661 return pObject;
663 pObject = aIter.Next();
668 return nullptr;
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();
678 if (pShell)
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 ?");
686 if (pPage)
688 SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
689 SdrObject* pObject = aIter.Next();
690 while (pObject && !pFound)
692 if ( ScDrawLayer::GetVisibleName( pObject ) == rName )
694 pFound = pObject;
695 nObjectTab = i;
697 pObject = aIter.Next();
702 if ( !pFound )
703 return;
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);
716 if (pLayer)
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 )
726 UnmarkAll();
728 SCTAB nObjectTab = 0;
729 SdrObject* pFound = nullptr;
731 ScDocShell* pShell = rDoc.GetDocumentShell();
732 if (pShell)
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 ?");
740 if (pPage)
742 SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
743 SdrObject* pObject = aIter.Next();
744 while (pObject && !pFound)
746 if ( ScDrawLayer::GetVisibleName( pObject ) == rName )
748 pFound = pObject;
749 nObjectTab = i;
751 pObject = aIter.Next();
757 if ( pFound )
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;
789 if (pObject )
791 bisMarked = IsObjMarked(pObject);
793 return bisMarked;
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!)
802 if (pViewData)
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;
821 return pObj;
824 return nullptr;
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" );
862 if( pNote )
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
868 if( bUndo )
869 pDrawLayer->BeginCalcUndo(false);
870 // delete the note (already removed from document above)
871 pNote.reset();
872 // add the undo action for the note
873 if( bUndo )
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
876 if( pDocShell )
877 pDocShell->PostPaintCell( pCaptData->maStart );
878 // done, return now to skip call of FmFormView::DeleteMarked()
879 return;
883 FmFormView::DeleteMarked();
886 SdrEndTextEditKind ScDrawView::ScEndTextEdit()
888 bool bIsTextEdit = IsTextEdit();
889 SdrEndTextEditKind eKind = SdrEndTextEdit();
891 if (bIsTextEdit)
892 pViewData->GetViewShell()->SetDrawTextUndo(nullptr); // the "normal" undo manager
894 return eKind;
897 void ScDrawView::MarkDropObj( SdrObject* pObj )
899 if ( pDropMarkObj != pObj )
901 pDropMarkObj = pObj;
902 ImplClearCalcDropMarker();
904 if(pDropMarkObj)
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 );
930 if ( !pGridWin )
931 return;
933 ScAddress aOldStt;
934 if( pData && pData->maStart.IsValid())
936 aOldStt = pData->maStart;
938 else
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(
946 aObjRect,
947 aAnchor,
948 rDoc,
949 GetTab());
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)
970 return;
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))
996 return false;
998 ScGridWindow* pGridWin(pViewData->GetActiveWin());
1000 if(nullptr == pGridWin)
1002 return false;
1005 ScDrawObjData* pData(ScDrawLayer::GetObjData(&rSdrObject));
1006 ScAddress aOldStt;
1008 if(nullptr != pData && pData->maStart.IsValid())
1010 aOldStt = pData->maStart;
1012 else
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(
1020 aObjRect,
1021 aAnchor,
1022 rDoc,
1023 GetTab());
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());
1050 return true;
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())
1061 return false;
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(
1071 aRectangle,
1072 aAnchor,
1073 rDoc,
1074 GetTab());
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());
1100 return true;
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 );
1130 EndUndo();
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);
1142 return &rHitObject;
1145 return nullptr;
1148 // Own derivation of ObjectContact to allow on-demand calculation of
1149 // GridOffset for non-linear ViewToDevice transformation (calc)
1150 namespace sdr::contact
1152 namespace {
1154 class ObjectContactOfScDrawView final : public ObjectContactOfPageView
1156 private:
1157 // The ScDrawView to work on
1158 const ScDrawView& mrScDrawView;
1160 public:
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))
1193 return false;
1195 // no GridOffset support for printer
1196 if(isOutputToPrinter())
1198 return false;
1201 // no GridOffset support for PDF export
1202 if(isOutputToPDFFile())
1204 return false;
1207 // yes - we support it
1208 return true;
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(
1221 *pTargetSdrObject,
1222 rTarget);
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(
1234 rB2DRange,
1235 rTarget);
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(
1246 *this,
1247 rPageWindow,
1248 pDebugName);
1251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */