Coverage Report

Created: 2025-12-08 09:28

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