/src/libreoffice/sc/source/ui/drawfunc/fudraw.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 <editeng/editeng.hxx> |
21 | | #include <vcl/ptrstyle.hxx> |
22 | | #include <editeng/outlobj.hxx> |
23 | | #include <svx/svdobj.hxx> |
24 | | #include <svx/svdoole2.hxx> |
25 | | #include <svx/svdouno.hxx> |
26 | | #include <svx/ImageMapInfo.hxx> |
27 | | #include <sfx2/dispatch.hxx> |
28 | | #include <sfx2/viewfrm.hxx> |
29 | | #include <vcl/uitest/logger.hxx> |
30 | | #include <vcl/uitest/eventdescription.hxx> |
31 | | |
32 | | #include <sc.hrc> |
33 | | #include <fudraw.hxx> |
34 | | #include <futext.hxx> |
35 | | #include <tabvwsh.hxx> |
36 | | #include <drwlayer.hxx> |
37 | | #include <userdat.hxx> |
38 | | #include <docsh.hxx> |
39 | | #include <drawview.hxx> |
40 | | #include <comphelper/lok.hxx> |
41 | | #include <com/sun/star/embed/EmbedVerbs.hpp> |
42 | | |
43 | | namespace |
44 | | { |
45 | | |
46 | | void collectUIInformation( const OUString& aevent ) |
47 | 0 | { |
48 | 0 | EventDescription aDescription; |
49 | 0 | aDescription.aID = "grid_window"; |
50 | 0 | aDescription.aParameters = {{ aevent , ""}}; |
51 | 0 | aDescription.aAction = "COMMENT"; |
52 | 0 | aDescription.aParent = "MainWindow"; |
53 | 0 | aDescription.aKeyWord = "ScGridWinUIObject"; |
54 | 0 | UITestLogger::getInstance().logEvent(aDescription); |
55 | 0 | } |
56 | | |
57 | | } |
58 | | |
59 | | // base class for draw module specific functions |
60 | | FuDraw::FuDraw(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP, |
61 | | SdrModel& rDoc, const SfxRequest& rReq) |
62 | 0 | : FuPoor(rViewSh, pWin, pViewP, rDoc, rReq) |
63 | 0 | , aNewPointer(PointerStyle::Arrow) |
64 | 0 | , aOldPointer(PointerStyle::Arrow) |
65 | 0 | { |
66 | 0 | } |
67 | | |
68 | | FuDraw::~FuDraw() |
69 | 0 | { |
70 | 0 | } |
71 | | |
72 | | void FuDraw::DoModifiers(const MouseEvent& rMEvt) |
73 | 0 | { |
74 | | // Shift = Ortho and AngleSnap |
75 | | // Control = Snap (Toggle) |
76 | | // Alt = centric |
77 | |
|
78 | 0 | bool bShift = rMEvt.IsShift(); |
79 | 0 | bool bAlt = rMEvt.IsMod2(); |
80 | |
|
81 | 0 | bool bOrtho = bShift; |
82 | 0 | bool bAngleSnap = bShift; |
83 | 0 | bool bCenter = bAlt; |
84 | | |
85 | | // #i33136# |
86 | 0 | if(doConstructOrthogonal()) |
87 | 0 | { |
88 | 0 | bOrtho = !bShift; |
89 | 0 | } |
90 | |
|
91 | 0 | if (pView->IsOrtho() != bOrtho) |
92 | 0 | pView->SetOrtho(bOrtho); |
93 | 0 | if (pView->IsAngleSnapEnabled() != bAngleSnap) |
94 | 0 | pView->SetAngleSnapEnabled(bAngleSnap); |
95 | |
|
96 | 0 | if (pView->IsCreate1stPointAsCenter() != bCenter) |
97 | 0 | pView->SetCreate1stPointAsCenter(bCenter); |
98 | 0 | if (pView->IsResizeAtCenter() != bCenter) |
99 | 0 | pView->SetResizeAtCenter(bCenter); |
100 | |
|
101 | 0 | } |
102 | | |
103 | | void FuDraw::ResetModifiers() |
104 | 0 | { |
105 | 0 | if (!pView) |
106 | 0 | return; |
107 | | |
108 | 0 | ScViewData& rViewData = rViewShell.GetViewData(); |
109 | 0 | const ScViewOptions& rOpt = rViewData.GetOptions(); |
110 | 0 | const ScGridOptions& rGrid = rOpt.GetGridOptions(); |
111 | 0 | bool bGridOpt = rGrid.GetUseGridSnap(); |
112 | |
|
113 | 0 | if (pView->IsOrtho()) |
114 | 0 | pView->SetOrtho(false); |
115 | 0 | if (pView->IsAngleSnapEnabled()) |
116 | 0 | pView->SetAngleSnapEnabled(false); |
117 | |
|
118 | 0 | if (pView->IsGridSnap() != bGridOpt) |
119 | 0 | pView->SetGridSnap(bGridOpt); |
120 | 0 | if (pView->IsSnapEnabled() != bGridOpt) |
121 | 0 | pView->SetSnapEnabled(bGridOpt); |
122 | |
|
123 | 0 | if (pView->IsCreate1stPointAsCenter()) |
124 | 0 | pView->SetCreate1stPointAsCenter(false); |
125 | 0 | if (pView->IsResizeAtCenter()) |
126 | 0 | pView->SetResizeAtCenter(false); |
127 | 0 | } |
128 | | |
129 | | bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt) |
130 | 0 | { |
131 | | // remember button state for creation of own MouseEvents |
132 | 0 | SetMouseButtonCode(rMEvt.GetButtons()); |
133 | |
|
134 | 0 | DoModifiers( rMEvt ); |
135 | 0 | return false; |
136 | 0 | } |
137 | | |
138 | | bool FuDraw::MouseMove(const MouseEvent& rMEvt) |
139 | 0 | { |
140 | 0 | if (SfxViewShell* pSfxViewShell = pView->GetSfxViewShell()) |
141 | 0 | { |
142 | 0 | pSfxViewShell->GetDrawView()->MouseMove(rMEvt, pWindow->GetOutDev()); |
143 | | // evaluate modifiers only if in a drawing layer action |
144 | | // (don't interfere with keyboard shortcut handling) |
145 | 0 | if (pView->IsAction()) |
146 | 0 | DoModifiers( rMEvt ); |
147 | 0 | } |
148 | |
|
149 | 0 | return false; |
150 | 0 | } |
151 | | |
152 | | bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt) |
153 | 0 | { |
154 | | // remember button state for creation of own MouseEvents |
155 | 0 | SetMouseButtonCode(rMEvt.GetButtons()); |
156 | |
|
157 | 0 | ResetModifiers(); |
158 | 0 | return false; |
159 | 0 | } |
160 | | |
161 | | // Process Keyboard events. Return true if an event is being handled |
162 | | static bool lcl_KeyEditMode( SdrObject* pObj, ScTabViewShell& rViewShell, const KeyEvent* pInitialKey ) |
163 | 0 | { |
164 | 0 | bool bReturn = false; |
165 | 0 | if ( DynCastSdrTextObj( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) == nullptr ) |
166 | 0 | { |
167 | 0 | assert(pObj); |
168 | | // start text edit - like FuSelection::MouseButtonUp, |
169 | | // but with bCursorToEnd instead of mouse position |
170 | |
|
171 | 0 | OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject(); |
172 | 0 | bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() ); |
173 | 0 | sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT; |
174 | | |
175 | | // don't switch shells if text shell is already active |
176 | 0 | FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr(); |
177 | 0 | if ( !pPoor || pPoor->GetSlotID() != nTextSlotId ) |
178 | 0 | { |
179 | 0 | rViewShell.GetViewData().GetDispatcher(). |
180 | 0 | Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD); |
181 | 0 | } |
182 | | |
183 | | // get the resulting FuText and set in edit mode |
184 | 0 | pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr(); |
185 | 0 | if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // no RTTI |
186 | 0 | { |
187 | 0 | FuText* pText = static_cast<FuText*>(pPoor); |
188 | 0 | pText->SetInEditMode( pObj, nullptr, true, pInitialKey ); |
189 | | //! set cursor to end of text |
190 | 0 | } |
191 | 0 | bReturn = true; |
192 | 0 | } |
193 | 0 | return bReturn; |
194 | 0 | } |
195 | | |
196 | | bool FuDraw::KeyInput(const KeyEvent& rKEvt) |
197 | 0 | { |
198 | 0 | bool bReturn = false; |
199 | 0 | ScViewData& rViewData = rViewShell.GetViewData(); |
200 | |
|
201 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
202 | 0 | switch ( rKEvt.GetKeyCode().GetCode() ) |
203 | 0 | { |
204 | 0 | case KEY_ESCAPE: |
205 | 0 | if ( rViewShell.IsDrawTextShell() || aSfxRequest.GetSlot() == SID_DRAW_NOTEEDIT ) |
206 | 0 | { |
207 | 0 | collectUIInformation(u"CLOSE"_ustr); |
208 | | // if object selected -> normal draw-shell, else turn off drawing |
209 | 0 | rViewData.GetDispatcher().Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD); |
210 | 0 | bReturn = true; |
211 | 0 | } |
212 | 0 | else if ( rViewShell.IsDrawSelMode() ) |
213 | 0 | { |
214 | 0 | pView->UnmarkAll(); |
215 | 0 | rViewData.GetDispatcher().Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD); |
216 | 0 | bReturn = true; |
217 | 0 | } |
218 | 0 | else if ( rMarkList.GetMarkCount() != 0 ) |
219 | 0 | { |
220 | | // III |
221 | 0 | SdrHdlList& rHdlList = const_cast< SdrHdlList& >( pView->GetHdlList() ); |
222 | 0 | if( rHdlList.GetFocusHdl() ) |
223 | 0 | rHdlList.ResetFocusHdl(); |
224 | 0 | else |
225 | 0 | pView->UnmarkAll(); |
226 | | |
227 | | // while bezier editing, object is selected |
228 | 0 | if (rMarkList.GetMarkCount() == 0) |
229 | 0 | rViewShell.SetDrawShell( false ); |
230 | |
|
231 | 0 | bReturn = true; |
232 | 0 | } |
233 | 0 | break; |
234 | | |
235 | 0 | case KEY_DELETE: //! via accelerator |
236 | 0 | pView->DeleteMarked(); |
237 | 0 | bReturn = true; |
238 | 0 | break; |
239 | | |
240 | 0 | case KEY_RETURN: |
241 | 0 | { |
242 | 0 | if( rKEvt.GetKeyCode().GetModifier() == 0 ) |
243 | 0 | { |
244 | | // activate OLE object on RETURN for selected object |
245 | | // put selected text object in edit mode |
246 | 0 | if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() ) |
247 | 0 | { |
248 | 0 | bool bOle = rViewShell.GetViewFrame().GetFrame().IsInPlace(); |
249 | 0 | SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); |
250 | 0 | auto pOleObj = dynamic_cast<SdrOle2Obj*>(pObj); |
251 | 0 | if( pOleObj && !bOle ) |
252 | 0 | { |
253 | 0 | rViewShell.ActivateObject(pOleObj, css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY); |
254 | | |
255 | | // consumed |
256 | 0 | bReturn = true; |
257 | 0 | } |
258 | 0 | else if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) ) // start text edit for suitable object |
259 | 0 | bReturn = true; |
260 | 0 | } |
261 | 0 | } |
262 | 0 | } |
263 | 0 | break; |
264 | | |
265 | 0 | case KEY_F2: |
266 | 0 | { |
267 | 0 | if( rKEvt.GetKeyCode().GetModifier() == 0 ) |
268 | 0 | { |
269 | | // put selected text object in edit mode |
270 | | // (this is not SID_SETINPUTMODE, but F2 hardcoded, like in Writer) |
271 | 0 | if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() ) |
272 | 0 | { |
273 | 0 | SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); |
274 | 0 | if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) ) // start text edit for suitable object |
275 | 0 | bReturn = true; |
276 | 0 | } |
277 | 0 | } |
278 | 0 | } |
279 | 0 | break; |
280 | | |
281 | 0 | case KEY_TAB: |
282 | 0 | { |
283 | | // in calc do NOT start draw object selection using TAB/SHIFT-TAB when |
284 | | // there is not yet an object selected |
285 | 0 | if(rMarkList.GetMarkCount() != 0) |
286 | 0 | { |
287 | 0 | vcl::KeyCode aCode = rKEvt.GetKeyCode(); |
288 | |
|
289 | 0 | if ( !aCode.IsMod1() && !aCode.IsMod2() ) |
290 | 0 | { |
291 | | // changeover to the next object |
292 | 0 | if(!pView->MarkNextObj( !aCode.IsShift() )) |
293 | 0 | { |
294 | | //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj(). |
295 | 0 | if ( pView->HasMultipleMarkableObjects() && pView->HasMarkableObj() ) |
296 | 0 | { |
297 | | // No next object: go over open end and |
298 | | // get first from the other side |
299 | 0 | pView->UnmarkAllObj(); |
300 | 0 | pView->MarkNextObj(!aCode.IsShift()); |
301 | 0 | } |
302 | 0 | } |
303 | | |
304 | | // II |
305 | 0 | if(rMarkList.GetMarkCount() != 0) |
306 | 0 | pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow); |
307 | |
|
308 | 0 | bReturn = true; |
309 | 0 | } |
310 | | |
311 | | // handle Mod1 and Mod2 to get travelling running on different systems |
312 | 0 | if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2()) |
313 | 0 | { |
314 | | // II do something with a selected handle? |
315 | 0 | const SdrHdlList& rHdlList = pView->GetHdlList(); |
316 | 0 | bool bForward(!rKEvt.GetKeyCode().IsShift()); |
317 | |
|
318 | 0 | const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward); |
319 | | |
320 | | // guarantee visibility of focused handle |
321 | 0 | SdrHdl* pHdl = rHdlList.GetFocusHdl(); |
322 | |
|
323 | 0 | if(pHdl) |
324 | 0 | { |
325 | 0 | Point aHdlPosition(pHdl->GetPos()); |
326 | 0 | tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200)); |
327 | 0 | pView->MakeVisible(aVisRect, *pWindow); |
328 | 0 | } |
329 | | |
330 | | // consumed |
331 | 0 | bReturn = true; |
332 | 0 | } |
333 | 0 | } |
334 | 0 | } |
335 | 0 | break; |
336 | | |
337 | 0 | case KEY_END: |
338 | 0 | { |
339 | | // in calc do NOT select the last draw object when |
340 | | // there is not yet an object selected |
341 | 0 | if(rMarkList.GetMarkCount() != 0) |
342 | 0 | { |
343 | 0 | vcl::KeyCode aCode = rKEvt.GetKeyCode(); |
344 | |
|
345 | 0 | if ( aCode.IsMod1() ) |
346 | 0 | { |
347 | | // mark last object |
348 | 0 | pView->UnmarkAllObj(); |
349 | 0 | pView->MarkNextObj(); |
350 | | |
351 | | // II |
352 | 0 | if(rMarkList.GetMarkCount() != 0) |
353 | 0 | pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow); |
354 | |
|
355 | 0 | bReturn = true; |
356 | 0 | } |
357 | 0 | } |
358 | 0 | } |
359 | 0 | break; |
360 | | |
361 | 0 | case KEY_HOME: |
362 | 0 | { |
363 | | // in calc do NOT select the first draw object when |
364 | | // there is not yet an object selected |
365 | 0 | if(rMarkList.GetMarkCount() != 0) |
366 | 0 | { |
367 | 0 | vcl::KeyCode aCode = rKEvt.GetKeyCode(); |
368 | |
|
369 | 0 | if ( aCode.IsMod1() ) |
370 | 0 | { |
371 | | // mark first object |
372 | 0 | pView->UnmarkAllObj(); |
373 | 0 | pView->MarkNextObj(true); |
374 | | |
375 | | // II |
376 | 0 | if(rMarkList.GetMarkCount() != 0) |
377 | 0 | pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow); |
378 | |
|
379 | 0 | bReturn = true; |
380 | 0 | } |
381 | 0 | } |
382 | 0 | } |
383 | 0 | break; |
384 | | |
385 | 0 | case KEY_UP: |
386 | 0 | case KEY_DOWN: |
387 | 0 | case KEY_LEFT: |
388 | 0 | case KEY_RIGHT: |
389 | 0 | { |
390 | | // in calc do cursor travelling of draw objects only when |
391 | | // there is an object selected yet |
392 | 0 | if(rMarkList.GetMarkCount() != 0) |
393 | 0 | { |
394 | |
|
395 | 0 | if(rMarkList.GetMarkCount() == 1) |
396 | 0 | { |
397 | | // disable cursor travelling on note objects as the tail connector position |
398 | | // must not move. |
399 | 0 | SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); |
400 | 0 | if( ScDrawLayer::IsNoteCaption( pObj ) ) |
401 | 0 | break; |
402 | 0 | } |
403 | | |
404 | 0 | tools::Long nX = 0; |
405 | 0 | tools::Long nY = 0; |
406 | 0 | sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); |
407 | |
|
408 | 0 | if (nCode == KEY_UP) |
409 | 0 | { |
410 | | // scroll up |
411 | 0 | nX = 0; |
412 | 0 | nY =-1; |
413 | 0 | } |
414 | 0 | else if (nCode == KEY_DOWN) |
415 | 0 | { |
416 | | // scroll down |
417 | 0 | nX = 0; |
418 | 0 | nY = 1; |
419 | 0 | } |
420 | 0 | else if (nCode == KEY_LEFT) |
421 | 0 | { |
422 | | // scroll left |
423 | 0 | nX =-1; |
424 | 0 | nY = 0; |
425 | 0 | } |
426 | 0 | else if (nCode == KEY_RIGHT) |
427 | 0 | { |
428 | | // scroll right |
429 | 0 | nX = 1; |
430 | 0 | nY = 0; |
431 | 0 | } |
432 | |
|
433 | 0 | bool bReadOnly = rViewData.GetDocShell()->IsReadOnly(); |
434 | |
|
435 | 0 | if(!rKEvt.GetKeyCode().IsMod1() && !bReadOnly) |
436 | 0 | { |
437 | 0 | if(rKEvt.GetKeyCode().IsMod2()) |
438 | 0 | { |
439 | | // move in 1 pixel distance |
440 | 0 | Size aLogicSizeOnePixel = pWindow ? pWindow->PixelToLogic(Size(1,1)) : Size(100, 100); |
441 | 0 | nX *= aLogicSizeOnePixel.Width(); |
442 | 0 | nY *= aLogicSizeOnePixel.Height(); |
443 | 0 | } |
444 | 0 | else if(rKEvt.GetKeyCode().IsShift()) // #i121236# Support for shift key in calc |
445 | 0 | { |
446 | 0 | nX *= 1000; |
447 | 0 | nY *= 1000; |
448 | 0 | } |
449 | 0 | else |
450 | 0 | { |
451 | | // old, fixed move distance |
452 | 0 | nX *= 100; |
453 | 0 | nY *= 100; |
454 | 0 | } |
455 | | |
456 | | // is there a movement to do? |
457 | 0 | if(0 != nX || 0 != nY) |
458 | 0 | { |
459 | | // II |
460 | 0 | const SdrHdlList& rHdlList = pView->GetHdlList(); |
461 | 0 | SdrHdl* pHdl = rHdlList.GetFocusHdl(); |
462 | |
|
463 | 0 | if(nullptr == pHdl) |
464 | 0 | { |
465 | | // only take action when move is allowed |
466 | 0 | if(pView->IsMoveAllowed()) |
467 | 0 | { |
468 | | // restrict movement to WorkArea |
469 | 0 | const tools::Rectangle& rWorkArea = pView->GetWorkArea(); |
470 | |
|
471 | 0 | if(!rWorkArea.IsEmpty()) |
472 | 0 | { |
473 | 0 | tools::Rectangle aMarkRect(pView->GetMarkedObjRect()); |
474 | 0 | aMarkRect.Move(nX, nY); |
475 | |
|
476 | 0 | if(!aMarkRect.Contains(rWorkArea)) |
477 | 0 | { |
478 | 0 | if(aMarkRect.Left() < rWorkArea.Left()) |
479 | 0 | { |
480 | 0 | nX += rWorkArea.Left() - aMarkRect.Left(); |
481 | 0 | } |
482 | |
|
483 | 0 | if(aMarkRect.Right() > rWorkArea.Right()) |
484 | 0 | { |
485 | 0 | nX -= aMarkRect.Right() - rWorkArea.Right(); |
486 | 0 | } |
487 | |
|
488 | 0 | if(aMarkRect.Top() < rWorkArea.Top()) |
489 | 0 | { |
490 | 0 | nY += rWorkArea.Top() - aMarkRect.Top(); |
491 | 0 | } |
492 | |
|
493 | 0 | if(aMarkRect.Bottom() > rWorkArea.Bottom()) |
494 | 0 | { |
495 | 0 | nY -= aMarkRect.Bottom() - rWorkArea.Bottom(); |
496 | 0 | } |
497 | 0 | } |
498 | 0 | } |
499 | | |
500 | | // now move the selected draw objects |
501 | 0 | pView->MoveAllMarked(Size(nX, nY)); |
502 | | |
503 | | // II |
504 | 0 | pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow); |
505 | |
|
506 | 0 | bReturn = true; |
507 | 0 | } |
508 | 0 | } |
509 | 0 | else |
510 | 0 | { |
511 | | // move handle with index nHandleIndex |
512 | 0 | if (nX || nY) |
513 | 0 | { |
514 | | // now move the Handle (nX, nY) |
515 | 0 | Point aStartPoint(pHdl->GetPos()); |
516 | 0 | Point aEndPoint(pHdl->GetPos() + Point(nX, nY)); |
517 | 0 | const SdrDragStat& rDragStat = pView->GetDragStat(); |
518 | | |
519 | | // start dragging |
520 | 0 | pView->BegDragObj(aStartPoint, nullptr, pHdl, 0); |
521 | |
|
522 | 0 | if(pView->IsDragObj()) |
523 | 0 | { |
524 | 0 | bool bWasNoSnap = rDragStat.IsNoSnap(); |
525 | 0 | bool bWasSnapEnabled = pView->IsSnapEnabled(); |
526 | | |
527 | | // switch snapping off |
528 | 0 | if(!bWasNoSnap) |
529 | 0 | const_cast<SdrDragStat&>(rDragStat).SetNoSnap(); |
530 | 0 | if(bWasSnapEnabled) |
531 | 0 | pView->SetSnapEnabled(false); |
532 | |
|
533 | 0 | pView->MovAction(aEndPoint); |
534 | 0 | pView->EndDragObj(); |
535 | | |
536 | | // restore snap |
537 | 0 | if(!bWasNoSnap) |
538 | 0 | const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap); |
539 | 0 | if(bWasSnapEnabled) |
540 | 0 | pView->SetSnapEnabled(bWasSnapEnabled); |
541 | 0 | } |
542 | | |
543 | | // make moved handle visible |
544 | 0 | tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200)); |
545 | 0 | pView->MakeVisible(aVisRect, *pWindow); |
546 | |
|
547 | 0 | bReturn = true; |
548 | 0 | } |
549 | 0 | } |
550 | 0 | } |
551 | 0 | } |
552 | 0 | } |
553 | 0 | } |
554 | 0 | break; |
555 | | |
556 | 0 | case KEY_SPACE: |
557 | 0 | { |
558 | | // in calc do only something when draw objects are selected |
559 | 0 | if(rMarkList.GetMarkCount() != 0) |
560 | 0 | { |
561 | 0 | const SdrHdlList& rHdlList = pView->GetHdlList(); |
562 | 0 | SdrHdl* pHdl = rHdlList.GetFocusHdl(); |
563 | |
|
564 | 0 | if(pHdl) |
565 | 0 | { |
566 | 0 | if(pHdl->GetKind() == SdrHdlKind::Poly) |
567 | 0 | { |
568 | | // rescue ID of point with focus |
569 | 0 | sal_uInt32 nPol(pHdl->GetPolyNum()); |
570 | 0 | sal_uInt32 nPnt(pHdl->GetPointNum()); |
571 | |
|
572 | 0 | if(pView->IsPointMarked(*pHdl)) |
573 | 0 | { |
574 | 0 | if(rKEvt.GetKeyCode().IsShift()) |
575 | 0 | { |
576 | 0 | pView->UnmarkPoint(*pHdl); |
577 | 0 | } |
578 | 0 | } |
579 | 0 | else |
580 | 0 | { |
581 | 0 | if(!rKEvt.GetKeyCode().IsShift()) |
582 | 0 | { |
583 | 0 | pView->UnmarkAllPoints(); |
584 | 0 | } |
585 | |
|
586 | 0 | pView->MarkPoint(*pHdl); |
587 | 0 | } |
588 | |
|
589 | 0 | if(nullptr == rHdlList.GetFocusHdl()) |
590 | 0 | { |
591 | | // restore point with focus |
592 | 0 | SdrHdl* pNewOne = nullptr; |
593 | |
|
594 | 0 | for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a) |
595 | 0 | { |
596 | 0 | SdrHdl* pAct = rHdlList.GetHdl(a); |
597 | |
|
598 | 0 | if(pAct |
599 | 0 | && pAct->GetKind() == SdrHdlKind::Poly |
600 | 0 | && pAct->GetPolyNum() == nPol |
601 | 0 | && pAct->GetPointNum() == nPnt) |
602 | 0 | { |
603 | 0 | pNewOne = pAct; |
604 | 0 | } |
605 | 0 | } |
606 | |
|
607 | 0 | if(pNewOne) |
608 | 0 | { |
609 | 0 | const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne); |
610 | 0 | } |
611 | 0 | } |
612 | |
|
613 | 0 | bReturn = true; |
614 | 0 | } |
615 | 0 | } |
616 | 0 | } |
617 | 0 | } |
618 | 0 | break; |
619 | 0 | } |
620 | | |
621 | 0 | if (!bReturn) |
622 | 0 | { |
623 | 0 | bReturn = FuPoor::KeyInput(rKEvt); |
624 | 0 | } |
625 | |
|
626 | 0 | if (!bReturn) |
627 | 0 | { |
628 | | // allow direct typing into a selected text object |
629 | |
|
630 | 0 | if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() && EditEngine::IsSimpleCharInput(rKEvt) ) |
631 | 0 | { |
632 | 0 | SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); |
633 | |
|
634 | 0 | if (nullptr != pObj && pObj->isDiagram()) |
635 | 0 | { |
636 | 0 | SdrObject* pSubSelection(pObj->getDiagramSubSelection()); |
637 | 0 | if (nullptr != pSubSelection && pSubSelection->isDiagramTextNode()) |
638 | 0 | pObj = pSubSelection; |
639 | 0 | } |
640 | | |
641 | | // start text edit for suitable object, pass key event to OutlinerView |
642 | 0 | if ( lcl_KeyEditMode( pObj, rViewShell, &rKEvt ) ) |
643 | 0 | bReturn = true; |
644 | 0 | } |
645 | 0 | } |
646 | |
|
647 | 0 | return bReturn; |
648 | 0 | } |
649 | | |
650 | | // toggle mouse-pointer |
651 | | static bool lcl_UrlHit( const SdrView* pView, const Point& rPosPixel, const vcl::Window* pWindow ) |
652 | 0 | { |
653 | 0 | SdrViewEvent aVEvt; |
654 | 0 | MouseEvent aMEvt( rPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT ); |
655 | 0 | SdrHitKind eHit = pView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ); |
656 | |
|
657 | 0 | if (eHit != SdrHitKind::NONE && aVEvt.mpObj != nullptr) |
658 | 0 | { |
659 | 0 | if ( SvxIMapInfo::GetIMapInfo(aVEvt.mpObj) && SvxIMapInfo::GetHitIMapObject( |
660 | 0 | aVEvt.mpObj, pWindow->PixelToLogic(rPosPixel), pWindow->GetOutDev() ) ) |
661 | 0 | return true; |
662 | | |
663 | 0 | if (aVEvt.meEvent == SdrEventKind::ExecuteUrl) |
664 | 0 | return true; |
665 | 0 | } |
666 | | |
667 | 0 | return false; |
668 | 0 | } |
669 | | |
670 | | void FuDraw::ForcePointer(const MouseEvent* pMEvt) |
671 | 0 | { |
672 | 0 | if ( pView->IsAction() ) |
673 | 0 | return; |
674 | | |
675 | 0 | Point aPosPixel = pWindow->GetPointerPosPixel(); |
676 | 0 | bool bAlt = pMEvt && pMEvt->IsMod2(); |
677 | 0 | Point aPnt = pWindow->PixelToLogic( aPosPixel ); |
678 | 0 | SdrHdl* pHdl = pView->PickHandle(aPnt); |
679 | 0 | SdrPageView* pPV; |
680 | 0 | SdrObject* pMacroPickObj; |
681 | |
|
682 | 0 | ScMacroInfo* pInfo = nullptr; |
683 | 0 | SdrObject* pObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER); |
684 | 0 | if (pObj) |
685 | 0 | { |
686 | 0 | if ( pObj->IsGroupObject() ) |
687 | 0 | { |
688 | 0 | SdrObject* pHit = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP); |
689 | 0 | if (pHit) |
690 | 0 | pObj = pHit; |
691 | 0 | } |
692 | 0 | pInfo = ScDrawLayer::GetMacroInfo( pObj ); |
693 | 0 | } |
694 | |
|
695 | 0 | if ( pView->IsTextEdit() ) |
696 | 0 | { |
697 | 0 | rViewShell.SetActivePointer(PointerStyle::Text); // can't be ? |
698 | 0 | } |
699 | 0 | else if ( pHdl ) |
700 | 0 | { |
701 | 0 | rViewShell.SetActivePointer( |
702 | 0 | pView->GetPreferredPointer( aPnt, pWindow->GetOutDev() ) ); |
703 | 0 | } |
704 | 0 | else if ( pView->IsMarkedHit(aPnt) ) |
705 | 0 | { |
706 | 0 | rViewShell.SetActivePointer( PointerStyle::Move ); |
707 | 0 | } |
708 | 0 | else if ( !bAlt && ( !pMEvt || !pMEvt->GetButtons() ) |
709 | 0 | && lcl_UrlHit( pView, aPosPixel, pWindow ) ) |
710 | 0 | { |
711 | | // could be suppressed with ALT |
712 | 0 | pWindow->SetPointer( PointerStyle::RefHand ); // Text-URL / ImageMap |
713 | 0 | } |
714 | 0 | else if ( !bAlt && (pMacroPickObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO)) ) |
715 | 0 | { |
716 | | // could be suppressed with ALT |
717 | 0 | SdrObjMacroHitRec aHitRec; //! something missing ???? |
718 | 0 | rViewShell.SetActivePointer(pMacroPickObj->GetMacroPointer(aHitRec)); |
719 | 0 | } |
720 | 0 | else if ( !bAlt && pInfo && (!pInfo->GetMacro().isEmpty() || !pObj->getHyperlink().isEmpty()) ) |
721 | 0 | pWindow->SetPointer( PointerStyle::RefHand ); |
722 | 0 | else if ( IsDetectiveHit( aPnt ) ) |
723 | 0 | rViewShell.SetActivePointer( PointerStyle::Detective ); |
724 | 0 | else |
725 | 0 | { |
726 | 0 | const bool bIsThemed = rViewShell.GetViewData().IsThemedCursor(); |
727 | 0 | rViewShell.SetActivePointer( bIsThemed ? PointerStyle::FatCross : PointerStyle::Arrow ); //! in Gridwin? |
728 | 0 | } |
729 | 0 | } |
730 | | |
731 | | bool FuDraw::IsEditingANote() const |
732 | 0 | { |
733 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
734 | 0 | const size_t backval=rMarkList.GetMarkCount(); |
735 | 0 | for (size_t nlv1=0; nlv1<backval; ++nlv1) |
736 | 0 | { |
737 | 0 | SdrObject* pObj = rMarkList.GetMark( nlv1 )->GetMarkedSdrObj(); |
738 | 0 | if ( ScDrawLayer::IsNoteCaption( pObj ) ) |
739 | 0 | { |
740 | 0 | return true; |
741 | 0 | } |
742 | 0 | } |
743 | 0 | return false; |
744 | 0 | } |
745 | | |
746 | | bool FuDraw::IsSizingOrMovingNote( const MouseEvent& rMEvt ) const |
747 | 0 | { |
748 | 0 | bool bIsSizingOrMoving = false; |
749 | 0 | if ( rMEvt.IsLeft() ) |
750 | 0 | { |
751 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
752 | 0 | if(rMarkList.GetMarkCount() == 1) |
753 | 0 | { |
754 | 0 | SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); |
755 | 0 | if ( ScDrawLayer::IsNoteCaption( pObj ) ) |
756 | 0 | { |
757 | 0 | Point aMPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() ); |
758 | 0 | bIsSizingOrMoving = |
759 | 0 | pView->PickHandle( aMPos ) || // handles to resize the note |
760 | 0 | pView->IsTextEditFrameHit( aMPos ); // frame for moving the note |
761 | 0 | } |
762 | 0 | } |
763 | 0 | } |
764 | 0 | return bIsSizingOrMoving; |
765 | 0 | } |
766 | | |
767 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |