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 <Window.hxx>
21 #include <sfx2/bindings.hxx>
22 #include <sfx2/request.hxx>
23
24 #include <sfx2/viewfrm.hxx>
25 #include <svx/svxids.hrc>
26
27 #include <editeng/outliner.hxx>
28 #include <editeng/editview.hxx>
29 #include <editeng/editeng.hxx>
30
31 #include <app.hrc>
32 #include <ViewShell.hxx>
33 #include <DrawViewShell.hxx>
34 #include <DrawDocShell.hxx>
35 #include <PresentationViewShell.hxx>
36 #include <View.hxx>
37 #include <FrameView.hxx>
38 #include <OutlineViewShell.hxx>
39 #include <OutlineView.hxx>
40 #include <drawdoc.hxx>
41 #include <WindowUpdater.hxx>
42 #include <ViewShellBase.hxx>
43 #include <uiobject.hxx>
44
45 #include <sal/log.hxx>
46 #include <tools/debug.hxx>
47 #include <vcl/commandevent.hxx>
48 #include <vcl/settings.hxx>
49 #include <comphelper/lok.hxx>
50 #include <sfx2/lokhelper.hxx>
51
52 namespace sd {
53
54 #define SCROLL_LINE_FACT 0.05 ///< factor for line scrolling
55 #define SCROLL_PAGE_FACT 0.5 ///< factor for page scrolling
56 #define SCROLL_SENSITIVE 20 ///< sensitive area in pixel
57 #define ZOOM_MULTIPLICATOR 10000 ///< multiplier to avoid rounding errors
58 #define MIN_ZOOM 5 ///< minimal zoom factor
59 #define MAX_ZOOM 3000 ///< maximal zoom factor
60
Window(vcl::Window * pParent)61 Window::Window(vcl::Window* pParent)
62 : vcl::Window(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)),
63 DropTargetHelper( this ),
64 maWinPos(0, 0), // precautionary; but the values should be set
65 maViewOrigin(0, 0), // again from the owner of the window
66 maViewSize(1000, 1000),
67 maPrevSize(-1,-1),
68 mnMinZoom(MIN_ZOOM),
69 mnMaxZoom(MAX_ZOOM),
70 mbMinZoomAutoCalc(false),
71 mbCenterAllowed(true),
72 mnTicks (0),
73 mpViewShell(nullptr),
74 mbUseDropScroll (true)
75 {
76 SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
77
78 MapMode aMap(GetMapMode());
79 aMap.SetMapUnit(MapUnit::Map100thMM);
80 SetMapMode(aMap);
81
82 // with it, the vcl::WindowColor is used in the slide mode
83 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetWindowColor() ) );
84
85 // adjust contrast mode initially
86 bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
87 GetOutDev()->SetDrawMode( bUseContrast
88 ? sd::OUTPUT_DRAWMODE_CONTRAST
89 : sd::OUTPUT_DRAWMODE_COLOR );
90
91 // #i78183# Added after discussed with AF
92 EnableRTL(false);
93 }
94
~Window()95 Window::~Window()
96 {
97 disposeOnce();
98 }
99
dispose()100 void Window::dispose()
101 {
102 if (mpViewShell != nullptr)
103 {
104 WindowUpdater* pWindowUpdater = mpViewShell->GetWindowUpdater();
105 if (pWindowUpdater != nullptr)
106 pWindowUpdater->UnregisterWindow (this);
107 }
108 DropTargetHelper::dispose();
109 vcl::Window::dispose();
110 }
111
SetViewShell(ViewShell * pViewSh)112 void Window::SetViewShell (ViewShell* pViewSh)
113 {
114 WindowUpdater* pWindowUpdater = nullptr;
115 // Unregister at device updater of old view shell.
116 if (mpViewShell != nullptr)
117 {
118 pWindowUpdater = mpViewShell->GetWindowUpdater();
119 if (pWindowUpdater != nullptr)
120 pWindowUpdater->UnregisterWindow (this);
121 }
122
123 mpViewShell = pViewSh;
124
125 // Register at device updater of new view shell
126 if (mpViewShell != nullptr)
127 {
128 pWindowUpdater = mpViewShell->GetWindowUpdater();
129 if (pWindowUpdater != nullptr)
130 pWindowUpdater->RegisterWindow (this);
131 }
132 }
133
GetViewShell()134 ViewShell* Window::GetViewShell()
135 {
136 return mpViewShell;
137 }
138
CalcMinZoom()139 void Window::CalcMinZoom()
140 {
141 // Are we entitled to change the minimal zoom factor?
142 if ( !mbMinZoomAutoCalc )
143 return;
144
145 // Get current zoom factor.
146 ::tools::Long nZoom = GetZoom();
147
148 // Get the rectangle of the output area in logical coordinates
149 // and calculate the scaling factors that would lead to the view
150 // area (also called application area) to completely fill the
151 // window.
152 Size aWinSize = PixelToLogic(GetOutputSizePixel());
153 sal_uLong nX = static_cast<sal_uLong>(static_cast<double>(aWinSize.Width())
154 * double(ZOOM_MULTIPLICATOR) / static_cast<double>(maViewSize.Width()));
155 sal_uLong nY = static_cast<sal_uLong>(static_cast<double>(aWinSize.Height())
156 * double(ZOOM_MULTIPLICATOR) / static_cast<double>(maViewSize.Height()));
157
158 // Decide whether to take the larger or the smaller factor.
159 sal_uLong nFact = std::min(nX, nY);
160
161 // The factor is transformed according to the current zoom factor.
162 nFact = nFact * nZoom / ZOOM_MULTIPLICATOR;
163 mnMinZoom = std::max(sal_uInt16(MIN_ZOOM), static_cast<sal_uInt16>(nFact));
164
165 // If the current zoom factor is smaller than the calculated minimal
166 // zoom factor then set the new minimal factor as the current zoom
167 // factor.
168 if ( nZoom < static_cast<::tools::Long>(mnMinZoom) )
169 SetZoomFactor(mnMinZoom);
170 }
171
SetMinZoom(::tools::Long nMin)172 void Window::SetMinZoom (::tools::Long nMin)
173 {
174 mnMinZoom = static_cast<sal_uInt16>(nMin);
175 }
176
SetMaxZoom(::tools::Long nMax)177 void Window::SetMaxZoom (::tools::Long nMax)
178 {
179 mnMaxZoom = static_cast<sal_uInt16>(nMax);
180 }
181
GetZoom() const182 ::tools::Long Window::GetZoom() const
183 {
184 if( GetMapMode().GetScaleX().GetDenominator() )
185 {
186 return ::tools::Long(GetMapMode().GetScaleX() * 100);
187 }
188 else
189 {
190 return 0;
191 }
192 }
193
Resize()194 void Window::Resize()
195 {
196 vcl::Window::Resize();
197 CalcMinZoom();
198
199 if( mpViewShell && mpViewShell->GetViewFrame() )
200 mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
201 }
202
PrePaint(vcl::RenderContext &)203 void Window::PrePaint(vcl::RenderContext& /*rRenderContext*/)
204 {
205 if ( mpViewShell )
206 mpViewShell->PrePaint();
207 }
208
Paint(vcl::RenderContext &,const::tools::Rectangle & rRect)209 void Window::Paint(vcl::RenderContext& /*rRenderContext*/, const ::tools::Rectangle& rRect)
210 {
211 if ( mpViewShell )
212 mpViewShell->Paint(rRect, this);
213 }
214
KeyInput(const KeyEvent & rKEvt)215 void Window::KeyInput(const KeyEvent& rKEvt)
216 {
217 if (getenv("SD_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 && mpViewShell)
218 {
219 mpViewShell->GetDoc()->dumpAsXml(nullptr);
220 if (OutlinerView *pOLV = mpViewShell->GetView()->GetTextEditOutlinerView())
221 pOLV->GetEditView().GetEditEngine()->dumpAsXmlEditDoc(nullptr);
222 return;
223 }
224
225 if (!(mpViewShell && mpViewShell->KeyInput(rKEvt, this)))
226 {
227 if (mpViewShell && rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
228 {
229 mpViewShell->GetViewShell()->Escape();
230 }
231 else
232 {
233 vcl::Window::KeyInput(rKEvt);
234 }
235 }
236 }
237
MouseButtonDown(const MouseEvent & rMEvt)238 void Window::MouseButtonDown(const MouseEvent& rMEvt)
239 {
240 if ( mpViewShell )
241 mpViewShell->MouseButtonDown(rMEvt, this);
242 }
243
MouseMove(const MouseEvent & rMEvt)244 void Window::MouseMove(const MouseEvent& rMEvt)
245 {
246 if ( mpViewShell )
247 mpViewShell->MouseMove(rMEvt, this);
248 }
249
MouseButtonUp(const MouseEvent & rMEvt)250 void Window::MouseButtonUp(const MouseEvent& rMEvt)
251 {
252 mnTicks = 0;
253
254 if ( mpViewShell )
255 mpViewShell->MouseButtonUp(rMEvt, this);
256 }
257
Command(const CommandEvent & rCEvt)258 void Window::Command(const CommandEvent& rCEvt)
259 {
260 if (mpViewShell)
261 mpViewShell->Command(rCEvt, this);
262 //pass at least alt press/release to parent impl
263 if (rCEvt.GetCommand() == CommandEventId::ModKeyChange)
264 vcl::Window::Command(rCEvt);
265 //show the text edit outliner view cursor
266 else if (mpViewShell && !HasFocus() && rCEvt.GetCommand() == CommandEventId::CursorPos)
267 {
268 // tdf#138855 Getting Focus may destroy TextEditOutlinerView so Grab if
269 // text editing active, but fetch the TextEditOutlinerView post-grab
270 if (mpViewShell->GetView()->IsTextEdit())
271 {
272 GrabFocus();
273 OutlinerView* pOLV = mpViewShell->GetView()->GetTextEditOutlinerView();
274 if (pOLV && this == pOLV->GetWindow())
275 pOLV->ShowCursor();
276 }
277 }
278 }
279
EventNotify(NotifyEvent & rNEvt)280 bool Window::EventNotify( NotifyEvent& rNEvt )
281 {
282 bool bResult = false;
283 if ( mpViewShell )
284 {
285 bResult = mpViewShell->Notify(rNEvt, this);
286 }
287 if( !bResult )
288 bResult = vcl::Window::EventNotify(rNEvt);
289
290 return bResult;
291 }
292
RequestHelp(const HelpEvent & rEvt)293 void Window::RequestHelp(const HelpEvent& rEvt)
294 {
295 if (!mpViewShell || !mpViewShell->RequestHelp(rEvt))
296 vcl::Window::RequestHelp( rEvt );
297 }
298
299 /**
300 * Set the position of the upper left corner from the visible area of the
301 * window.
302 */
SetWinViewPos(const Point & rPnt)303 void Window::SetWinViewPos(const Point& rPnt)
304 {
305 maWinPos = rPnt;
306 }
307
308 /**
309 * Set origin of the representation in respect to the whole working area.
310 */
SetViewOrigin(const Point & rPnt)311 void Window::SetViewOrigin(const Point& rPnt)
312 {
313 maViewOrigin = rPnt;
314 }
315
316 /**
317 * Set size of the whole working area which can be seen with the window.
318 */
SetViewSize(const Size & rSize)319 void Window::SetViewSize(const Size& rSize)
320 {
321 maViewSize = rSize;
322 CalcMinZoom();
323 }
324
SetCenterAllowed(bool bIsAllowed)325 void Window::SetCenterAllowed (bool bIsAllowed)
326 {
327 mbCenterAllowed = bIsAllowed;
328 }
329
SetZoomFactor(::tools::Long nZoom)330 ::tools::Long Window::SetZoomFactor(::tools::Long nZoom)
331 {
332 // Clip the zoom factor to the valid range marked by nMinZoom as
333 // calculated by CalcMinZoom() and the constant MAX_ZOOM.
334 if ( nZoom > MAX_ZOOM )
335 nZoom = MAX_ZOOM;
336 if ( nZoom < static_cast<::tools::Long>(mnMinZoom) )
337 nZoom = mnMinZoom;
338
339 // Set the zoom factor at the window's map mode.
340 if (!comphelper::LibreOfficeKit::isActive())
341 {
342 MapMode aMap(GetMapMode());
343 aMap.SetScaleX(Fraction(nZoom, 100));
344 aMap.SetScaleY(Fraction(nZoom, 100));
345 SetMapMode(aMap);
346 }
347
348 // invalidate previous size - it was relative to the old scaling
349 maPrevSize = Size(-1,-1);
350
351 // Update the map mode's origin (to what effect?).
352 UpdateMapOrigin();
353
354 // Update the view's snapping to the new zoom factor.
355 if ( auto pDrawViewShell = dynamic_cast< DrawViewShell *>( mpViewShell ) )
356 pDrawViewShell->GetView()->RecalcLogicSnapMagnetic(*GetOutDev());
357
358 // Return the zoom factor just in case it has been changed above to lie
359 // inside the valid range.
360 return nZoom;
361 }
362
SetZoomIntegral(::tools::Long nZoom)363 void Window::SetZoomIntegral(::tools::Long nZoom)
364 {
365 // Clip the zoom factor to the valid range marked by nMinZoom as
366 // previously calculated by <member>CalcMinZoom()</member> and the
367 // MAX_ZOOM constant.
368 if ( nZoom > MAX_ZOOM )
369 nZoom = MAX_ZOOM;
370 if ( nZoom < static_cast<::tools::Long>(mnMinZoom) )
371 nZoom = mnMinZoom;
372
373 // Calculate the window's new origin.
374 Size aSize = PixelToLogic(GetOutputSizePixel());
375 ::tools::Long nW = aSize.Width() * GetZoom() / nZoom;
376 ::tools::Long nH = aSize.Height() * GetZoom() / nZoom;
377 maWinPos.AdjustX((aSize.Width() - nW) / 2 );
378 maWinPos.AdjustY((aSize.Height() - nH) / 2 );
379 if ( maWinPos.X() < 0 ) maWinPos.setX( 0 );
380 if ( maWinPos.Y() < 0 ) maWinPos.setY( 0 );
381
382 // Finally update this window's map mode to the given zoom factor that
383 // has been clipped to the valid range.
384 SetZoomFactor(nZoom);
385 }
386
GetZoomForRect(const::tools::Rectangle & rZoomRect)387 ::tools::Long Window::GetZoomForRect( const ::tools::Rectangle& rZoomRect )
388 {
389 ::tools::Long nRetZoom = 100;
390
391 if( (rZoomRect.GetWidth() != 0) && (rZoomRect.GetHeight() != 0))
392 {
393 // Calculate the scale factors which will lead to the given
394 // rectangle being fully visible (when translated accordingly) as
395 // large as possible in the output area independently in both
396 // coordinate directions .
397 sal_uLong nX(0);
398 sal_uLong nY(0);
399
400 const Size aWinSize( PixelToLogic(GetOutputSizePixel()) );
401 if(rZoomRect.GetHeight())
402 {
403 nX = static_cast<sal_uLong>(static_cast<double>(aWinSize.Height())
404 * double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetHeight()));
405 }
406
407 if(rZoomRect.GetWidth())
408 {
409 nY = static_cast<sal_uLong>(static_cast<double>(aWinSize.Width())
410 * double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetWidth()));
411 }
412
413 // Use the smaller one of both so that the zoom rectangle will be
414 // fully visible with respect to both coordinate directions.
415 sal_uLong nFact = std::min(nX, nY);
416
417 // Transform the current zoom factor so that it leads to the desired
418 // scaling.
419 nRetZoom = nFact * GetZoom() / ZOOM_MULTIPLICATOR;
420
421 // Calculate the new origin.
422 if ( nFact == 0 )
423 {
424 // Don't change anything if the scale factor is degenerate.
425 nRetZoom = GetZoom();
426 }
427 else
428 {
429 // Clip the zoom factor to the valid range marked by nMinZoom as
430 // previously calculated by <member>CalcMinZoom()</member> and the
431 // MAX_ZOOM constant.
432 if ( nRetZoom > MAX_ZOOM )
433 nRetZoom = MAX_ZOOM;
434 if ( nRetZoom < static_cast<::tools::Long>(mnMinZoom) )
435 nRetZoom = mnMinZoom;
436 }
437 }
438
439 return nRetZoom;
440 }
441
442 /** Recalculate the zoom factor and translation so that the given rectangle
443 is displayed centered and as large as possible while still being fully
444 visible in the window.
445 */
SetZoomRect(const::tools::Rectangle & rZoomRect)446 ::tools::Long Window::SetZoomRect (const ::tools::Rectangle& rZoomRect)
447 {
448 ::tools::Long nNewZoom = 100;
449
450 if (rZoomRect.GetWidth() == 0 || rZoomRect.GetHeight() == 0)
451 {
452 // The given rectangle is degenerate. Use the default zoom factor
453 // (above) of 100%.
454 SetZoomIntegral(nNewZoom);
455 }
456 else
457 {
458 Point aPos = rZoomRect.TopLeft();
459 // Transform the output area from pixel coordinates into logical
460 // coordinates.
461 Size aWinSize = PixelToLogic(GetOutputSizePixel());
462 // Paranoia! The degenerate case of zero width or height has been
463 // taken care of above.
464 DBG_ASSERT(rZoomRect.GetWidth(), "ZoomRect-Width = 0!");
465 DBG_ASSERT(rZoomRect.GetHeight(), "ZoomRect-Height = 0!");
466
467 // Calculate the scale factors which will lead to the given
468 // rectangle being fully visible (when translated accordingly) as
469 // large as possible in the output area independently in both
470 // coordinate directions .
471 sal_uLong nX(0);
472 sal_uLong nY(0);
473
474 if(rZoomRect.GetHeight())
475 {
476 nX = static_cast<sal_uLong>(static_cast<double>(aWinSize.Height())
477 * double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetHeight()));
478 }
479
480 if(rZoomRect.GetWidth())
481 {
482 nY = static_cast<sal_uLong>(static_cast<double>(aWinSize.Width())
483 * double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetWidth()));
484 }
485
486 // Use the smaller one of both so that the zoom rectangle will be
487 // fully visible with respect to both coordinate directions.
488 sal_uLong nFact = std::min(nX, nY);
489
490 // Transform the current zoom factor so that it leads to the desired
491 // scaling.
492 ::tools::Long nZoom = nFact * GetZoom() / ZOOM_MULTIPLICATOR;
493
494 // Calculate the new origin.
495 if ( nFact == 0 )
496 {
497 // Don't change anything if the scale factor is degenerate.
498 nNewZoom = GetZoom();
499 }
500 else
501 {
502 // Calculate the new window position that centers the given
503 // rectangle on the screen.
504 if ( nZoom > MAX_ZOOM )
505 nFact = nFact * MAX_ZOOM / nZoom;
506
507 maWinPos = maViewOrigin + aPos;
508
509 aWinSize.setWidth( static_cast<::tools::Long>(static_cast<double>(aWinSize.Width()) * double(ZOOM_MULTIPLICATOR) / static_cast<double>(nFact)) );
510 maWinPos.AdjustX((rZoomRect.GetWidth() - aWinSize.Width()) / 2 );
511 aWinSize.setHeight( static_cast<::tools::Long>(static_cast<double>(aWinSize.Height()) * double(ZOOM_MULTIPLICATOR) / static_cast<double>(nFact)) );
512 maWinPos.AdjustY((rZoomRect.GetHeight() - aWinSize.Height()) / 2 );
513
514 if ( maWinPos.X() < 0 ) maWinPos.setX( 0 );
515 if ( maWinPos.Y() < 0 ) maWinPos.setY( 0 );
516
517 // Adapt the window's map mode to the new zoom factor.
518 nNewZoom = SetZoomFactor(nZoom);
519 }
520 }
521
522 return nNewZoom;
523 }
524
SetMinZoomAutoCalc(bool bAuto)525 void Window::SetMinZoomAutoCalc (bool bAuto)
526 {
527 mbMinZoomAutoCalc = bAuto;
528 }
529
530 /**
531 * Calculate and set new MapMode origin.
532 * If aWinPos.X()/Y() == -1, then we center the corresponding position (e.g. for
533 * initialization).
534 */
UpdateMapOrigin(bool bInvalidate)535 void Window::UpdateMapOrigin(bool bInvalidate)
536 {
537 bool bChanged = false;
538 const Size aWinSize = PixelToLogic(GetOutputSizePixel());
539
540 if ( mbCenterAllowed )
541 {
542 if( maPrevSize != Size(-1,-1) )
543 {
544 // keep view centered around current pos, when window
545 // resizes
546 maWinPos.AdjustX( -((aWinSize.Width() - maPrevSize.Width()) / 2) );
547 maWinPos.AdjustY( -((aWinSize.Height() - maPrevSize.Height()) / 2) );
548 bChanged = true;
549 }
550
551 if ( maWinPos.X() > maViewSize.Width() - aWinSize.Width() )
552 {
553 maWinPos.setX( maViewSize.Width() - aWinSize.Width() );
554 bChanged = true;
555 }
556 if ( maWinPos.Y() > maViewSize.Height() - aWinSize.Height() )
557 {
558 maWinPos.setY( maViewSize.Height() - aWinSize.Height() );
559 bChanged = true;
560 }
561 if ( aWinSize.Width() > maViewSize.Width() || maWinPos.X() < 0 )
562 {
563 maWinPos.setX( maViewSize.Width() / 2 - aWinSize.Width() / 2 );
564 bChanged = true;
565 }
566 if ( aWinSize.Height() > maViewSize.Height() || maWinPos.Y() < 0 )
567 {
568 maWinPos.setY( maViewSize.Height() / 2 - aWinSize.Height() / 2 );
569 bChanged = true;
570 }
571 }
572
573 UpdateMapMode ();
574
575 maPrevSize = aWinSize;
576
577 // When tiled rendering, the above UpdateMapMode() call doesn't touch the map mode.
578 if (bChanged && bInvalidate && !comphelper::LibreOfficeKit::isActive())
579 Invalidate();
580 }
581
UpdateMapMode()582 void Window::UpdateMapMode()
583 {
584 maWinPos -= maViewOrigin;
585 Size aPix(maWinPos.X(), maWinPos.Y());
586 aPix = LogicToPixel(aPix);
587 // Size has to be a multiple of BRUSH_SIZE due to the correct depiction of
588 // pattern
589 // #i2237#
590 // removed old stuff here which still forced zoom to be
591 // %BRUSH_SIZE which is outdated now
592
593 if (dynamic_cast< DrawViewShell *>( mpViewShell ))
594 {
595 // page should not "stick" to the window border
596 if (aPix.Width() == 0)
597 {
598 // #i2237#
599 // Since BRUSH_SIZE alignment is outdated now, i use the
600 // former constant here directly
601 aPix.AdjustWidth( -8 );
602 }
603 if (aPix.Height() == 0)
604 {
605 // #i2237#
606 // Since BRUSH_SIZE alignment is outdated now, i use the
607 // former constant here directly
608 aPix.AdjustHeight( -8 );
609 }
610 }
611
612 aPix = PixelToLogic(aPix);
613 maWinPos.setX( aPix.Width() );
614 maWinPos.setY( aPix.Height() );
615 Point aNewOrigin (-maWinPos.X(), -maWinPos.Y());
616 maWinPos += maViewOrigin;
617
618 if (!comphelper::LibreOfficeKit::isActive())
619 {
620 MapMode aMap(GetMapMode());
621 aMap.SetOrigin(aNewOrigin);
622 SetMapMode(aMap);
623 }
624 }
625
626 /**
627 * @returns X position of the visible area as fraction (< 1) of the whole
628 * working area.
629 */
GetVisibleX() const630 double Window::GetVisibleX() const
631 {
632 return (static_cast<double>(maWinPos.X()) / maViewSize.Width());
633 }
634
635 /**
636 * @returns Y position of the visible area as fraction (< 1) of the whole
637 * working area.
638 */
GetVisibleY() const639 double Window::GetVisibleY() const
640 {
641 return (static_cast<double>(maWinPos.Y()) / maViewSize.Height());
642 }
643
644 /**
645 * Set x and y position of the visible area as fraction (< 1) of the whole
646 * working area. Negative values are ignored.
647 */
SetVisibleXY(double fX,double fY)648 void Window::SetVisibleXY(double fX, double fY)
649 {
650 ::tools::Long nOldX = maWinPos.X();
651 ::tools::Long nOldY = maWinPos.Y();
652
653 if ( fX >= 0 )
654 maWinPos.setX( static_cast<::tools::Long>(fX * maViewSize.Width()) );
655 if ( fY >= 0 )
656 maWinPos.setY( static_cast<::tools::Long>(fY * maViewSize.Height()) );
657 UpdateMapOrigin(false);
658 Scroll(nOldX - maWinPos.X(), nOldY - maWinPos.Y(), ScrollFlags::Children);
659 PaintImmediately();
660 }
661
662 /**
663 * @returns width of the visible area in proportion to the width of the whole
664 * working area.
665 */
GetVisibleWidth() const666 double Window::GetVisibleWidth() const
667 {
668 Size aWinSize = PixelToLogic(GetOutputSizePixel());
669 if ( aWinSize.Width() > maViewSize.Width() )
670 aWinSize.setWidth( maViewSize.Width() );
671 return (static_cast<double>(aWinSize.Width()) / maViewSize.Width());
672 }
673
674 /**
675 * @returns height of the visible area in proportion to the height of the whole
676 * working area.
677 */
GetVisibleHeight() const678 double Window::GetVisibleHeight() const
679 {
680 Size aWinSize = PixelToLogic(GetOutputSizePixel());
681 if ( aWinSize.Height() > maViewSize.Height() )
682 aWinSize.setHeight( maViewSize.Height() );
683 return (static_cast<double>(aWinSize.Height()) / maViewSize.Height());
684 }
685
GetVisibleCenter()686 Point Window::GetVisibleCenter()
687 {
688 Point aPos = ::tools::Rectangle(Point(), GetOutputSizePixel()).Center();
689
690 // For LOK
691 bool bMapModeWasEnabled(IsMapModeEnabled());
692 EnableMapMode(/*true*/);
693 aPos = PixelToLogic(aPos);
694 EnableMapMode(bMapModeWasEnabled);
695
696 return aPos;
697 }
698
699 /**
700 * @returns width of a scroll column in proportion to the width of the whole
701 * working area.
702 */
GetScrlLineWidth() const703 double Window::GetScrlLineWidth() const
704 {
705 return (GetVisibleWidth() * SCROLL_LINE_FACT);
706 }
707
708 /**
709 * @returns height of a scroll column in proportion to the height of the whole
710 * working area.
711 */
GetScrlLineHeight() const712 double Window::GetScrlLineHeight() const
713 {
714 return (GetVisibleHeight() * SCROLL_LINE_FACT);
715 }
716
717 /**
718 * @returns width of a scroll page in proportion to the width of the whole
719 * working area.
720 */
GetScrlPageWidth() const721 double Window::GetScrlPageWidth() const
722 {
723 return (GetVisibleWidth() * SCROLL_PAGE_FACT);
724 }
725
726 /**
727 * @returns height of a scroll page in proportion to the height of the whole
728 * working area.
729 */
GetScrlPageHeight() const730 double Window::GetScrlPageHeight() const
731 {
732 return (GetVisibleHeight() * SCROLL_PAGE_FACT);
733 }
734
735 /**
736 * Deactivate window.
737 */
LoseFocus()738 void Window::LoseFocus()
739 {
740 mnTicks = 0;
741 vcl::Window::LoseFocus ();
742 }
743
744 /**
745 * Activate window.
746 */
GrabFocus()747 void Window::GrabFocus()
748 {
749 mnTicks = 0;
750 vcl::Window::GrabFocus ();
751 }
752
DataChanged(const DataChangedEvent & rDCEvt)753 void Window::DataChanged( const DataChangedEvent& rDCEvt )
754 {
755 vcl::Window::DataChanged( rDCEvt );
756
757 /* Omit PRINTER by all documents which are not using a printer.
758 Omit FONTS and FONTSUBSTITUTION if no text output is available or if the
759 document does not allow text. */
760
761 if ( !((rDCEvt.GetType() == DataChangedEventType::PRINTER) ||
762 (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
763 (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
764 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
765 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
766 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))) )
767 return;
768
769 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
770 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
771 {
772 /* Rearrange or initiate Resize for scroll bars since the size of
773 the scroll bars my have changed. Within this, inside the resize-
774 handler, the size of the scroll bars will be asked from the
775 Settings. */
776 Resize();
777
778 /* Re-set data, which are from system control or from Settings. May
779 have to re-set more data since the resolution may also has
780 changed. */
781 if( mpViewShell )
782 {
783 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
784 SvtAccessibilityOptions aAccOptions;
785 DrawModeFlags nOutputMode;
786 sal_uInt16 nPreviewSlot;
787
788 if( rStyleSettings.GetHighContrastMode() )
789 nOutputMode = sd::OUTPUT_DRAWMODE_CONTRAST;
790 else
791 nOutputMode = sd::OUTPUT_DRAWMODE_COLOR;
792
793 if( rStyleSettings.GetHighContrastMode() && aAccOptions.GetIsForPagePreviews() )
794 nPreviewSlot = SID_PREVIEW_QUALITY_CONTRAST;
795 else
796 nPreviewSlot = SID_PREVIEW_QUALITY_COLOR;
797
798 if( dynamic_cast< DrawViewShell *>( mpViewShell ) != nullptr )
799 {
800 GetOutDev()->SetDrawMode( nOutputMode );
801 mpViewShell->GetFrameView()->SetDrawMode( nOutputMode );
802 Invalidate();
803 }
804
805 // Overwrite window color for OutlineView
806 if( dynamic_cast< OutlineViewShell *>( mpViewShell ) != nullptr )
807 {
808 svtools::ColorConfig aColorConfig;
809 const Color aDocColor( aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor );
810 SetBackground( Wallpaper( aDocColor ) );
811 }
812
813 SfxRequest aReq( nPreviewSlot, SfxCallMode::SLOT, mpViewShell->GetDocSh()->GetDoc()->GetItemPool() );
814 mpViewShell->ExecReq( aReq );
815 mpViewShell->Invalidate();
816 mpViewShell->ArrangeGUIElements();
817
818 // re-create handles to show new outfit
819 if(dynamic_cast< DrawViewShell *>( mpViewShell ) != nullptr)
820 {
821 mpViewShell->GetView()->AdjustMarkHdl();
822 }
823 }
824 }
825
826 if ( (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
827 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
828 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
829 {
830 /* Virtual devices, which also depends on the resolution or the
831 system control, should be updated. Otherwise, we should update
832 the virtual devices at least at DataChangedEventType::DISPLAY since some
833 systems allow to change the resolution and color depth during
834 runtime. Or the virtual devices have to be updated when the color
835 palette has changed since a different color matching can be used
836 when outputting. */
837 }
838
839 if ( rDCEvt.GetType() == DataChangedEventType::FONTS )
840 {
841 /* If the document provides font choose boxes, we have to update
842 them. I don't know how this looks like (also not really me, I
843 only translated the comment ;). We may can handle it global. We
844 have to discuss it with PB, but he is ill at the moment.
845 Before we handle it here, discuss it with PB and me. */
846 }
847
848 if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
849 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) )
850 {
851 /* Do reformatting since the fonts of the document may no longer
852 exist, or exist now, or are replaced with others. */
853 if( mpViewShell )
854 {
855 DrawDocShell* pDocSh = mpViewShell->GetDocSh();
856 if( pDocSh )
857 pDocSh->SetPrinter( pDocSh->GetPrinter( true ) );
858 }
859 }
860
861 if ( rDCEvt.GetType() == DataChangedEventType::PRINTER )
862 {
863 /* I don't know how the handling should look like. Maybe we delete a
864 printer and look what we have to do. Maybe I have to add
865 something to the VCL, in case the used printer is deleted.
866 Otherwise I may recalculate the formatting here if the current
867 printer is destroyed. */
868 if( mpViewShell )
869 {
870 DrawDocShell* pDocSh = mpViewShell->GetDocSh();
871 if( pDocSh )
872 pDocSh->SetPrinter( pDocSh->GetPrinter( true ) );
873 }
874 }
875
876 // Update everything
877 Invalidate();
878 }
879
AcceptDrop(const AcceptDropEvent & rEvt)880 sal_Int8 Window::AcceptDrop( const AcceptDropEvent& rEvt )
881 {
882 sal_Int8 nRet = DND_ACTION_NONE;
883
884 if( mpViewShell && !mpViewShell->GetDocSh()->IsReadOnly() )
885 {
886 nRet = mpViewShell->AcceptDrop( rEvt, *this, this, SDRPAGE_NOTFOUND, SDRLAYER_NOTFOUND );
887
888 if (mbUseDropScroll && dynamic_cast< OutlineViewShell *>( mpViewShell ) == nullptr)
889 DropScroll( rEvt.maPosPixel );
890 }
891
892 return nRet;
893 }
894
ExecuteDrop(const ExecuteDropEvent & rEvt)895 sal_Int8 Window::ExecuteDrop( const ExecuteDropEvent& rEvt )
896 {
897 sal_Int8 nRet = DND_ACTION_NONE;
898
899 if( mpViewShell )
900 {
901 nRet = mpViewShell->ExecuteDrop( rEvt, *this, this, SDRPAGE_NOTFOUND, SDRLAYER_NOTFOUND );
902 }
903
904 return nRet;
905 }
906
SetUseDropScroll(bool bUseDropScroll)907 void Window::SetUseDropScroll (bool bUseDropScroll)
908 {
909 mbUseDropScroll = bUseDropScroll;
910 }
911
DropScroll(const Point & rMousePos)912 void Window::DropScroll(const Point& rMousePos)
913 {
914 short nDx = 0;
915 short nDy = 0;
916
917 Size aSize = GetOutputSizePixel();
918
919 if (aSize.Width() > SCROLL_SENSITIVE * 3)
920 {
921 if ( rMousePos.X() < SCROLL_SENSITIVE )
922 {
923 nDx = -1;
924 }
925
926 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE )
927 {
928 nDx = 1;
929 }
930 }
931
932 if (aSize.Height() > SCROLL_SENSITIVE * 3)
933 {
934 if ( rMousePos.Y() < SCROLL_SENSITIVE )
935 {
936 nDy = -1;
937 }
938
939 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE )
940 {
941 nDy = 1;
942 }
943 }
944
945 if ( (nDx || nDy) && (rMousePos.X()!=0 || rMousePos.Y()!=0 ) )
946 {
947 if (mnTicks > 20)
948 mpViewShell->ScrollLines(nDx, nDy);
949 else
950 mnTicks ++;
951 }
952 }
953
954 css::uno::Reference<css::accessibility::XAccessible>
CreateAccessible()955 Window::CreateAccessible()
956 {
957 // If current viewshell is PresentationViewShell, just return empty because the correct ShowWin will be created later.
958 if (dynamic_cast< PresentationViewShell *>( mpViewShell ))
959 {
960 return vcl::Window::CreateAccessible ();
961 }
962 css::uno::Reference< css::accessibility::XAccessible > xAcc = GetAccessible(false);
963 if (xAcc)
964 {
965 return xAcc;
966 }
967 if (mpViewShell != nullptr)
968 {
969 xAcc = mpViewShell->CreateAccessibleDocumentView (this);
970 SetAccessible(xAcc);
971 return xAcc;
972 }
973 else
974 {
975 SAL_WARN("sd", "::sd::Window::CreateAccessible: no view shell");
976 return vcl::Window::CreateAccessible ();
977 }
978 }
979
GetOutlinerView() const980 OutlinerView* Window::GetOutlinerView() const
981 {
982 OutlinerView *pOLV = nullptr;
983 sd::View* pView = mpViewShell->GetView();
984 if (mpViewShell->GetShellType() == ViewShell::ST_OUTLINE)
985 {
986 if (OutlineView* pOView = dynamic_cast<OutlineView*>(pView))
987 pOLV = pOView->GetViewByWindow(this);
988 }
989 else if (pView->IsTextEdit())
990 {
991 pOLV = pView->GetTextEditOutlinerView();
992 }
993 return pOLV;
994 }
995
GetSurroundingText() const996 OUString Window::GetSurroundingText() const
997 {
998 OutlinerView *pOLV = GetOutlinerView();
999 if (pOLV)
1000 return pOLV->GetEditView().GetSurroundingText();
1001 return OUString();
1002 }
1003
GetSurroundingTextSelection() const1004 Selection Window::GetSurroundingTextSelection() const
1005 {
1006 OutlinerView *pOLV = GetOutlinerView();
1007 if (pOLV)
1008 return pOLV->GetEditView().GetSurroundingTextSelection();
1009 return Selection( 0, 0 );
1010 }
1011
DeleteSurroundingText(const Selection & rSelection)1012 bool Window::DeleteSurroundingText(const Selection& rSelection)
1013 {
1014 OutlinerView *pOLV = GetOutlinerView();
1015 if (pOLV)
1016 return pOLV->GetEditView().DeleteSurroundingText(rSelection);
1017 return false;
1018 }
1019
LogicInvalidate(const::tools::Rectangle * pRectangle)1020 void Window::LogicInvalidate(const ::tools::Rectangle* pRectangle)
1021 {
1022 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(mpViewShell);
1023 if (!pDrawViewShell || pDrawViewShell->IsInSwitchPage())
1024 return;
1025
1026 if (!comphelper::LibreOfficeKit::isActive())
1027 return;
1028 OString sRectangle;
1029 if (!pRectangle)
1030 sRectangle = "EMPTY";
1031 else
1032 {
1033 ::tools::Rectangle aRectangle(*pRectangle);
1034 if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
1035 aRectangle = OutputDevice::LogicToLogic(aRectangle, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip));
1036 sRectangle = aRectangle.toString();
1037 }
1038 SfxViewShell& rSfxViewShell = pDrawViewShell->GetViewShellBase();
1039 SfxLokHelper::notifyInvalidation(&rSfxViewShell, sRectangle);
1040 }
1041
LogicMouseButtonDown(const MouseEvent & rMouseEvent)1042 void Window::LogicMouseButtonDown(const MouseEvent& rMouseEvent)
1043 {
1044 // When we're not doing tiled rendering, then positions must be passed as pixels.
1045 assert(comphelper::LibreOfficeKit::isActive());
1046
1047 Point aPoint = GetPointerPosPixel();
1048 SetLastMousePos(rMouseEvent.GetPosPixel());
1049
1050 mpViewShell->MouseButtonDown(rMouseEvent, this);
1051
1052 SetPointerPosPixel(aPoint);
1053 }
1054
LogicMouseButtonUp(const MouseEvent & rMouseEvent)1055 void Window::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
1056 {
1057 // When we're not doing tiled rendering, then positions must be passed as pixels.
1058 assert(comphelper::LibreOfficeKit::isActive());
1059
1060 Point aPoint = GetPointerPosPixel();
1061 SetLastMousePos(rMouseEvent.GetPosPixel());
1062
1063 mpViewShell->MouseButtonUp(rMouseEvent, this);
1064
1065 SetPointerPosPixel(aPoint);
1066 }
1067
LogicMouseMove(const MouseEvent & rMouseEvent)1068 void Window::LogicMouseMove(const MouseEvent& rMouseEvent)
1069 {
1070 // When we're not doing tiled rendering, then positions must be passed as pixels.
1071 assert(comphelper::LibreOfficeKit::isActive());
1072
1073 Point aPoint = GetPointerPosPixel();
1074 SetLastMousePos(rMouseEvent.GetPosPixel());
1075
1076 mpViewShell->MouseMove(rMouseEvent, this);
1077
1078 SetPointerPosPixel(aPoint);
1079 }
1080
GetUITestFactory() const1081 FactoryFunction Window::GetUITestFactory() const
1082 {
1083 if (get_id() == "impress_win")
1084 return ImpressWindowUIObject::create;
1085
1086 return WindowUIObject::create;
1087 }
1088
1089 } // end of namespace sd
1090
1091 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1092