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