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