/src/libreoffice/sd/source/ui/func/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 <sal/config.h> |
21 | | |
22 | | #include <vcl/svapp.hxx> |
23 | | #include <vcl/ptrstyle.hxx> |
24 | | #include <editeng/flditem.hxx> |
25 | | #include <svx/svdogrp.hxx> |
26 | | #include <tools/urlobj.hxx> |
27 | | #include <vcl/help.hxx> |
28 | | #include <svx/bmpmask.hxx> |
29 | | #include <svx/svdotext.hxx> |
30 | | #include <svx/ImageMapInfo.hxx> |
31 | | #include <sfx2/dispatch.hxx> |
32 | | #include <sfx2/bindings.hxx> |
33 | | #include <sfx2/sfxhelp.hxx> |
34 | | #include <svx/svdpagv.hxx> |
35 | | #include <vcl/imapobj.hxx> |
36 | | #include <svx/svxids.hrc> |
37 | | #include <svx/obj3d.hxx> |
38 | | #include <svx/scene3d.hxx> |
39 | | #include <sfx2/viewfrm.hxx> |
40 | | |
41 | | #include <strings.hrc> |
42 | | |
43 | | |
44 | | #include <sdmod.hxx> |
45 | | #include <fudraw.hxx> |
46 | | #include <ViewShell.hxx> |
47 | | #include <FrameView.hxx> |
48 | | #include <View.hxx> |
49 | | #include <Window.hxx> |
50 | | #include <drawdoc.hxx> |
51 | | #include <DrawDocShell.hxx> |
52 | | #include <sdresid.hxx> |
53 | | #include <fusel.hxx> |
54 | | #include <vcl/weld/MessageDialog.hxx> |
55 | | #include <vcl/weld/WaitObject.hxx> |
56 | | #include <svx/sdrhittesthelper.hxx> |
57 | | |
58 | | using namespace ::com::sun::star; |
59 | | |
60 | | namespace sd { |
61 | | |
62 | | |
63 | | /** |
64 | | * Base-class for all drawmodul-specific functions |
65 | | */ |
66 | | FuDraw::FuDraw(ViewShell& rViewSh, ::sd::Window* pWin, ::sd::View* pView, |
67 | | SdDrawDocument& rDoc, SfxRequest& rReq) |
68 | 0 | : FuPoor(rViewSh, pWin, pView, rDoc, rReq) |
69 | 0 | , aNewPointer(PointerStyle::Arrow) |
70 | 0 | , aOldPointer(PointerStyle::Arrow) |
71 | 0 | , bMBDown(false) |
72 | 0 | , bDragHelpLine(false) |
73 | 0 | , nHelpLine(0) |
74 | 0 | , bPermanent(false) |
75 | 0 | { |
76 | 0 | } |
77 | | |
78 | | FuDraw::~FuDraw() |
79 | 0 | { |
80 | 0 | mpView->BrkAction(); |
81 | 0 | } |
82 | | |
83 | | |
84 | | /** |
85 | | * Code shared by MouseButtonDown and MouseMove |
86 | | */ |
87 | | void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed) |
88 | 0 | { |
89 | 0 | FrameView* pFrameView = mrViewShell.GetFrameView(); |
90 | 0 | bool bGridSnap = pFrameView->IsGridSnap(); |
91 | 0 | bGridSnap = (bSnapModPressed != bGridSnap); |
92 | |
|
93 | 0 | if (mpView->IsGridSnap() != bGridSnap) |
94 | 0 | mpView->SetGridSnap(bGridSnap); |
95 | |
|
96 | 0 | bool bBordSnap = pFrameView->IsBordSnap(); |
97 | 0 | bBordSnap = (bSnapModPressed != bBordSnap); |
98 | |
|
99 | 0 | if (mpView->IsBordSnap() != bBordSnap) |
100 | 0 | mpView->SetBordSnap(bBordSnap); |
101 | |
|
102 | 0 | bool bHlplSnap = pFrameView->IsHlplSnap(); |
103 | 0 | bHlplSnap = (bSnapModPressed != bHlplSnap); |
104 | |
|
105 | 0 | if (mpView->IsHlplSnap() != bHlplSnap) |
106 | 0 | mpView->SetHlplSnap(bHlplSnap); |
107 | |
|
108 | 0 | bool bOFrmSnap = pFrameView->IsOFrmSnap(); |
109 | 0 | bOFrmSnap = (bSnapModPressed != bOFrmSnap); |
110 | |
|
111 | 0 | if (mpView->IsOFrmSnap() != bOFrmSnap) |
112 | 0 | mpView->SetOFrmSnap(bOFrmSnap); |
113 | |
|
114 | 0 | bool bOPntSnap = pFrameView->IsOPntSnap(); |
115 | 0 | bOPntSnap = (bSnapModPressed != bOPntSnap); |
116 | |
|
117 | 0 | if (mpView->IsOPntSnap() != bOPntSnap) |
118 | 0 | mpView->SetOPntSnap(bOPntSnap); |
119 | |
|
120 | 0 | bool bOConSnap = pFrameView->IsOConSnap(); |
121 | 0 | bOConSnap = (bSnapModPressed != bOConSnap); |
122 | |
|
123 | 0 | if (mpView->IsOConSnap() != bOConSnap) |
124 | 0 | mpView->SetOConSnap(bOConSnap); |
125 | |
|
126 | 0 | bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled(); |
127 | |
|
128 | 0 | if (mpView->IsAngleSnapEnabled() != bAngleSnap) |
129 | 0 | mpView->SetAngleSnapEnabled(bAngleSnap); |
130 | |
|
131 | 0 | bool bCenter = rMEvt.IsMod2(); |
132 | |
|
133 | 0 | if ( mpView->IsCreate1stPointAsCenter() != bCenter || |
134 | 0 | mpView->IsResizeAtCenter() != bCenter ) |
135 | 0 | { |
136 | 0 | mpView->SetCreate1stPointAsCenter(bCenter); |
137 | 0 | mpView->SetResizeAtCenter(bCenter); |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | | |
142 | | bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt) |
143 | 0 | { |
144 | | // remember button state for creation of own MouseEvents |
145 | 0 | SetMouseButtonCode(rMEvt.GetButtons()); |
146 | |
|
147 | 0 | bool bReturn = false; |
148 | 0 | bDragHelpLine = false; |
149 | 0 | aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); |
150 | |
|
151 | 0 | if ( rMEvt.IsLeft() ) |
152 | 0 | { |
153 | 0 | FrameView* pFrameView = mrViewShell.GetFrameView(); |
154 | |
|
155 | 0 | bool bOrtho = false; |
156 | |
|
157 | 0 | bool bRestricted = true; |
158 | |
|
159 | 0 | if (mpView->IsDragObj()) |
160 | 0 | { |
161 | | // object is dragged (move, resize,...) |
162 | 0 | const SdrHdl* pHdl = mpView->GetDragStat().GetHdl(); |
163 | |
|
164 | 0 | if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl())) |
165 | 0 | { |
166 | | // Move |
167 | 0 | bRestricted = false; |
168 | 0 | } |
169 | 0 | } |
170 | | |
171 | | // #i33136# |
172 | 0 | if(bRestricted && doConstructOrthogonal()) |
173 | 0 | { |
174 | | // Restrict movement: |
175 | | // rectangle->square, ellipse->circle, etc. |
176 | 0 | bOrtho = !rMEvt.IsShift(); |
177 | 0 | } |
178 | 0 | else |
179 | 0 | { |
180 | 0 | bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho(); |
181 | 0 | } |
182 | 0 | if (!mpView->IsSnapEnabled()) |
183 | 0 | mpView->SetSnapEnabled(true); |
184 | |
|
185 | 0 | bool bSnapModPressed = rMEvt.IsMod1(); |
186 | 0 | if (mpView->IsOrtho() != bOrtho) |
187 | 0 | mpView->SetOrtho(bOrtho); |
188 | |
|
189 | 0 | DoModifiers(rMEvt, bSnapModPressed); |
190 | |
|
191 | 0 | SdrPageView* pPV = nullptr; |
192 | 0 | sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); |
193 | | |
194 | | // look only for HelpLines when they are visible (!) |
195 | 0 | bool bHelpLine(false); |
196 | 0 | if(mpView->IsHlplVisible()) |
197 | 0 | bHelpLine = mpView->PickHelpLine(aMDPos, nHitLog, *mpWindow->GetOutDev(), nHelpLine, pPV); |
198 | 0 | bool bHitHdl = (mpView->PickHandle(aMDPos) != nullptr); |
199 | |
|
200 | 0 | if ( bHelpLine |
201 | 0 | && !mpView->IsCreateObj() |
202 | 0 | && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) ) |
203 | 0 | { |
204 | 0 | mpWindow->CaptureMouse(); |
205 | 0 | mpView->BegDragHelpLine(nHelpLine, pPV); |
206 | 0 | bDragHelpLine = mpView->IsDragHelpLine(); |
207 | 0 | bReturn = true; |
208 | 0 | } |
209 | 0 | } |
210 | 0 | ForcePointer(&rMEvt); |
211 | |
|
212 | 0 | return bReturn; |
213 | 0 | } |
214 | | |
215 | | bool FuDraw::MouseMove(const MouseEvent& rMEvt) |
216 | 0 | { |
217 | 0 | FrameView* pFrameView = mrViewShell.GetFrameView(); |
218 | 0 | Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); |
219 | |
|
220 | 0 | bool bOrtho = false; |
221 | 0 | bool bRestricted = true; |
222 | |
|
223 | 0 | if (mpView->IsDragObj()) |
224 | 0 | { |
225 | | // object is dragged (move, resize, ...) |
226 | 0 | const SdrHdl* pHdl = mpView->GetDragStat().GetHdl(); |
227 | |
|
228 | 0 | if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl())) |
229 | 0 | { |
230 | | // Move |
231 | 0 | bRestricted = false; |
232 | 0 | } |
233 | 0 | } |
234 | |
|
235 | 0 | if (mpView->IsAction()) |
236 | 0 | { |
237 | | // #i33136# and fdo#88339 |
238 | 0 | if(bRestricted && doConstructOrthogonal()) |
239 | 0 | { |
240 | | // Scale proportionally by default: |
241 | | // rectangle->square, ellipse->circle, images, etc. |
242 | 0 | bOrtho = !rMEvt.IsShift(); |
243 | 0 | } |
244 | 0 | else |
245 | 0 | { |
246 | 0 | bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho(); |
247 | 0 | } |
248 | |
|
249 | 0 | bool bSnapModPressed = rMEvt.IsMod2(); |
250 | 0 | mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); |
251 | |
|
252 | 0 | if (mpView->IsOrtho() != bOrtho) |
253 | 0 | mpView->SetOrtho(bOrtho); |
254 | 0 | DoModifiers(rMEvt, bSnapModPressed); |
255 | | |
256 | |
|
257 | 0 | if ( mpView->IsDragHelpLine() ) |
258 | 0 | mpView->MovDragHelpLine(aPos); |
259 | 0 | } |
260 | |
|
261 | 0 | bool bReturn = mpView->MouseMove(rMEvt, mpWindow->GetOutDev()); |
262 | |
|
263 | 0 | if (mpView->IsAction()) |
264 | 0 | { |
265 | | // Because the flag set back if necessary in MouseMove |
266 | 0 | if (mpView->IsOrtho() != bOrtho) |
267 | 0 | mpView->SetOrtho(bOrtho); |
268 | 0 | } |
269 | |
|
270 | 0 | ForcePointer(&rMEvt); |
271 | |
|
272 | 0 | return bReturn; |
273 | 0 | } |
274 | | |
275 | | bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt) |
276 | 0 | { |
277 | 0 | if (mpView && mpView->IsDragHelpLine()) |
278 | 0 | mpView->EndDragHelpLine(); |
279 | |
|
280 | 0 | if ( bDragHelpLine ) |
281 | 0 | { |
282 | 0 | ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel()); |
283 | |
|
284 | 0 | if (mpView && !aOutputArea.Contains(rMEvt.GetPosPixel())) |
285 | 0 | mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine); |
286 | |
|
287 | 0 | mpWindow->ReleaseMouse(); |
288 | 0 | } |
289 | |
|
290 | 0 | if (mpView) |
291 | 0 | { |
292 | 0 | FrameView* pFrameView = mrViewShell.GetFrameView(); |
293 | 0 | mpView->SetOrtho( pFrameView->IsOrtho() ); |
294 | 0 | mpView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() ); |
295 | 0 | mpView->SetSnapEnabled(true); |
296 | 0 | mpView->SetCreate1stPointAsCenter(false); |
297 | 0 | mpView->SetResizeAtCenter(false); |
298 | 0 | mpView->SetDragWithCopy(pFrameView->IsDragWithCopy()); |
299 | 0 | mpView->SetGridSnap(pFrameView->IsGridSnap()); |
300 | 0 | mpView->SetBordSnap(pFrameView->IsBordSnap()); |
301 | 0 | mpView->SetHlplSnap(pFrameView->IsHlplSnap()); |
302 | 0 | mpView->SetOFrmSnap(pFrameView->IsOFrmSnap()); |
303 | 0 | mpView->SetOPntSnap(pFrameView->IsOPntSnap()); |
304 | 0 | mpView->SetOConSnap(pFrameView->IsOConSnap()); |
305 | 0 | } |
306 | |
|
307 | 0 | bIsInDragMode = false; |
308 | 0 | ForcePointer(&rMEvt); |
309 | 0 | FuPoor::MouseButtonUp(rMEvt); |
310 | |
|
311 | 0 | return false; |
312 | 0 | } |
313 | | |
314 | | /** |
315 | | * Process keyboard input |
316 | | * @returns sal_True if a KeyEvent is being processed, sal_False otherwise |
317 | | */ |
318 | | bool FuDraw::KeyInput(const KeyEvent& rKEvt) |
319 | 0 | { |
320 | 0 | bool bReturn = false; |
321 | 0 | const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); |
322 | |
|
323 | 0 | switch ( rKEvt.GetKeyCode().GetCode() ) |
324 | 0 | { |
325 | 0 | case KEY_ESCAPE: |
326 | 0 | { |
327 | 0 | bReturn = FuDraw::cancel(); |
328 | 0 | } |
329 | 0 | break; |
330 | | |
331 | 0 | case KEY_DELETE: |
332 | 0 | case KEY_BACKSPACE: |
333 | 0 | { |
334 | 0 | if (!mpDocSh->IsReadOnly()) |
335 | 0 | { |
336 | 0 | if (mpView->IsPresObjSelected(false, true, false, true)) |
337 | 0 | { |
338 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(), |
339 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
340 | 0 | SdResId(STR_ACTION_NOTPOSSIBLE))); |
341 | 0 | xInfoBox->run(); |
342 | 0 | } |
343 | 0 | else |
344 | 0 | { |
345 | | // wait-mousepointer while deleting object |
346 | 0 | weld::WaitObject aWait(mrViewShell.GetFrameWeld()); |
347 | | // delete object |
348 | 0 | mpView->DeleteMarked(); |
349 | 0 | } |
350 | 0 | } |
351 | 0 | bReturn = true; |
352 | 0 | } |
353 | 0 | break; |
354 | | |
355 | 0 | case KEY_TAB: |
356 | 0 | { |
357 | 0 | vcl::KeyCode aCode = rKEvt.GetKeyCode(); |
358 | |
|
359 | 0 | if ( !aCode.IsMod1() && !aCode.IsMod2() ) |
360 | 0 | { |
361 | | // Moved next line which was a bugfix itself into |
362 | | // the scope which really does the object selection travel |
363 | | // and thus is allowed to call SelectionHasChanged(). |
364 | | |
365 | | // Switch to FuSelect. |
366 | 0 | mrViewShell.GetViewFrame()->GetDispatcher()->Execute( |
367 | 0 | SID_OBJECT_SELECT, |
368 | 0 | SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); |
369 | | |
370 | | // changeover to the next object |
371 | 0 | if(!mpView->MarkNextObj( !aCode.IsShift() )) |
372 | 0 | { |
373 | | //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj(). |
374 | 0 | if ( mpView->HasMultipleMarkableObjects() && rMarkList.GetMarkCount() != 0 ) |
375 | 0 | { |
376 | | // No next object: go over open end and get first from |
377 | | // the other side |
378 | 0 | mpView->UnmarkAllObj(); |
379 | 0 | mpView->MarkNextObj(!aCode.IsShift()); |
380 | 0 | } |
381 | 0 | } |
382 | |
|
383 | 0 | if(rMarkList.GetMarkCount() != 0) |
384 | 0 | mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); |
385 | |
|
386 | 0 | bReturn = true; |
387 | 0 | } |
388 | 0 | } |
389 | 0 | break; |
390 | | |
391 | 0 | case KEY_END: |
392 | 0 | { |
393 | 0 | vcl::KeyCode aCode = rKEvt.GetKeyCode(); |
394 | |
|
395 | 0 | if ( aCode.IsMod1() ) |
396 | 0 | { |
397 | | // mark last object |
398 | 0 | mpView->UnmarkAllObj(); |
399 | 0 | mpView->MarkNextObj(); |
400 | |
|
401 | 0 | if(rMarkList.GetMarkCount() != 0) |
402 | 0 | mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); |
403 | |
|
404 | 0 | bReturn = true; |
405 | 0 | } |
406 | 0 | } |
407 | 0 | break; |
408 | | |
409 | 0 | case KEY_HOME: |
410 | 0 | { |
411 | 0 | vcl::KeyCode aCode = rKEvt.GetKeyCode(); |
412 | |
|
413 | 0 | if ( aCode.IsMod1() ) |
414 | 0 | { |
415 | | // mark first object |
416 | 0 | mpView->UnmarkAllObj(); |
417 | 0 | mpView->MarkNextObj(true); |
418 | |
|
419 | 0 | if(rMarkList.GetMarkCount() != 0) |
420 | 0 | mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); |
421 | |
|
422 | 0 | bReturn = true; |
423 | 0 | } |
424 | 0 | } |
425 | 0 | break; |
426 | | |
427 | 0 | default: |
428 | 0 | break; |
429 | 0 | } |
430 | | |
431 | 0 | if (!bReturn) |
432 | 0 | { |
433 | 0 | bReturn = FuPoor::KeyInput(rKEvt); |
434 | 0 | } |
435 | 0 | else |
436 | 0 | { |
437 | 0 | mpWindow->ReleaseMouse(); |
438 | 0 | } |
439 | |
|
440 | 0 | return bReturn; |
441 | 0 | } |
442 | | |
443 | | void FuDraw::Activate() |
444 | 0 | { |
445 | 0 | FuPoor::Activate(); |
446 | 0 | ForcePointer(); |
447 | 0 | } |
448 | | |
449 | | /** |
450 | | * Toggle mouse-pointer |
451 | | */ |
452 | | void FuDraw::ForcePointer(const MouseEvent* pMEvt) |
453 | 0 | { |
454 | 0 | Point aPnt; |
455 | 0 | sal_uInt16 nModifier = 0; |
456 | 0 | bool bLeftDown = false; |
457 | 0 | bool bDefPointer = true; |
458 | |
|
459 | 0 | if (pMEvt) |
460 | 0 | { |
461 | 0 | aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel()); |
462 | 0 | nModifier = pMEvt->GetModifier(); |
463 | 0 | bLeftDown = pMEvt->IsLeft(); |
464 | 0 | } |
465 | 0 | else |
466 | 0 | { |
467 | 0 | aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel()); |
468 | 0 | } |
469 | |
|
470 | 0 | if (mpView->IsDragObj()) |
471 | 0 | { |
472 | 0 | if (SdModule::get()->GetWaterCan() && !mpView->PickHandle(aPnt)) |
473 | 0 | { |
474 | | // water can mode |
475 | 0 | bDefPointer = false; |
476 | 0 | mpWindow->SetPointer(PointerStyle::Fill); |
477 | 0 | } |
478 | 0 | } |
479 | 0 | else |
480 | 0 | { |
481 | 0 | SdrHdl* pHdl = mpView->PickHandle(aPnt); |
482 | |
|
483 | 0 | if (SdModule::get()->GetWaterCan() && !pHdl) |
484 | 0 | { |
485 | | // water can mode |
486 | 0 | bDefPointer = false; |
487 | 0 | mpWindow->SetPointer(PointerStyle::Fill); |
488 | 0 | } |
489 | 0 | else if (!pHdl && |
490 | 0 | mrViewShell.GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId())) |
491 | 0 | { |
492 | | // pipette mode |
493 | 0 | SfxChildWindow* pWnd = mrViewShell.GetViewFrame()->GetChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()); |
494 | 0 | SvxBmpMask* pMask = pWnd ? static_cast<SvxBmpMask*>(pWnd->GetWindow()) : nullptr; |
495 | 0 | if (pMask && pMask->IsEyedropping()) |
496 | 0 | { |
497 | 0 | bDefPointer = false; |
498 | 0 | mpWindow->SetPointer(PointerStyle::RefHand); |
499 | 0 | } |
500 | 0 | } |
501 | 0 | else if (!mpView->IsAction()) |
502 | 0 | { |
503 | 0 | SdrObject* pObj = nullptr; |
504 | 0 | SdrPageView* pPV = nullptr; |
505 | 0 | SdrViewEvent aVEvt; |
506 | 0 | SdrHitKind eHit = SdrHitKind::NONE; |
507 | 0 | SdrDragMode eDragMode = mpView->GetDragMode(); |
508 | |
|
509 | 0 | if (pMEvt) |
510 | 0 | { |
511 | 0 | eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt); |
512 | 0 | } |
513 | |
|
514 | 0 | if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject)) |
515 | 0 | { |
516 | | // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode |
517 | | // Independent of the settings at Tools->Options->Draw "Objects always moveable" |
518 | | // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes |
519 | | // wouldn't be possible per default. |
520 | 0 | const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); |
521 | 0 | SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj(); |
522 | 0 | if (DynCastE3dObject(pObject) && (rMarkList.GetMarkCount() == 1)) |
523 | 0 | { |
524 | 0 | mpWindow->SetPointer(PointerStyle::Rotate); |
525 | 0 | bDefPointer = false; // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again |
526 | 0 | } |
527 | 0 | } |
528 | |
|
529 | 0 | if (eHit == SdrHitKind::NONE) |
530 | 0 | { |
531 | | // found nothing -> look after at the masterpage |
532 | 0 | pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER); |
533 | 0 | } |
534 | 0 | else if (eHit == SdrHitKind::UnmarkedObject) |
535 | 0 | { |
536 | 0 | pObj = aVEvt.mpObj; |
537 | 0 | } |
538 | 0 | else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) != nullptr) |
539 | 0 | { |
540 | 0 | SdrObjKind nSdrObjKind = aVEvt.mpObj->GetObjIdentifier(); |
541 | |
|
542 | 0 | if ( nSdrObjKind != SdrObjKind::Text && |
543 | 0 | nSdrObjKind != SdrObjKind::TitleText && |
544 | 0 | nSdrObjKind != SdrObjKind::OutlineText && |
545 | 0 | aVEvt.mpObj->IsEmptyPresObj() ) |
546 | 0 | { |
547 | 0 | pObj = nullptr; |
548 | 0 | bDefPointer = false; |
549 | 0 | mpWindow->SetPointer(PointerStyle::Arrow); |
550 | 0 | } |
551 | 0 | } |
552 | |
|
553 | 0 | if (pObj && pMEvt && !pMEvt->IsMod2() |
554 | 0 | && dynamic_cast<const FuSelection*>(this) != nullptr) |
555 | 0 | { |
556 | | // test for ImageMap |
557 | 0 | bDefPointer = !SetPointer(pObj, aPnt); |
558 | |
|
559 | 0 | if (bDefPointer |
560 | 0 | && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr |
561 | 0 | || DynCastE3dScene(pObj))) |
562 | 0 | { |
563 | | // take a glance into the group |
564 | 0 | pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, |
565 | 0 | SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP); |
566 | 0 | if (pObj) |
567 | 0 | bDefPointer = !SetPointer(pObj, aPnt); |
568 | 0 | } |
569 | 0 | } |
570 | 0 | } |
571 | 0 | } |
572 | |
|
573 | 0 | if (bDefPointer) |
574 | 0 | { |
575 | 0 | mpWindow->SetPointer(mpView->GetPreferredPointer( |
576 | 0 | aPnt, mpWindow->GetOutDev(), nModifier, bLeftDown)); |
577 | 0 | } |
578 | 0 | } |
579 | | |
580 | | /** |
581 | | * Set cursor to pointer when in clickable area of an ImageMap |
582 | | * |
583 | | * @return True when pointer was set |
584 | | */ |
585 | | bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos) |
586 | 0 | { |
587 | 0 | bool bImageMapInfo = SvxIMapInfo::GetIMapInfo(pObj) != nullptr; |
588 | |
|
589 | 0 | if (!bImageMapInfo) |
590 | 0 | return false; |
591 | | |
592 | 0 | const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers(); |
593 | 0 | double fHitLog(mpWindow->PixelToLogic(Size(HITPIX, 0)).Width()); |
594 | 0 | ::tools::Long n2HitLog(fHitLog * 2); |
595 | 0 | Point aHitPosR(rPos); |
596 | 0 | Point aHitPosL(rPos); |
597 | 0 | Point aHitPosT(rPos); |
598 | 0 | Point aHitPosB(rPos); |
599 | |
|
600 | 0 | aHitPosR.AdjustX(n2HitLog); |
601 | 0 | aHitPosL.AdjustX(-n2HitLog); |
602 | 0 | aHitPosT.AdjustY(n2HitLog); |
603 | 0 | aHitPosB.AdjustY(-n2HitLog); |
604 | |
|
605 | 0 | if (!pObj->IsClosedObj() |
606 | 0 | || (SdrObjectPrimitiveHit(*pObj, aHitPosR, {fHitLog, fHitLog}, *mpView->GetSdrPageView(), pVisiLayer, |
607 | 0 | false) |
608 | 0 | && SdrObjectPrimitiveHit(*pObj, aHitPosL, {fHitLog, fHitLog}, *mpView->GetSdrPageView(), |
609 | 0 | pVisiLayer, false) |
610 | 0 | && SdrObjectPrimitiveHit(*pObj, aHitPosT, {fHitLog, fHitLog}, *mpView->GetSdrPageView(), |
611 | 0 | pVisiLayer, false) |
612 | 0 | && SdrObjectPrimitiveHit(*pObj, aHitPosB, {fHitLog, fHitLog}, *mpView->GetSdrPageView(), |
613 | 0 | pVisiLayer, false))) |
614 | 0 | { |
615 | | // hit inside the object (without margin) or open object |
616 | 0 | if (SvxIMapInfo::GetHitIMapObject(pObj, rPos)) |
617 | 0 | { |
618 | 0 | mpWindow->SetPointer(PointerStyle::RefHand); |
619 | 0 | return true; |
620 | 0 | } |
621 | 0 | } |
622 | | |
623 | 0 | return false; |
624 | 0 | } |
625 | | |
626 | | /** |
627 | | * Response of doubleclick |
628 | | */ |
629 | | void FuDraw::DoubleClick(const MouseEvent& rMEvt) |
630 | 0 | { |
631 | 0 | sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); |
632 | |
|
633 | 0 | const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); |
634 | 0 | if ( rMarkList.GetMarkCount() != 0 ) |
635 | 0 | { |
636 | 0 | if (rMarkList.GetMarkCount() == 1) |
637 | 0 | { |
638 | 0 | SdrMark* pMark = rMarkList.GetMark(0); |
639 | 0 | SdrObject* pObj = pMark->GetMarkedSdrObj(); |
640 | |
|
641 | 0 | SdrInventor nInv = pObj->GetObjInventor(); |
642 | 0 | SdrObjKind nSdrObjKind = pObj->GetObjIdentifier(); |
643 | |
|
644 | 0 | bool bReadOnly = mpDocSh->IsReadOnly(); |
645 | 0 | if (!bReadOnly) |
646 | 0 | { |
647 | 0 | SfxViewShell* pViewShell = mrViewShell.GetViewShell(); |
648 | 0 | if (pViewShell) |
649 | 0 | { |
650 | 0 | bReadOnly = pViewShell->IsLokReadOnlyView(); |
651 | 0 | } |
652 | 0 | } |
653 | |
|
654 | 0 | if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2 |
655 | 0 | && !bReadOnly) |
656 | 0 | { |
657 | | // activate OLE-object |
658 | 0 | SfxInt16Item aItem(SID_OBJECT, 0); |
659 | 0 | mrViewShell.GetViewFrame()-> |
660 | 0 | GetDispatcher()->ExecuteList(SID_OBJECT, |
661 | 0 | SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, |
662 | 0 | { &aItem }); |
663 | 0 | } |
664 | 0 | else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Graphic |
665 | 0 | && pObj->IsEmptyPresObj() && !bReadOnly) |
666 | 0 | { |
667 | 0 | mrViewShell.GetViewFrame()-> |
668 | 0 | GetDispatcher()->Execute( SID_INSERT_GRAPHIC, |
669 | 0 | SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); |
670 | 0 | } |
671 | 0 | else if ( ( DynCastSdrTextObj( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr ) && |
672 | 0 | !SdModule::get()->GetWaterCan() && |
673 | 0 | mrViewShell.GetFrameView()->IsDoubleClickTextEdit() && |
674 | 0 | !bReadOnly) |
675 | 0 | { |
676 | 0 | SfxUInt16Item aItem(SID_TEXTEDIT, 2); |
677 | 0 | mrViewShell.GetViewFrame()->GetDispatcher()->ExecuteList( |
678 | 0 | SID_TEXTEDIT, |
679 | 0 | SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, |
680 | 0 | { &aItem }); |
681 | 0 | } |
682 | 0 | else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Group) |
683 | 0 | { |
684 | | // hit group -> select subobject |
685 | 0 | mpView->UnMarkAll(); |
686 | 0 | mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true); |
687 | 0 | } |
688 | 0 | } |
689 | 0 | } |
690 | 0 | else |
691 | 0 | mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); |
692 | 0 | } |
693 | | |
694 | | bool FuDraw::RequestHelp(const HelpEvent& rHEvt) |
695 | 0 | { |
696 | 0 | bool bReturn = false; |
697 | |
|
698 | 0 | if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled()) |
699 | 0 | { |
700 | 0 | SdrViewEvent aVEvt; |
701 | |
|
702 | 0 | MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT); |
703 | |
|
704 | 0 | SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); |
705 | |
|
706 | 0 | SdrObject* pObj = aVEvt.mpObj; |
707 | |
|
708 | 0 | if (eHit != SdrHitKind::NONE && pObj != nullptr) |
709 | 0 | { |
710 | 0 | Point aPosPixel = rHEvt.GetMousePosPixel(); |
711 | |
|
712 | 0 | bReturn = SetHelpText(pObj, aPosPixel, aVEvt); |
713 | |
|
714 | 0 | if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || DynCastE3dScene(pObj))) |
715 | 0 | { |
716 | | // take a glance into the group |
717 | 0 | SdrPageView* pPV = nullptr; |
718 | |
|
719 | 0 | Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel))); |
720 | |
|
721 | 0 | pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP); |
722 | 0 | if (pObj) |
723 | 0 | bReturn = SetHelpText(pObj, aPosPixel, aVEvt); |
724 | 0 | } |
725 | 0 | } |
726 | 0 | } |
727 | |
|
728 | 0 | if (!bReturn) |
729 | 0 | { |
730 | 0 | bReturn = FuPoor::RequestHelp(rHEvt); |
731 | 0 | } |
732 | |
|
733 | 0 | if (!bReturn) |
734 | 0 | bReturn = mpView->RequestHelp(rHEvt); |
735 | |
|
736 | 0 | return bReturn; |
737 | 0 | } |
738 | | |
739 | | bool FuDraw::SetHelpText(const SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt) |
740 | 0 | { |
741 | 0 | OUString aHelpText; |
742 | 0 | Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel))); |
743 | 0 | IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, aPos); |
744 | |
|
745 | 0 | if (!rVEvt.mpURLField && !pIMapObj) |
746 | 0 | return false; |
747 | | |
748 | 0 | OUString aURL; |
749 | 0 | if (rVEvt.mpURLField) |
750 | 0 | aURL = INetURLObject::decode(rVEvt.mpURLField->GetURL(), |
751 | 0 | INetURLObject::DecodeMechanism::WithCharset); |
752 | 0 | else if (pIMapObj) |
753 | 0 | { |
754 | 0 | aURL = pIMapObj->GetAltText() + |
755 | 0 | " (" + |
756 | 0 | INetURLObject::decode(pIMapObj->GetURL(), |
757 | 0 | INetURLObject::DecodeMechanism::WithCharset) + |
758 | 0 | ")"; |
759 | 0 | } |
760 | 0 | else |
761 | 0 | return false; |
762 | | |
763 | 0 | aHelpText = SfxHelp::GetURLHelpText(aURL); |
764 | |
|
765 | 0 | if (aHelpText.isEmpty()) |
766 | 0 | return false; |
767 | | |
768 | 0 | ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect()); |
769 | 0 | ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()), |
770 | 0 | mpWindow->OutputToScreenPixel(aLogicPix.BottomRight())); |
771 | |
|
772 | 0 | if (Help::IsBalloonHelpEnabled()) |
773 | 0 | Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText); |
774 | 0 | else if (Help::IsQuickHelpEnabled()) |
775 | 0 | Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText); |
776 | |
|
777 | 0 | return true; |
778 | 0 | } |
779 | | |
780 | | /** is called when the current function should be aborted. <p> |
781 | | This is used when a function gets a KEY_ESCAPE but can also |
782 | | be called directly. |
783 | | |
784 | | @returns true if an active function was aborted |
785 | | */ |
786 | | bool FuDraw::cancel() |
787 | 0 | { |
788 | 0 | bool bReturn = false; |
789 | 0 | const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); |
790 | |
|
791 | 0 | if ( mpView->IsAction() ) |
792 | 0 | { |
793 | 0 | mpView->BrkAction(); |
794 | 0 | bReturn = true; |
795 | 0 | } |
796 | 0 | else if ( mpView->IsTextEdit() ) |
797 | 0 | { |
798 | 0 | mpView->SdrEndTextEdit(); |
799 | 0 | bReturn = true; |
800 | |
|
801 | 0 | SfxBindings& rBindings = mrViewShell.GetViewFrame()->GetBindings(); |
802 | 0 | rBindings.Invalidate( SID_DEC_INDENT ); |
803 | 0 | rBindings.Invalidate( SID_INC_INDENT ); |
804 | 0 | rBindings.Invalidate( SID_PARASPACE_INCREASE ); |
805 | 0 | rBindings.Invalidate( SID_PARASPACE_DECREASE ); |
806 | 0 | } |
807 | 0 | else if ( rMarkList.GetMarkCount() != 0 ) |
808 | 0 | { |
809 | 0 | const SdrHdlList& rHdlList = mpView->GetHdlList(); |
810 | 0 | SdrHdl* pHdl = rHdlList.GetFocusHdl(); |
811 | |
|
812 | 0 | if(pHdl) |
813 | 0 | { |
814 | 0 | const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl(); |
815 | 0 | } |
816 | 0 | else |
817 | 0 | { |
818 | 0 | mpView->UnmarkAll(); |
819 | 0 | } |
820 | | |
821 | | // Switch to FuSelect. |
822 | 0 | mrViewShell.GetViewFrame()->GetDispatcher()->Execute( |
823 | 0 | SID_OBJECT_SELECT, |
824 | 0 | SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); |
825 | |
|
826 | 0 | bReturn = true; |
827 | 0 | } |
828 | |
|
829 | 0 | return bReturn; |
830 | 0 | } |
831 | | |
832 | | } // end of namespace sd |
833 | | |
834 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |