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 <sal/config.h>
24 #include <svx/svdograf.hxx>
25 #include <svx/svdoole2.hxx>
26 #include <svx/ImageMapInfo.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <comphelper/lok.hxx>
29 #include <officecfg/Office/Common.hxx>
31 #include <strings.hrc>
32 #include <scresid.hxx>
33 #include <drawview.hxx>
34 #include <drwlayer.hxx>
35 #include "imapwrap.hxx"
36 #include <viewdata.hxx>
37 #include <document.hxx>
38 #include <userdat.hxx>
39 #include <tabvwsh.hxx>
42 ScDrawView::ScDrawView(
45 : FmFormView(*pData
->GetDocument().GetDrawLayer(), pOut
),
48 rDoc( pData
->GetDocument() ),
49 nTab( pData
->GetTabNo() ),
50 pDropMarkObj( nullptr ),
53 SetNegativeX(comphelper::LibreOfficeKit::isActive() && rDoc
.IsLayoutRTL(nTab
));
54 // #i73602# Use default from the configuration
55 SetBufferedOverlayAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_Calc::get());
57 // #i74769#, #i75172# Use default from the configuration
58 SetBufferedOutputAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::PaintBuffer_Calc::get());
65 void ScDrawView::SetPageAnchored()
67 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
68 if( rMarkList
.GetMarkCount() == 0 )
71 const size_t nCount
= rMarkList
.GetMarkCount();
73 BegUndo(ScResId(SCSTR_UNDO_PAGE_ANCHOR
));
74 for( size_t i
=0; i
<nCount
; ++i
)
76 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
77 AddUndo (std::make_unique
<ScUndoAnchorData
>( pObj
, &rDoc
, nTab
));
78 ScDrawLayer::SetPageAnchored( *pObj
);
83 pViewData
->GetDocShell()->SetDrawModified();
85 // Remove the anchor object.
86 maHdlList
.RemoveAllByKind(SdrHdlKind::Anchor
);
87 maHdlList
.RemoveAllByKind(SdrHdlKind::Anchor_TR
);
90 void ScDrawView::SetCellAnchored(bool bResizeWithCell
)
92 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
93 if( rMarkList
.GetMarkCount() == 0 )
96 const size_t nCount
= rMarkList
.GetMarkCount();
98 BegUndo(ScResId(SCSTR_UNDO_CELL_ANCHOR
));
99 for( size_t i
=0; i
<nCount
; ++i
)
101 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
102 AddUndo (std::make_unique
<ScUndoAnchorData
>( pObj
, &rDoc
, nTab
));
103 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, rDoc
, nTab
, bResizeWithCell
);
109 pViewData
->GetDocShell()->SetDrawModified();
111 // Set the anchor object.
116 ScAnchorType
ScDrawView::GetAnchorType() const
120 bool bCellResize
= false;
121 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
122 if( rMarkList
.GetMarkCount() != 0 )
124 const size_t nCount
= rMarkList
.GetMarkCount();
125 for( size_t i
=0; i
<nCount
; ++i
)
127 const SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
128 const ScAnchorType aAnchorType
= ScDrawLayer::GetAnchorType( *pObj
);
129 if( aAnchorType
== SCA_CELL
)
131 else if (aAnchorType
== SCA_CELL_RESIZE
)
137 if( bPage
&& !bCell
&& !bCellResize
)
139 if( !bPage
&& bCell
&& !bCellResize
)
141 if( !bPage
&& !bCell
&& bCellResize
)
142 return SCA_CELL_RESIZE
;
148 bool lcl_AreRectanglesApproxEqual(const tools::Rectangle
& rRectA
, const tools::Rectangle
& rRectB
)
150 // Twips <-> Hmm conversions introduce +-1 differences although the rectangles should actually
151 // be equal. Therefore test with == is not appropriate in some cases.
152 if (std::abs(rRectA
.Left() - rRectB
.Left()) > 1)
154 if (std::abs(rRectA
.Top() - rRectB
.Top()) > 1)
156 if (std::abs(rRectA
.Right() - rRectB
.Right()) > 1)
158 if (std::abs(rRectA
.Bottom() - rRectB
.Bottom()) > 1)
164 * Updated the anchors of any non-note object that is cell anchored which
165 * has been moved since the last anchors for its position was calculated.
167 void adjustAnchoredPosition(const SdrHint
& rHint
, const ScDocument
& rDoc
, SCTAB nTab
)
169 if (rHint
.GetKind() != SdrHintKind::ObjectChange
&& rHint
.GetKind() != SdrHintKind::ObjectInserted
)
172 SdrObject
* pObj
= const_cast<SdrObject
*>(rHint
.GetObject());
176 ScDrawObjData
*pAnchor
= ScDrawLayer::GetObjData(pObj
);
180 if (pAnchor
->meType
== ScDrawObjData::CellNote
)
183 // SetCellAnchoredFromPosition has to be called only if shape geometry has been changed, and not
184 // if only shape visibility has been changed. It is not enough to test shape rect, because e.g. a
185 // 180deg rotation changes only the logic rect (tdf#139583).
186 ScDrawObjData
& rNoRotatedAnchor
= *ScDrawLayer::GetNonRotatedObjData(pObj
, true /*bCreate*/);
187 if (lcl_AreRectanglesApproxEqual(pAnchor
->getShapeRect(), pObj
->GetSnapRect())
188 && lcl_AreRectanglesApproxEqual(rNoRotatedAnchor
.getShapeRect(), pObj
->GetLogicRect()))
191 if (pAnchor
->maStart
.Tab() != nTab
)
192 // The object is not anchored on the current sheet. Skip it.
193 // TODO: In the future, we may want to adjust objects that are
194 // anchored on all selected sheets.
197 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, rDoc
, pAnchor
->maStart
.Tab(), pAnchor
->mbResizeWithCell
);
202 void ScDrawView::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
204 if (rHint
.GetId() == SfxHintId::ThisIsAnSdrHint
)
206 const SdrHint
* pSdrHint
= static_cast<const SdrHint
*>( &rHint
);
207 adjustAnchoredPosition(*pSdrHint
, rDoc
, nTab
);
208 FmFormView::Notify( rBC
,rHint
);
210 else if (rHint
.GetId() == SfxHintId::ScTabDeleted
) // Sheet has been deleted
212 auto pDeletedHint
= static_cast<const ScTabDeletedHint
*>(&rHint
);
213 SCTAB nDelTab
= pDeletedHint
->GetTab();
214 if (ValidTab(nDelTab
))
216 // used to be: HidePagePgNum(nDelTab) - hide only if the deleted sheet is shown here
217 if ( nDelTab
== nTab
)
221 else if (rHint
.GetId() == SfxHintId::ScTabSizeChanged
) // Size has been changed
223 auto pChangedHint
= static_cast<const ScTabSizeChangedHint
*>(&rHint
);
224 if ( nTab
== pChangedHint
->GetTab() )
228 FmFormView::Notify( rBC
,rHint
);
231 void ScDrawView::UpdateIMap( SdrObject
* pObj
)
234 pViewData
->GetViewShell()->GetViewFrame().HasChildWindow( ScIMapChildWindowId() ) &&
235 pObj
&& ( dynamic_cast<const SdrGrafObj
*>( pObj
) != nullptr || dynamic_cast<const SdrOle2Obj
*>( pObj
) != nullptr )) )
239 TargetList aTargetList
;
240 SvxIMapInfo
* pIMapInfo
= SvxIMapInfo::GetIMapInfo( pObj
);
241 const ImageMap
* pImageMap
= nullptr;
243 pImageMap
= &pIMapInfo
->GetImageMap();
245 // handle target list
246 SfxViewFrame::GetTargetList( aTargetList
);
248 // handle graphics from object
249 if ( auto pGrafObj
= dynamic_cast<SdrGrafObj
*>( pObj
) )
250 aGraphic
= pGrafObj
->GetGraphic();
253 const Graphic
* pGraphic
= static_cast<const SdrOle2Obj
*>(pObj
)->GetGraphic();
255 aGraphic
= *pGraphic
;
258 ScIMapDlgSet( aGraphic
, pImageMap
, &aTargetList
, pObj
); // from imapwrap
261 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */