/src/libreoffice/svx/source/dialog/graphctl.cxx
Line | Count | Source (jump to first uncovered line) |
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 <config_wasm_strip.h> |
21 | | |
22 | | #include <svl/itempool.hxx> |
23 | | #include <vcl/settings.hxx> |
24 | | #include <vcl/ptrstyle.hxx> |
25 | | #include <vcl/svapp.hxx> |
26 | | |
27 | | #include <svx/graphctl.hxx> |
28 | | #include <svx/sdr/overlay/overlaymanager.hxx> |
29 | | #include <GraphCtlAccessibleContext.hxx> |
30 | | #include <svx/svxids.hrc> |
31 | | #include <svx/svdpage.hxx> |
32 | | #include <svx/sdrpaintwindow.hxx> |
33 | | |
34 | | void GraphCtrlUserCall::Changed( const SdrObject& rObj, SdrUserCallType eType, const tools::Rectangle& /*rOldBoundRect*/ ) |
35 | 0 | { |
36 | 0 | switch( eType ) |
37 | 0 | { |
38 | 0 | case SdrUserCallType::MoveOnly: |
39 | 0 | case SdrUserCallType::Resize: |
40 | 0 | rWin.SdrObjChanged( rObj ); |
41 | 0 | break; |
42 | | |
43 | 0 | case SdrUserCallType::Inserted: |
44 | 0 | rWin.SdrObjCreated( rObj ); |
45 | 0 | break; |
46 | | |
47 | 0 | default: |
48 | 0 | break; |
49 | 0 | } |
50 | 0 | rWin.QueueIdleUpdate(); |
51 | 0 | } |
52 | | |
53 | | GraphCtrl::GraphCtrl(weld::Dialog* pDialog) |
54 | 0 | : aUpdateIdle("svx GraphCtrl Update") |
55 | 0 | , aMap100(MapUnit::Map100thMM) |
56 | 0 | , eObjKind(SdrObjKind::NONE) |
57 | 0 | , nPolyEdit(0) |
58 | 0 | , bEditMode(false) |
59 | 0 | , mbSdrMode(false) |
60 | 0 | , mbInIdleUpdate(false) |
61 | 0 | , mpDialog(pDialog) |
62 | 0 | { |
63 | 0 | pUserCall.reset(new GraphCtrlUserCall( *this )); |
64 | 0 | aUpdateIdle.SetPriority( TaskPriority::LOWEST ); |
65 | 0 | aUpdateIdle.SetInvokeHandler( LINK( this, GraphCtrl, UpdateHdl ) ); |
66 | 0 | aUpdateIdle.Start(); |
67 | 0 | } |
68 | | |
69 | | void GraphCtrl::SetDrawingArea(weld::DrawingArea* pDrawingArea) |
70 | 0 | { |
71 | 0 | weld::CustomWidgetController::SetDrawingArea(pDrawingArea); |
72 | 0 | EnableRTL(false); |
73 | 0 | } |
74 | | |
75 | | GraphCtrl::~GraphCtrl() |
76 | 0 | { |
77 | 0 | aUpdateIdle.Stop(); |
78 | |
|
79 | 0 | #if !ENABLE_WASM_STRIP_ACCESSIBILITY |
80 | 0 | if( mpAccContext.is() ) |
81 | 0 | { |
82 | 0 | mpAccContext->disposing(); |
83 | 0 | mpAccContext.clear(); |
84 | 0 | } |
85 | 0 | #endif |
86 | |
|
87 | 0 | pView.reset(); |
88 | 0 | pModel.reset(); |
89 | 0 | pUserCall.reset(); |
90 | 0 | } |
91 | | |
92 | | void GraphCtrl::SetSdrMode(bool bSdrMode) |
93 | 0 | { |
94 | 0 | mbSdrMode = bSdrMode; |
95 | |
|
96 | 0 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
97 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
98 | 0 | rDevice.SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) ); |
99 | 0 | xVD->SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) ); |
100 | 0 | rDevice.SetMapMode( aMap100 ); |
101 | 0 | xVD->SetMapMode( aMap100 ); |
102 | |
|
103 | 0 | pView.reset(); |
104 | 0 | pModel.reset(); |
105 | |
|
106 | 0 | if ( mbSdrMode ) |
107 | 0 | InitSdrModel(); |
108 | |
|
109 | 0 | QueueIdleUpdate(); |
110 | 0 | } |
111 | | |
112 | | void GraphCtrl::InitSdrModel() |
113 | 0 | { |
114 | 0 | SolarMutexGuard aGuard; |
115 | |
|
116 | 0 | rtl::Reference<SdrPage> pPage; |
117 | | |
118 | | // destroy old junk |
119 | 0 | pView.reset(); |
120 | 0 | pModel.reset(); |
121 | | |
122 | | // Creating a Model |
123 | 0 | pModel.reset(new SdrModel(nullptr, nullptr, true)); |
124 | 0 | pModel->SetScaleUnit(aMap100.GetMapUnit()); |
125 | 0 | pModel->SetDefaultFontHeight( 500 ); |
126 | |
|
127 | 0 | pPage = new SdrPage( *pModel ); |
128 | |
|
129 | 0 | pPage->SetSize( aGraphSize ); |
130 | 0 | pPage->SetBorder( 0, 0, 0, 0 ); |
131 | 0 | pModel->InsertPage( pPage.get() ); |
132 | 0 | pModel->SetChanged( false ); |
133 | | |
134 | | // Creating a View |
135 | 0 | pView.reset(new GraphCtrlView(*pModel, this)); |
136 | 0 | pView->SetWorkArea( tools::Rectangle( Point(), aGraphSize ) ); |
137 | 0 | pView->EnableExtendedMouseEventDispatcher( true ); |
138 | 0 | pView->ShowSdrPage(pView->GetModel().GetPage(0)); |
139 | 0 | pView->SetFrameDragSingles(); |
140 | 0 | pView->SetMarkedPointsSmooth( SdrPathSmoothKind::Symmetric ); |
141 | 0 | pView->SetEditMode(); |
142 | | |
143 | | // #i72889# set needed flags |
144 | 0 | pView->SetPageDecorationAllowed(false); |
145 | 0 | pView->SetMasterPageVisualizationAllowed(false); |
146 | 0 | pView->SetBufferedOutputAllowed(true); |
147 | 0 | pView->SetBufferedOverlayAllowed(true); |
148 | |
|
149 | 0 | #if !ENABLE_WASM_STRIP_ACCESSIBILITY |
150 | | // Tell the accessibility object about the changes. |
151 | 0 | if (mpAccContext.is()) |
152 | 0 | mpAccContext->setModelAndView (pModel.get(), pView.get()); |
153 | 0 | #endif |
154 | 0 | } |
155 | | |
156 | | void GraphCtrl::SetGraphic( const Graphic& rGraphic, bool bNewModel ) |
157 | 0 | { |
158 | 0 | aGraphic = rGraphic; |
159 | 0 | xVD->SetOutputSizePixel(Size(0, 0)); //force redraw |
160 | |
|
161 | 0 | if ( aGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel ) |
162 | 0 | aGraphSize = Application::GetDefaultDevice()->PixelToLogic( aGraphic.GetPrefSize(), aMap100 ); |
163 | 0 | else |
164 | 0 | aGraphSize = OutputDevice::LogicToLogic( aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), aMap100 ); |
165 | |
|
166 | 0 | if ( mbSdrMode && bNewModel ) |
167 | 0 | InitSdrModel(); |
168 | |
|
169 | 0 | aGraphSizeLink.Call( this ); |
170 | |
|
171 | 0 | Resize(); |
172 | |
|
173 | 0 | Invalidate(); |
174 | 0 | QueueIdleUpdate(); |
175 | 0 | } |
176 | | |
177 | | void GraphCtrl::GraphicToVD() |
178 | 0 | { |
179 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
180 | 0 | xVD->SetOutputSizePixel(GetOutputSizePixel()); |
181 | 0 | xVD->SetBackground(rDevice.GetBackground()); |
182 | 0 | xVD->Erase(); |
183 | 0 | const bool bGraphicValid(GraphicType::NONE != aGraphic.GetType()); |
184 | 0 | if (bGraphicValid) |
185 | 0 | aGraphic.Draw(*xVD, Point(), aGraphSize); |
186 | 0 | } |
187 | | |
188 | | void GraphCtrl::Resize() |
189 | 0 | { |
190 | 0 | weld::CustomWidgetController::Resize(); |
191 | |
|
192 | 0 | if (aGraphSize.Width() && aGraphSize.Height()) |
193 | 0 | { |
194 | 0 | MapMode aDisplayMap( aMap100 ); |
195 | 0 | Point aNewPos; |
196 | 0 | Size aNewSize; |
197 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
198 | 0 | const Size aWinSize = rDevice.PixelToLogic( GetOutputSizePixel(), aDisplayMap ); |
199 | 0 | const tools::Long nWidth = aWinSize.Width(); |
200 | 0 | const tools::Long nHeight = aWinSize.Height(); |
201 | 0 | double fGrfWH = static_cast<double>(aGraphSize.Width()) / aGraphSize.Height(); |
202 | 0 | double fWinWH = static_cast<double>(nWidth) / nHeight; |
203 | | |
204 | | // Adapt Bitmap to Thumb size |
205 | 0 | if ( fGrfWH < fWinWH) |
206 | 0 | { |
207 | 0 | aNewSize.setWidth( static_cast<tools::Long>( static_cast<double>(nHeight) * fGrfWH ) ); |
208 | 0 | aNewSize.setHeight( nHeight ); |
209 | 0 | } |
210 | 0 | else |
211 | 0 | { |
212 | 0 | aNewSize.setWidth( nWidth ); |
213 | 0 | aNewSize.setHeight( static_cast<tools::Long>( static_cast<double>(nWidth) / fGrfWH ) ); |
214 | 0 | } |
215 | |
|
216 | 0 | aNewPos.setX( ( nWidth - aNewSize.Width() ) >> 1 ); |
217 | 0 | aNewPos.setY( ( nHeight - aNewSize.Height() ) >> 1 ); |
218 | | |
219 | | // Implementing MapMode for Engine |
220 | 0 | aDisplayMap.SetScaleX( Fraction( aNewSize.Width(), aGraphSize.Width() ) ); |
221 | 0 | aDisplayMap.SetScaleY( Fraction( aNewSize.Height(), aGraphSize.Height() ) ); |
222 | |
|
223 | 0 | aDisplayMap.SetOrigin( OutputDevice::LogicToLogic( aNewPos, aMap100, aDisplayMap ) ); |
224 | 0 | rDevice.SetMapMode( aDisplayMap ); |
225 | 0 | xVD->SetMapMode( aDisplayMap ); |
226 | 0 | } |
227 | |
|
228 | 0 | Invalidate(); |
229 | 0 | } |
230 | | |
231 | | void GraphCtrl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) |
232 | 0 | { |
233 | | // #i72889# used split repaint to be able to paint an own background |
234 | | // even to the buffered view |
235 | 0 | const bool bGraphicValid(GraphicType::NONE != aGraphic.GetType()); |
236 | |
|
237 | 0 | if (GetOutputSizePixel() != xVD->GetOutputSizePixel()) |
238 | 0 | GraphicToVD(); |
239 | |
|
240 | 0 | if (mbSdrMode) |
241 | 0 | { |
242 | 0 | SdrPaintWindow* pPaintWindow = pView->BeginCompleteRedraw(&rRenderContext); |
243 | 0 | pPaintWindow->SetOutputToWindow(true); |
244 | |
|
245 | 0 | if (bGraphicValid) |
246 | 0 | { |
247 | 0 | vcl::RenderContext& rTarget = pPaintWindow->GetTargetOutputDevice(); |
248 | |
|
249 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
250 | 0 | rTarget.SetBackground(rDevice.GetBackground()); |
251 | 0 | rTarget.Erase(); |
252 | |
|
253 | 0 | rTarget.DrawOutDev(Point(), xVD->GetOutputSize(), Point(), xVD->GetOutputSize(), *xVD); |
254 | 0 | } |
255 | |
|
256 | 0 | const vcl::Region aRepaintRegion(rRect); |
257 | 0 | pView->DoCompleteRedraw(*pPaintWindow, aRepaintRegion); |
258 | 0 | pView->EndCompleteRedraw(*pPaintWindow, true); |
259 | 0 | } |
260 | 0 | else |
261 | 0 | { |
262 | | // #i73381# in non-SdrMode, paint to local directly |
263 | 0 | rRenderContext.DrawOutDev(rRect.TopLeft(), rRect.GetSize(), |
264 | 0 | rRect.TopLeft(), rRect.GetSize(), |
265 | 0 | *xVD); |
266 | 0 | } |
267 | 0 | } |
268 | | |
269 | | void GraphCtrl::SdrObjChanged( const SdrObject& ) |
270 | 0 | { |
271 | 0 | QueueIdleUpdate(); |
272 | 0 | } |
273 | | |
274 | | void GraphCtrl::SdrObjCreated( const SdrObject& ) |
275 | 0 | { |
276 | 0 | QueueIdleUpdate(); |
277 | 0 | } |
278 | | |
279 | | void GraphCtrl::MarkListHasChanged() |
280 | 0 | { |
281 | 0 | QueueIdleUpdate(); |
282 | 0 | } |
283 | | |
284 | | bool GraphCtrl::KeyInput( const KeyEvent& rKEvt ) |
285 | 0 | { |
286 | 0 | vcl::KeyCode aCode( rKEvt.GetKeyCode() ); |
287 | 0 | bool bProc = false; |
288 | |
|
289 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
290 | |
|
291 | 0 | switch ( aCode.GetCode() ) |
292 | 0 | { |
293 | 0 | case KEY_DELETE: |
294 | 0 | case KEY_BACKSPACE: |
295 | 0 | { |
296 | 0 | if ( mbSdrMode ) |
297 | 0 | { |
298 | 0 | pView->DeleteMarked(); |
299 | 0 | bProc = true; |
300 | 0 | } |
301 | 0 | } |
302 | 0 | break; |
303 | | |
304 | 0 | case KEY_ESCAPE: |
305 | 0 | { |
306 | 0 | if ( mbSdrMode ) |
307 | 0 | { |
308 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
309 | 0 | if ( pView->IsAction() ) |
310 | 0 | { |
311 | 0 | pView->BrkAction(); |
312 | 0 | bProc = true; |
313 | 0 | } |
314 | 0 | else if ( rMarkList.GetMarkCount() != 0 ) |
315 | 0 | { |
316 | 0 | pView->UnmarkAllObj(); |
317 | 0 | bProc = true; |
318 | 0 | } |
319 | 0 | } |
320 | 0 | } |
321 | 0 | break; |
322 | | |
323 | 0 | case KEY_F11: |
324 | 0 | case KEY_TAB: |
325 | 0 | { |
326 | 0 | if( mbSdrMode ) |
327 | 0 | { |
328 | 0 | if( !aCode.IsMod1() && !aCode.IsMod2() ) |
329 | 0 | { |
330 | 0 | bool bForward = !aCode.IsShift(); |
331 | | // select next object |
332 | 0 | if ( ! pView->MarkNextObj( bForward )) |
333 | 0 | { |
334 | | // At first or last object. Cycle to the other end |
335 | | // of the list. |
336 | 0 | pView->UnmarkAllObj(); |
337 | 0 | pView->MarkNextObj (bForward); |
338 | 0 | } |
339 | 0 | bProc = true; |
340 | 0 | } |
341 | 0 | else if(aCode.IsMod1()) |
342 | 0 | { |
343 | | // select next handle |
344 | 0 | const SdrHdlList& rHdlList = pView->GetHdlList(); |
345 | 0 | bool bForward(!aCode.IsShift()); |
346 | |
|
347 | 0 | const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward); |
348 | |
|
349 | 0 | bProc = true; |
350 | 0 | } |
351 | 0 | } |
352 | 0 | } |
353 | 0 | break; |
354 | | |
355 | 0 | case KEY_END: |
356 | 0 | { |
357 | |
|
358 | 0 | if ( aCode.IsMod1() ) |
359 | 0 | { |
360 | | // mark last object |
361 | 0 | pView->UnmarkAllObj(); |
362 | 0 | pView->MarkNextObj(); |
363 | |
|
364 | 0 | bProc = true; |
365 | 0 | } |
366 | 0 | } |
367 | 0 | break; |
368 | | |
369 | 0 | case KEY_HOME: |
370 | 0 | { |
371 | 0 | if ( aCode.IsMod1() ) |
372 | 0 | { |
373 | 0 | pView->UnmarkAllObj(); |
374 | 0 | pView->MarkNextObj(true); |
375 | |
|
376 | 0 | bProc = true; |
377 | 0 | } |
378 | 0 | } |
379 | 0 | break; |
380 | | |
381 | 0 | case KEY_UP: |
382 | 0 | case KEY_DOWN: |
383 | 0 | case KEY_LEFT: |
384 | 0 | case KEY_RIGHT: |
385 | 0 | { |
386 | 0 | tools::Long nX = 0; |
387 | 0 | tools::Long nY = 0; |
388 | |
|
389 | 0 | if (aCode.GetCode() == KEY_UP) |
390 | 0 | { |
391 | | // Scroll up |
392 | 0 | nX = 0; |
393 | 0 | nY =-1; |
394 | 0 | } |
395 | 0 | else if (aCode.GetCode() == KEY_DOWN) |
396 | 0 | { |
397 | | // Scroll down |
398 | 0 | nX = 0; |
399 | 0 | nY = 1; |
400 | 0 | } |
401 | 0 | else if (aCode.GetCode() == KEY_LEFT) |
402 | 0 | { |
403 | | // Scroll left |
404 | 0 | nX =-1; |
405 | 0 | nY = 0; |
406 | 0 | } |
407 | 0 | else if (aCode.GetCode() == KEY_RIGHT) |
408 | 0 | { |
409 | | // Scroll right |
410 | 0 | nX = 1; |
411 | 0 | nY = 0; |
412 | 0 | } |
413 | |
|
414 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
415 | 0 | if (rMarkList.GetMarkCount() != 0 && !aCode.IsMod1() ) |
416 | 0 | { |
417 | 0 | if(aCode.IsMod2()) |
418 | 0 | { |
419 | | // move in 1 pixel distance |
420 | 0 | Size aLogicSizeOnePixel = rDevice.PixelToLogic(Size(1,1)); |
421 | 0 | nX *= aLogicSizeOnePixel.Width(); |
422 | 0 | nY *= aLogicSizeOnePixel.Height(); |
423 | 0 | } |
424 | 0 | else |
425 | 0 | { |
426 | | // old, fixed move distance |
427 | 0 | nX *= 100; |
428 | 0 | nY *= 100; |
429 | 0 | } |
430 | | |
431 | | // II |
432 | 0 | const SdrHdlList& rHdlList = pView->GetHdlList(); |
433 | 0 | SdrHdl* pHdl = rHdlList.GetFocusHdl(); |
434 | |
|
435 | 0 | if(nullptr == pHdl) |
436 | 0 | { |
437 | | // restrict movement to WorkArea |
438 | 0 | const tools::Rectangle& rWorkArea = pView->GetWorkArea(); |
439 | |
|
440 | 0 | if(!rWorkArea.IsEmpty()) |
441 | 0 | { |
442 | 0 | tools::Rectangle aMarkRect(pView->GetMarkedObjRect()); |
443 | 0 | aMarkRect.Move(nX, nY); |
444 | |
|
445 | 0 | if(!aMarkRect.Contains(rWorkArea)) |
446 | 0 | { |
447 | 0 | if(aMarkRect.Left() < rWorkArea.Left()) |
448 | 0 | { |
449 | 0 | nX += rWorkArea.Left() - aMarkRect.Left(); |
450 | 0 | } |
451 | |
|
452 | 0 | if(aMarkRect.Right() > rWorkArea.Right()) |
453 | 0 | { |
454 | 0 | nX -= aMarkRect.Right() - rWorkArea.Right(); |
455 | 0 | } |
456 | |
|
457 | 0 | if(aMarkRect.Top() < rWorkArea.Top()) |
458 | 0 | { |
459 | 0 | nY += rWorkArea.Top() - aMarkRect.Top(); |
460 | 0 | } |
461 | |
|
462 | 0 | if(aMarkRect.Bottom() > rWorkArea.Bottom()) |
463 | 0 | { |
464 | 0 | nY -= aMarkRect.Bottom() - rWorkArea.Bottom(); |
465 | 0 | } |
466 | 0 | } |
467 | 0 | } |
468 | | |
469 | | // no handle selected |
470 | 0 | if(0 != nX || 0 != nY) |
471 | 0 | { |
472 | 0 | pView->MoveAllMarked(Size(nX, nY)); |
473 | 0 | } |
474 | 0 | } |
475 | 0 | else |
476 | 0 | { |
477 | | // move handle with index nHandleIndex |
478 | 0 | if (nX || nY) |
479 | 0 | { |
480 | | // now move the Handle (nX, nY) |
481 | 0 | Point aStartPoint(pHdl->GetPos()); |
482 | 0 | Point aEndPoint(pHdl->GetPos() + Point(nX, nY)); |
483 | 0 | const SdrDragStat& rDragStat = pView->GetDragStat(); |
484 | | |
485 | | // start dragging |
486 | 0 | pView->BegDragObj(aStartPoint, nullptr, pHdl, 0); |
487 | |
|
488 | 0 | if(pView->IsDragObj()) |
489 | 0 | { |
490 | 0 | bool bWasNoSnap = rDragStat.IsNoSnap(); |
491 | 0 | bool bWasSnapEnabled = pView->IsSnapEnabled(); |
492 | | |
493 | | // switch snapping off |
494 | 0 | if(!bWasNoSnap) |
495 | 0 | const_cast<SdrDragStat&>(rDragStat).SetNoSnap(); |
496 | 0 | if(bWasSnapEnabled) |
497 | 0 | pView->SetSnapEnabled(false); |
498 | |
|
499 | 0 | pView->MovAction(aEndPoint); |
500 | 0 | pView->EndDragObj(); |
501 | | |
502 | | // restore snap |
503 | 0 | if(!bWasNoSnap) |
504 | 0 | const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap); |
505 | 0 | if(bWasSnapEnabled) |
506 | 0 | pView->SetSnapEnabled(bWasSnapEnabled); |
507 | 0 | } |
508 | 0 | } |
509 | 0 | } |
510 | |
|
511 | 0 | bProc = true; |
512 | 0 | } |
513 | 0 | } |
514 | 0 | break; |
515 | | |
516 | 0 | case KEY_SPACE: |
517 | 0 | { |
518 | 0 | const SdrHdlList& rHdlList = pView->GetHdlList(); |
519 | 0 | SdrHdl* pHdl = rHdlList.GetFocusHdl(); |
520 | |
|
521 | 0 | if(pHdl) |
522 | 0 | { |
523 | 0 | if(pHdl->GetKind() == SdrHdlKind::Poly) |
524 | 0 | { |
525 | | // rescue ID of point with focus |
526 | 0 | sal_uInt32 nPol(pHdl->GetPolyNum()); |
527 | 0 | sal_uInt32 nPnt(pHdl->GetPointNum()); |
528 | |
|
529 | 0 | if(pView->IsPointMarked(*pHdl)) |
530 | 0 | { |
531 | 0 | if(rKEvt.GetKeyCode().IsShift()) |
532 | 0 | { |
533 | 0 | pView->UnmarkPoint(*pHdl); |
534 | 0 | } |
535 | 0 | } |
536 | 0 | else |
537 | 0 | { |
538 | 0 | if(!rKEvt.GetKeyCode().IsShift()) |
539 | 0 | { |
540 | 0 | pView->UnmarkAllPoints(); |
541 | 0 | } |
542 | |
|
543 | 0 | pView->MarkPoint(*pHdl); |
544 | 0 | } |
545 | |
|
546 | 0 | if(nullptr == rHdlList.GetFocusHdl()) |
547 | 0 | { |
548 | | // restore point with focus |
549 | 0 | SdrHdl* pNewOne = nullptr; |
550 | |
|
551 | 0 | for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a) |
552 | 0 | { |
553 | 0 | SdrHdl* pAct = rHdlList.GetHdl(a); |
554 | |
|
555 | 0 | if(pAct |
556 | 0 | && pAct->GetKind() == SdrHdlKind::Poly |
557 | 0 | && pAct->GetPolyNum() == nPol |
558 | 0 | && pAct->GetPointNum() == nPnt) |
559 | 0 | { |
560 | 0 | pNewOne = pAct; |
561 | 0 | } |
562 | 0 | } |
563 | |
|
564 | 0 | if(pNewOne) |
565 | 0 | { |
566 | 0 | const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne); |
567 | 0 | } |
568 | 0 | } |
569 | |
|
570 | 0 | bProc = true; |
571 | 0 | } |
572 | 0 | } |
573 | 0 | } |
574 | 0 | break; |
575 | | |
576 | 0 | default: |
577 | 0 | break; |
578 | 0 | } |
579 | | |
580 | 0 | if (bProc) |
581 | 0 | ReleaseMouse(); |
582 | |
|
583 | 0 | QueueIdleUpdate(); |
584 | |
|
585 | 0 | return bProc; |
586 | 0 | } |
587 | | |
588 | | bool GraphCtrl::MouseButtonDown( const MouseEvent& rMEvt ) |
589 | 0 | { |
590 | 0 | if ( mbSdrMode && ( rMEvt.GetClicks() < 2 ) ) |
591 | 0 | { |
592 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
593 | |
|
594 | 0 | const Point aLogPt( rDevice.PixelToLogic( rMEvt.GetPosPixel() ) ); |
595 | |
|
596 | 0 | if ( !tools::Rectangle( Point(), aGraphSize ).Contains( aLogPt ) && !pView->IsEditMode() ) |
597 | 0 | weld::CustomWidgetController::MouseButtonDown( rMEvt ); |
598 | 0 | else |
599 | 0 | { |
600 | | // Get Focus for key inputs |
601 | 0 | GrabFocus(); |
602 | |
|
603 | 0 | if ( nPolyEdit ) |
604 | 0 | { |
605 | 0 | SdrViewEvent aVEvt; |
606 | 0 | SdrHitKind eHit = pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ); |
607 | |
|
608 | 0 | if ( nPolyEdit == SID_BEZIER_INSERT && eHit == SdrHitKind::MarkedObject ) |
609 | 0 | pView->BegInsObjPoint( aLogPt, rMEvt.IsMod1()); |
610 | 0 | else |
611 | 0 | pView->MouseButtonDown( rMEvt, &rDevice ); |
612 | 0 | } |
613 | 0 | else |
614 | 0 | pView->MouseButtonDown( rMEvt, &rDevice ); |
615 | 0 | } |
616 | |
|
617 | 0 | SdrObject* pCreateObj = pView->GetCreateObj(); |
618 | | |
619 | | // We want to realize the insert |
620 | 0 | if ( pCreateObj && !pCreateObj->GetUserCall() ) |
621 | 0 | pCreateObj->SetUserCall( pUserCall.get() ); |
622 | |
|
623 | 0 | SetPointer( pView->GetPreferredPointer( aLogPt, &rDevice ) ); |
624 | 0 | } |
625 | 0 | else |
626 | 0 | weld::CustomWidgetController::MouseButtonDown( rMEvt ); |
627 | |
|
628 | 0 | QueueIdleUpdate(); |
629 | |
|
630 | 0 | return false; |
631 | 0 | } |
632 | | |
633 | | bool GraphCtrl::MouseMove(const MouseEvent& rMEvt) |
634 | 0 | { |
635 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
636 | 0 | const Point aLogPos( rDevice.PixelToLogic( rMEvt.GetPosPixel() ) ); |
637 | |
|
638 | 0 | if ( mbSdrMode ) |
639 | 0 | { |
640 | 0 | pView->MouseMove( rMEvt, &rDevice ); |
641 | |
|
642 | 0 | if( ( SID_BEZIER_INSERT == nPolyEdit ) && |
643 | 0 | !pView->PickHandle( aLogPos ) && |
644 | 0 | !pView->IsInsObjPoint() ) |
645 | 0 | { |
646 | 0 | SetPointer( PointerStyle::Cross ); |
647 | 0 | } |
648 | 0 | else |
649 | 0 | SetPointer( pView->GetPreferredPointer( aLogPos, &rDevice ) ); |
650 | 0 | } |
651 | 0 | else |
652 | 0 | weld::CustomWidgetController::MouseButtonUp( rMEvt ); |
653 | |
|
654 | 0 | if ( aMousePosLink.IsSet() ) |
655 | 0 | { |
656 | 0 | if ( tools::Rectangle( Point(), aGraphSize ).Contains( aLogPos ) ) |
657 | 0 | aMousePos = aLogPos; |
658 | 0 | else |
659 | 0 | aMousePos = Point(); |
660 | |
|
661 | 0 | aMousePosLink.Call( this ); |
662 | 0 | } |
663 | |
|
664 | 0 | QueueIdleUpdate(); |
665 | |
|
666 | 0 | return false; |
667 | 0 | } |
668 | | |
669 | | bool GraphCtrl::MouseButtonUp(const MouseEvent& rMEvt) |
670 | 0 | { |
671 | 0 | if ( mbSdrMode ) |
672 | 0 | { |
673 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
674 | |
|
675 | 0 | if ( pView->IsInsObjPoint() ) |
676 | 0 | pView->EndInsObjPoint( SdrCreateCmd::ForceEnd ); |
677 | 0 | else |
678 | 0 | pView->MouseButtonUp( rMEvt, &rDevice ); |
679 | |
|
680 | 0 | ReleaseMouse(); |
681 | 0 | SetPointer( pView->GetPreferredPointer( rDevice.PixelToLogic( rMEvt.GetPosPixel() ), &rDevice ) ); |
682 | 0 | } |
683 | 0 | else |
684 | 0 | weld::CustomWidgetController::MouseButtonUp( rMEvt ); |
685 | |
|
686 | 0 | QueueIdleUpdate(); |
687 | |
|
688 | 0 | return false; |
689 | 0 | } |
690 | | |
691 | | SdrObject* GraphCtrl::GetSelectedSdrObject() const |
692 | 0 | { |
693 | 0 | SdrObject* pSdrObj = nullptr; |
694 | |
|
695 | 0 | if ( mbSdrMode ) |
696 | 0 | { |
697 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
698 | |
|
699 | 0 | if ( rMarkList.GetMarkCount() == 1 ) |
700 | 0 | pSdrObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); |
701 | 0 | } |
702 | |
|
703 | 0 | return pSdrObj; |
704 | 0 | } |
705 | | |
706 | | void GraphCtrl::SetEditMode( const bool _bEditMode ) |
707 | 0 | { |
708 | 0 | if ( mbSdrMode ) |
709 | 0 | { |
710 | 0 | bEditMode = _bEditMode; |
711 | 0 | pView->SetEditMode( bEditMode ); |
712 | 0 | eObjKind = SdrObjKind::NONE; |
713 | 0 | pView->SetCurrentObj(eObjKind); |
714 | 0 | } |
715 | 0 | else |
716 | 0 | bEditMode = false; |
717 | |
|
718 | 0 | QueueIdleUpdate(); |
719 | 0 | } |
720 | | |
721 | | void GraphCtrl::SetPolyEditMode( const sal_uInt16 _nPolyEdit ) |
722 | 0 | { |
723 | 0 | if ( mbSdrMode && ( _nPolyEdit != nPolyEdit ) ) |
724 | 0 | { |
725 | 0 | nPolyEdit = _nPolyEdit; |
726 | 0 | pView->SetFrameDragSingles( nPolyEdit == 0 ); |
727 | 0 | } |
728 | 0 | else |
729 | 0 | nPolyEdit = 0; |
730 | |
|
731 | 0 | QueueIdleUpdate(); |
732 | 0 | } |
733 | | |
734 | | void GraphCtrl::SetObjKind( const SdrObjKind _eObjKind ) |
735 | 0 | { |
736 | 0 | if ( mbSdrMode ) |
737 | 0 | { |
738 | 0 | bEditMode = false; |
739 | 0 | pView->SetEditMode( bEditMode ); |
740 | 0 | eObjKind = _eObjKind; |
741 | 0 | pView->SetCurrentObj(eObjKind); |
742 | 0 | } |
743 | 0 | else |
744 | 0 | eObjKind = SdrObjKind::NONE; |
745 | |
|
746 | 0 | QueueIdleUpdate(); |
747 | 0 | } |
748 | | |
749 | | IMPL_LINK_NOARG(GraphCtrl, UpdateHdl, Timer *, void) |
750 | 0 | { |
751 | 0 | mbInIdleUpdate = true; |
752 | 0 | aUpdateLink.Call( this ); |
753 | 0 | mbInIdleUpdate = false; |
754 | 0 | } |
755 | | |
756 | | void GraphCtrl::QueueIdleUpdate() |
757 | 0 | { |
758 | 0 | if (!mbInIdleUpdate) |
759 | 0 | aUpdateIdle.Start(); |
760 | 0 | } |
761 | | |
762 | | namespace |
763 | | { |
764 | | class WeldOverlayManager final : public sdr::overlay::OverlayManager |
765 | | { |
766 | | weld::CustomWidgetController& m_rGraphCtrl; |
767 | | |
768 | | public: |
769 | | WeldOverlayManager(weld::CustomWidgetController& rGraphCtrl, OutputDevice& rDevice) |
770 | 0 | : OverlayManager(rDevice) |
771 | 0 | , m_rGraphCtrl(rGraphCtrl) |
772 | 0 | { |
773 | 0 | } |
774 | | |
775 | | // invalidate the given range at local OutputDevice |
776 | | virtual void invalidateRange(const basegfx::B2DRange& rRange) override |
777 | 0 | { |
778 | 0 | tools::Rectangle aInvalidateRectangle(RangeToInvalidateRectangle(rRange)); |
779 | 0 | m_rGraphCtrl.Invalidate(aInvalidateRectangle); |
780 | 0 | } |
781 | | }; |
782 | | } |
783 | | |
784 | | rtl::Reference<sdr::overlay::OverlayManager> GraphCtrlView::CreateOverlayManager(OutputDevice& rDevice) const |
785 | 0 | { |
786 | 0 | assert(&rDevice == &rGraphCtrl.GetDrawingArea()->get_ref_device()); |
787 | 0 | if (rDevice.GetOutDevType() == OUTDEV_VIRDEV) |
788 | 0 | { |
789 | 0 | rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager(new WeldOverlayManager(rGraphCtrl, rDevice)); |
790 | 0 | InitOverlayManager(xOverlayManager); |
791 | 0 | return xOverlayManager; |
792 | 0 | } |
793 | 0 | return SdrView::CreateOverlayManager(rDevice); |
794 | 0 | } |
795 | | |
796 | | void GraphCtrlView::InvalidateOneWin(OutputDevice& rDevice) |
797 | 0 | { |
798 | 0 | assert(&rDevice == &rGraphCtrl.GetDrawingArea()->get_ref_device()); |
799 | 0 | if (rDevice.GetOutDevType() == OUTDEV_VIRDEV) |
800 | 0 | { |
801 | 0 | rGraphCtrl.Invalidate(); |
802 | 0 | return; |
803 | 0 | } |
804 | 0 | SdrView::InvalidateOneWin(rDevice); |
805 | 0 | } |
806 | | |
807 | | void GraphCtrlView::InvalidateOneWin(OutputDevice& rDevice, const tools::Rectangle& rArea) |
808 | 0 | { |
809 | 0 | assert(&rDevice == &rGraphCtrl.GetDrawingArea()->get_ref_device()); |
810 | 0 | if (rDevice.GetOutDevType() == OUTDEV_VIRDEV) |
811 | 0 | { |
812 | 0 | rGraphCtrl.Invalidate(rArea); |
813 | 0 | return; |
814 | 0 | } |
815 | 0 | SdrView::InvalidateOneWin(rDevice, rArea); |
816 | 0 | } |
817 | | |
818 | | GraphCtrlView::~GraphCtrlView() |
819 | 0 | { |
820 | | // turn SetOutputToWindow back off again before |
821 | | // turning back into our baseclass during dtoring |
822 | 0 | const sal_uInt32 nWindowCount(PaintWindowCount()); |
823 | 0 | for (sal_uInt32 nWinNum(0); nWinNum < nWindowCount; nWinNum++) |
824 | 0 | { |
825 | 0 | SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum); |
826 | 0 | pPaintWindow->SetOutputToWindow(false); |
827 | 0 | } |
828 | 0 | } |
829 | | |
830 | | Point GraphCtrl::GetPositionInDialog() const |
831 | 0 | { |
832 | 0 | int x, y, width, height; |
833 | 0 | if (GetDrawingArea()->get_extents_relative_to(*mpDialog, x, y, width, height)) |
834 | 0 | return Point(x, y); |
835 | 0 | return Point(); |
836 | 0 | } |
837 | | |
838 | | rtl::Reference<comphelper::OAccessible> GraphCtrl::CreateAccessible() |
839 | 0 | { |
840 | 0 | #if !ENABLE_WASM_STRIP_ACCESSIBILITY |
841 | 0 | if(mpAccContext == nullptr ) |
842 | 0 | { |
843 | 0 | mpAccContext = new SvxGraphCtrlAccessibleContext(*this); |
844 | 0 | } |
845 | 0 | #endif |
846 | 0 | return mpAccContext; |
847 | 0 | } |
848 | | |
849 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |