/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <Window.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <svx/svxids.hrc>
#include <editeng/outliner.hxx>
#include <editeng/editview.hxx>
#include <editeng/editeng.hxx>
#include <app.hrc>
#include <ViewShell.hxx>
#include <DrawViewShell.hxx>
#include <DrawDocShell.hxx>
#include <PresentationViewShell.hxx>
#include <View.hxx>
#include <FrameView.hxx>
#include <OutlineViewShell.hxx>
#include <OutlineView.hxx>
#include <drawdoc.hxx>
#include <WindowUpdater.hxx>
#include <ViewShellBase.hxx>
#include <uiobject.hxx>
#include <officecfg/Office/Common.hxx>
#include <sal/log.hxx>
#include <tools/debug.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/settings.hxx>
#include <comphelper/lok.hxx>
#include <sfx2/lokhelper.hxx>
namespace sd {
#define SCROLL_LINE_FACT 0.05 ///< factor for line scrolling
#define SCROLL_PAGE_FACT 0.5 ///< factor for page scrolling
#define SCROLL_SENSITIVE 20 ///< sensitive area in pixel
#define ZOOM_MULTIPLICATOR 10000 ///< multiplier to avoid rounding errors
#define MIN_ZOOM 5 ///< minimal zoom factor
#define MAX_ZOOM 3000 ///< maximal zoom factor
Window::Window(vcl::Window* pParent)
: vcl::DocWindow(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)),
DropTargetHelper( this ),
maWinPos(0, 0), // precautionary; but the values should be set
maViewOrigin(0, 0), // again from the owner of the window
maViewSize(1000, 1000),
maPrevSize(-1,-1),
mnMinZoom(MIN_ZOOM),
mnMaxZoom(MAX_ZOOM),
mbMinZoomAutoCalc(false),
mbCenterAllowed(true),
mnTicks (0),
mpViewShell(nullptr),
mbUseDropScroll (true)
{
SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
MapMode aMap(GetMapMode());
aMap.SetMapUnit(MapUnit::Map100thMM);
SetMapMode(aMap);
// with it, the vcl::WindowColor is used in the slide mode
SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetWindowColor() ) );
// adjust contrast mode initially
bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
GetOutDev()->SetDrawMode( bUseContrast
? sd::OUTPUT_DRAWMODE_CONTRAST
: sd::OUTPUT_DRAWMODE_COLOR );
// #i78183# Added after discussed with AF
EnableRTL(false);
}
Window::~Window()
{
disposeOnce();
}
void Window::dispose()
{
if (mpViewShell != nullptr)
{
WindowUpdater* pWindowUpdater = mpViewShell->GetWindowUpdater();
if (pWindowUpdater != nullptr)
pWindowUpdater->UnregisterWindow (this);
}
DropTargetHelper::dispose();
vcl::Window::dispose();
}
void Window::SetViewShell (ViewShell* pViewSh)
{
WindowUpdater* pWindowUpdater = nullptr;
// Unregister at device updater of old view shell.
if (mpViewShell != nullptr)
{
pWindowUpdater = mpViewShell->GetWindowUpdater();
if (pWindowUpdater != nullptr)
pWindowUpdater->UnregisterWindow (this);
}
mpViewShell = pViewSh;
// Register at device updater of new view shell
if (mpViewShell != nullptr)
{
pWindowUpdater = mpViewShell->GetWindowUpdater();
if (pWindowUpdater != nullptr)
pWindowUpdater->RegisterWindow (this);
}
}
ViewShell* Window::GetViewShell()
{
return mpViewShell;
}
void Window::CalcMinZoom()
{
// Are we entitled to change the minimal zoom factor?
if ( !mbMinZoomAutoCalc )
return;
// Get current zoom factor.
::tools::Long nZoom = GetZoom();
// Get the rectangle of the output area in logical coordinates
// and calculate the scaling factors that would lead to the view
// area (also called application area) to completely fill the
// window.
Size aWinSize = PixelToLogic(GetOutputSizePixel());
sal_uLong nX = static_cast<sal_uLong>(static_cast<double>(aWinSize.Width())
* double(ZOOM_MULTIPLICATOR) / static_cast<double>(maViewSize.Width()));
sal_uLong nY = static_cast<sal_uLong>(static_cast<double>(aWinSize.Height())
* double(ZOOM_MULTIPLICATOR) / static_cast<double>(maViewSize.Height()));
// Decide whether to take the larger or the smaller factor.
sal_uLong nFact = std::min(nX, nY);
// The factor is transformed according to the current zoom factor.
nFact = nFact * nZoom / ZOOM_MULTIPLICATOR;
mnMinZoom = std::max(sal_uInt16(MIN_ZOOM), static_cast<sal_uInt16>(nFact));
// If the current zoom factor is smaller than the calculated minimal
// zoom factor then set the new minimal factor as the current zoom
// factor.
if ( nZoom < static_cast<::tools::Long>(mnMinZoom) )
SetZoomFactor(mnMinZoom);
}
void Window::SetMinZoom (::tools::Long nMin)
{
mnMinZoom = static_cast<sal_uInt16>(nMin);
}
void Window::SetMaxZoom (::tools::Long nMax)
{
mnMaxZoom = static_cast<sal_uInt16>(nMax);
}
::tools::Long Window::GetZoom() const
{
if( GetMapMode().GetScaleX().GetDenominator() )
{
return ::tools::Long(GetMapMode().GetScaleX() * 100);
}
else
{
return 0;
}
}
void Window::Resize()
{
vcl::Window::Resize();
CalcMinZoom();
if( mpViewShell && mpViewShell->GetViewFrame() )
mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
}
void Window::PrePaint(vcl::RenderContext& /*rRenderContext*/)
{
if ( mpViewShell )
mpViewShell->PrePaint();
}
void Window::Paint(vcl::RenderContext& /*rRenderContext*/, const ::tools::Rectangle& rRect)
{
if ( mpViewShell )
mpViewShell->Paint(rRect, this);
}
void Window::KeyInput(const KeyEvent& rKEvt)
{
if (getenv("SD_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 && mpViewShell)
{
mpViewShell->GetDoc()->dumpAsXml(nullptr);
if (OutlinerView *pOLV = mpViewShell->GetView()->GetTextEditOutlinerView())
pOLV->GetEditView().getEditEngine().dumpAsXmlEditDoc(nullptr);
return;
}
if (!(mpViewShell && mpViewShell->KeyInput(rKEvt, this)))
{
if (mpViewShell && rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
{
mpViewShell->GetViewShell()->Escape();
}
else
{
vcl::Window::KeyInput(rKEvt);
}
}
}
void Window::MouseButtonDown(const MouseEvent& rMEvt)
{
if ( mpViewShell )
mpViewShell->MouseButtonDown(rMEvt, this);
}
void Window::MouseMove(const MouseEvent& rMEvt)
{
if ( mpViewShell )
mpViewShell->MouseMove(rMEvt, this);
}
void Window::MouseButtonUp(const MouseEvent& rMEvt)
{
mnTicks = 0;
if ( mpViewShell )
mpViewShell->MouseButtonUp(rMEvt, this);
}
void Window::Command(const CommandEvent& rCEvt)
{
if (mpViewShell)
mpViewShell->Command(rCEvt, this);
//pass at least alt press/release to parent impl
if (rCEvt.GetCommand() == CommandEventId::ModKeyChange)
vcl::Window::Command(rCEvt);
//show the text edit outliner view cursor
else if (mpViewShell && !HasFocus() && rCEvt.GetCommand() == CommandEventId::CursorPos)
{
// tdf#138855 Getting Focus may destroy TextEditOutlinerView so Grab if
// text editing active, but fetch the TextEditOutlinerView post-grab
if (mpViewShell->GetView()->IsTextEdit())
{
GrabFocus();
OutlinerView* pOLV = mpViewShell->GetView()->GetTextEditOutlinerView();
if (pOLV && this == pOLV->GetWindow())
pOLV->ShowCursor();
}
}
}
bool Window::EventNotify( NotifyEvent& rNEvt )
{
bool bResult = false;
if ( mpViewShell )
{
bResult = mpViewShell->Notify(rNEvt, this);
}
if( !bResult )
bResult = vcl::Window::EventNotify(rNEvt);
return bResult;
}
void Window::RequestHelp(const HelpEvent& rEvt)
{
if (!mpViewShell || !mpViewShell->RequestHelp(rEvt))
vcl::Window::RequestHelp( rEvt );
}
/**
* Set the position of the upper left corner from the visible area of the
* window.
*/
void Window::SetWinViewPos(const Point& rPnt)
{
maWinPos = rPnt;
}
/**
* Set origin of the representation in respect to the whole working area.
*/
void Window::SetViewOrigin(const Point& rPnt)
{
maViewOrigin = rPnt;
}
/**
* Set size of the whole working area which can be seen with the window.
*/
void Window::SetViewSize(const Size& rSize)
{
maViewSize = rSize;
CalcMinZoom();
}
void Window::SetCenterAllowed (bool bIsAllowed)
{
mbCenterAllowed = bIsAllowed;
}
::tools::Long Window::SetZoomFactor(::tools::Long nZoom)
{
// Clip the zoom factor to the valid range marked by nMinZoom as
// calculated by CalcMinZoom() and the constant MAX_ZOOM.
if ( nZoom > MAX_ZOOM )
nZoom = MAX_ZOOM;
if ( nZoom < static_cast<::tools::Long>(mnMinZoom) )
nZoom = mnMinZoom;
// Set the zoom factor at the window's map mode.
if (!comphelper::LibreOfficeKit::isActive())
{
MapMode aMap(GetMapMode());
aMap.SetScaleX(Fraction(nZoom, 100));
aMap.SetScaleY(Fraction(nZoom, 100));
SetMapMode(aMap);
}
// invalidate previous size - it was relative to the old scaling
maPrevSize = Size(-1,-1);
// Update the map mode's origin (to what effect?).
UpdateMapOrigin();
// Update the view's snapping to the new zoom factor.
if ( auto pDrawViewShell = dynamic_cast< DrawViewShell *>( mpViewShell ) )
pDrawViewShell->GetView()->RecalcLogicSnapMagnetic(*GetOutDev());
// Return the zoom factor just in case it has been changed above to lie
// inside the valid range.
return nZoom;
}
void Window::SetZoomIntegral(::tools::Long nZoom)
{
// Clip the zoom factor to the valid range marked by nMinZoom as
// previously calculated by <member>CalcMinZoom()</member> and the
// MAX_ZOOM constant.
if ( nZoom > MAX_ZOOM )
nZoom = MAX_ZOOM;
if ( nZoom < static_cast<::tools::Long>(mnMinZoom) )
nZoom = mnMinZoom;
// Calculate the window's new origin.
Size aSize = PixelToLogic(GetOutputSizePixel());
::tools::Long nW = aSize.Width() * GetZoom() / nZoom;
::tools::Long nH = aSize.Height() * GetZoom() / nZoom;
maWinPos.AdjustX((aSize.Width() - nW) / 2 );
maWinPos.AdjustY((aSize.Height() - nH) / 2 );
if ( maWinPos.X() < 0 ) maWinPos.setX( 0 );
if ( maWinPos.Y() < 0 ) maWinPos.setY( 0 );
// Finally update this window's map mode to the given zoom factor that
// has been clipped to the valid range.
SetZoomFactor(nZoom);
}
::tools::Long Window::GetZoomForRect( const ::tools::Rectangle& rZoomRect )
{
::tools::Long nRetZoom = 100;
if( (rZoomRect.GetWidth() != 0) && (rZoomRect.GetHeight() != 0))
{
// Calculate the scale factors which will lead to the given
// rectangle being fully visible (when translated accordingly) as
// large as possible in the output area independently in both
// coordinate directions .
sal_uLong nX(0);
sal_uLong nY(0);
const Size aWinSize( PixelToLogic(GetOutputSizePixel()) );
if(rZoomRect.GetHeight())
{
nX = static_cast<sal_uLong>(static_cast<double>(aWinSize.Height())
* double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetHeight()));
}
if(rZoomRect.GetWidth())
{
nY = static_cast<sal_uLong>(static_cast<double>(aWinSize.Width())
* double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetWidth()));
}
// Use the smaller one of both so that the zoom rectangle will be
// fully visible with respect to both coordinate directions.
sal_uLong nFact = std::min(nX, nY);
// Transform the current zoom factor so that it leads to the desired
// scaling.
nRetZoom = nFact * GetZoom() / ZOOM_MULTIPLICATOR;
// Calculate the new origin.
if ( nFact == 0 )
{
// Don't change anything if the scale factor is degenerate.
nRetZoom = GetZoom();
}
else
{
// Clip the zoom factor to the valid range marked by nMinZoom as
// previously calculated by <member>CalcMinZoom()</member> and the
// MAX_ZOOM constant.
if ( nRetZoom > MAX_ZOOM )
nRetZoom = MAX_ZOOM;
if ( nRetZoom < static_cast<::tools::Long>(mnMinZoom) )
nRetZoom = mnMinZoom;
}
}
return nRetZoom;
}
/** Recalculate the zoom factor and translation so that the given rectangle
is displayed centered and as large as possible while still being fully
visible in the window.
*/
::tools::Long Window::SetZoomRect (const ::tools::Rectangle& rZoomRect)
{
::tools::Long nNewZoom = 100;
if (rZoomRect.GetWidth() == 0 || rZoomRect.GetHeight() == 0)
{
// The given rectangle is degenerate. Use the default zoom factor
// (above) of 100%.
SetZoomIntegral(nNewZoom);
}
else
{
Point aPos = rZoomRect.TopLeft();
// Transform the output area from pixel coordinates into logical
// coordinates.
Size aWinSize = PixelToLogic(GetOutputSizePixel());
// Paranoia! The degenerate case of zero width or height has been
// taken care of above.
DBG_ASSERT(rZoomRect.GetWidth(), "ZoomRect-Width = 0!");
DBG_ASSERT(rZoomRect.GetHeight(), "ZoomRect-Height = 0!");
// Calculate the scale factors which will lead to the given
// rectangle being fully visible (when translated accordingly) as
// large as possible in the output area independently in both
// coordinate directions .
sal_uLong nX(0);
sal_uLong nY(0);
if(rZoomRect.GetHeight())
{
nX = static_cast<sal_uLong>(static_cast<double>(aWinSize.Height())
* double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetHeight()));
}
if(rZoomRect.GetWidth())
{
nY = static_cast<sal_uLong>(static_cast<double>(aWinSize.Width())
* double(ZOOM_MULTIPLICATOR) / static_cast<double>(rZoomRect.GetWidth()));
}
// Use the smaller one of both so that the zoom rectangle will be
// fully visible with respect to both coordinate directions.
sal_uLong nFact = std::min(nX, nY);
// Transform the current zoom factor so that it leads to the desired
// scaling.
::tools::Long nZoom = nFact * GetZoom() / ZOOM_MULTIPLICATOR;
// Calculate the new origin.
if ( nFact == 0 )
{
// Don't change anything if the scale factor is degenerate.
nNewZoom = GetZoom();
}
else
{
// Calculate the new window position that centers the given
// rectangle on the screen.
if ( nZoom > MAX_ZOOM )
nFact = nFact * MAX_ZOOM / nZoom;
maWinPos = maViewOrigin + aPos;
aWinSize.setWidth( static_cast<::tools::Long>(static_cast<double>(aWinSize.Width()) * double(ZOOM_MULTIPLICATOR) / static_cast<double>(nFact)) );
maWinPos.AdjustX((rZoomRect.GetWidth() - aWinSize.Width()) / 2 );
aWinSize.setHeight( static_cast<::tools::Long>(static_cast<double>(aWinSize.Height()) * double(ZOOM_MULTIPLICATOR) / static_cast<double>(nFact)) );
maWinPos.AdjustY((rZoomRect.GetHeight() - aWinSize.Height()) / 2 );
if ( maWinPos.X() < 0 ) maWinPos.setX( 0 );
if ( maWinPos.Y() < 0 ) maWinPos.setY( 0 );
// Adapt the window's map mode to the new zoom factor.
nNewZoom = SetZoomFactor(nZoom);
}
}
return nNewZoom;
}
void Window::SetMinZoomAutoCalc (bool bAuto)
{
mbMinZoomAutoCalc = bAuto;
}
/**
* Calculate and set new MapMode origin.
* If aWinPos.X()/Y() == -1, then we center the corresponding position (e.g. for
* initialization).
*/
void Window::UpdateMapOrigin(bool bInvalidate)
{
bool bChanged = false;
const Size aWinSize = PixelToLogic(GetOutputSizePixel());
if ( mbCenterAllowed )
{
if( maPrevSize != Size(-1,-1) )
{
// keep view centered around current pos, when window
// resizes
maWinPos.AdjustX( -((aWinSize.Width() - maPrevSize.Width()) / 2) );
maWinPos.AdjustY( -((aWinSize.Height() - maPrevSize.Height()) / 2) );
bChanged = true;
}
if ( maWinPos.X() > maViewSize.Width() - aWinSize.Width() )
{
maWinPos.setX( maViewSize.Width() - aWinSize.Width() );
bChanged = true;
}
if ( maWinPos.Y() > maViewSize.Height() - aWinSize.Height() )
{
maWinPos.setY( maViewSize.Height() - aWinSize.Height() );
bChanged = true;
}
if ( aWinSize.Width() > maViewSize.Width() || maWinPos.X() < 0 )
{
maWinPos.setX( maViewSize.Width() / 2 - aWinSize.Width() / 2 );
bChanged = true;
}
if ( aWinSize.Height() > maViewSize.Height() || maWinPos.Y() < 0 )
{
maWinPos.setY( maViewSize.Height() / 2 - aWinSize.Height() / 2 );
bChanged = true;
}
}
UpdateMapMode ();
maPrevSize = aWinSize;
// When tiled rendering, the above UpdateMapMode() call doesn't touch the map mode.
if (bChanged && bInvalidate && !comphelper::LibreOfficeKit::isActive())
Invalidate();
}
void Window::UpdateMapMode()
{
maWinPos -= maViewOrigin;
Size aPix(maWinPos.X(), maWinPos.Y());
aPix = LogicToPixel(aPix);
// Size has to be a multiple of BRUSH_SIZE due to the correct depiction of
// pattern
// #i2237#
// removed old stuff here which still forced zoom to be
// %BRUSH_SIZE which is outdated now
if (dynamic_cast< DrawViewShell *>( mpViewShell ))
{
// page should not "stick" to the window border
if (aPix.Width() == 0)
{
// #i2237#
// Since BRUSH_SIZE alignment is outdated now, i use the
// former constant here directly
aPix.AdjustWidth( -8 );
}
if (aPix.Height() == 0)
{
// #i2237#
// Since BRUSH_SIZE alignment is outdated now, i use the
// former constant here directly
aPix.AdjustHeight( -8 );
}
}
aPix = PixelToLogic(aPix);
maWinPos.setX( aPix.Width() );
maWinPos.setY( aPix.Height() );
Point aNewOrigin (-maWinPos.X(), -maWinPos.Y());
maWinPos += maViewOrigin;
if (!comphelper::LibreOfficeKit::isActive())
{
MapMode aMap(GetMapMode());
aMap.SetOrigin(aNewOrigin);
SetMapMode(aMap);
}
}
/**
* @returns X position of the visible area as fraction (< 1) of the whole
* working area.
*/
double Window::GetVisibleX() const
{
return maViewSize.Width() == 0 ? 0 : (static_cast<double>(maWinPos.X()) / maViewSize.Width());
}
/**
* @returns Y position of the visible area as fraction (< 1) of the whole
* working area.
*/
double Window::GetVisibleY() const
{
return maViewSize.Height() == 0 ? 0 : (static_cast<double>(maWinPos.Y()) / maViewSize.Height());
}
/**
* Set x and y position of the visible area as fraction (< 1) of the whole
* working area. Negative values are ignored.
*/
void Window::SetVisibleXY(double fX, double fY)
{
::tools::Long nOldX = maWinPos.X();
::tools::Long nOldY = maWinPos.Y();
if ( fX >= 0 )
maWinPos.setX( static_cast<::tools::Long>(fX * maViewSize.Width()) );
if ( fY >= 0 )
maWinPos.setY( static_cast<::tools::Long>(fY * maViewSize.Height()) );
UpdateMapOrigin(false);
Scroll(nOldX - maWinPos.X(), nOldY - maWinPos.Y(), ScrollFlags::Children);
PaintImmediately();
}
/**
* @returns width of the visible area in proportion to the width of the whole
* working area.
*/
double Window::GetVisibleWidth() const
{
Size aWinSize = PixelToLogic(GetOutputSizePixel());
return
maViewSize.Width() == 0 ? 0 : (static_cast<double>(aWinSize.Width()) / maViewSize.Width());
}
/**
* @returns height of the visible area in proportion to the height of the whole
* working area.
*/
double Window::GetVisibleHeight() const
{
Size aWinSize = PixelToLogic(GetOutputSizePixel());
return maViewSize.Height() == 0
? 0 : (static_cast<double>(aWinSize.Height()) / maViewSize.Height());
}
Point Window::GetVisibleCenter()
{
Point aPos = ::tools::Rectangle(Point(), GetOutputSizePixel()).Center();
// For LOK
bool bMapModeWasEnabled(IsMapModeEnabled());
EnableMapMode(/*true*/);
aPos = PixelToLogic(aPos);
EnableMapMode(bMapModeWasEnabled);
return aPos;
}
/**
* @returns width of a scroll column in proportion to the width of the whole
* working area.
*/
double Window::GetScrlLineWidth() const
{
return std::min(1.0, GetVisibleWidth()) * SCROLL_LINE_FACT;
}
/**
* @returns height of a scroll column in proportion to the height of the whole
* working area.
*/
double Window::GetScrlLineHeight() const
{
return std::min(1.0, GetVisibleHeight()) * SCROLL_LINE_FACT;
}
/**
* @returns width of a scroll page in proportion to the width of the whole
* working area.
*/
double Window::GetScrlPageWidth() const
{
return std::min(1.0, GetVisibleWidth()) * SCROLL_PAGE_FACT;
}
/**
* @returns height of a scroll page in proportion to the height of the whole
* working area.
*/
double Window::GetScrlPageHeight() const
{
return std::min(1.0, GetVisibleHeight()) * SCROLL_PAGE_FACT;
}
/**
* Deactivate window.
*/
void Window::LoseFocus()
{
mnTicks = 0;
vcl::Window::LoseFocus ();
if (mpViewShell)
mpViewShell->onLoseFocus();
}
/**
* Activate window.
*/
void Window::GrabFocus()
{
mnTicks = 0;
vcl::Window::GrabFocus ();
if (mpViewShell)
mpViewShell->onGrabFocus();
}
void Window::DataChanged( const DataChangedEvent& rDCEvt )
{
vcl::Window::DataChanged( rDCEvt );
/* Omit PRINTER by all documents which are not using a printer.
Omit FONTS and FONTSUBSTITUTION if no text output is available or if the
document does not allow text. */
if ( !((rDCEvt.GetType() == DataChangedEventType::PRINTER) ||
(rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
(rDCEvt.GetType() == DataChangedEventType::FONTS) ||
(rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE))) )
return;
if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
{
/* Rearrange or initiate Resize for scroll bars since the size of
the scroll bars my have changed. Within this, inside the resize-
handler, the size of the scroll bars will be asked from the
Settings. */
Resize();
/* Re-set data, which are from system control or from Settings. May
have to re-set more data since the resolution may also has
changed. */
if( mpViewShell )
{
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
DrawModeFlags nOutputMode;
sal_uInt16 nPreviewSlot;
if( rStyleSettings.GetHighContrastMode() )
nOutputMode = sd::OUTPUT_DRAWMODE_CONTRAST;
else
nOutputMode = sd::OUTPUT_DRAWMODE_COLOR;
if( rStyleSettings.GetHighContrastMode()
&& officecfg::Office::Common::Accessibility::IsForPagePreviews::get() )
nPreviewSlot = SID_PREVIEW_QUALITY_CONTRAST;
else
nPreviewSlot = SID_PREVIEW_QUALITY_COLOR;
if( dynamic_cast< DrawViewShell *>( mpViewShell ) != nullptr )
{
GetOutDev()->SetDrawMode( nOutputMode );
mpViewShell->GetFrameView()->SetDrawMode( nOutputMode );
Invalidate();
}
// Overwrite window color for OutlineView
if( dynamic_cast< OutlineViewShell *>( mpViewShell ) != nullptr )
{
svtools::ColorConfig aColorConfig;
const Color aDocColor( aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor );
SetBackground( Wallpaper( aDocColor ) );
}
SfxRequest aReq( nPreviewSlot, SfxCallMode::SLOT, mpViewShell->GetDocSh()->GetDoc()->GetItemPool() );
mpViewShell->ExecReq( aReq );
mpViewShell->Invalidate();
mpViewShell->ArrangeGUIElements();
// re-create handles to show new outfit
if(dynamic_cast< DrawViewShell *>( mpViewShell ) != nullptr)
{
mpViewShell->GetView()->AdjustMarkHdl();
}
}
}
if ( (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
{
/* Virtual devices, which also depends on the resolution or the
system control, should be updated. Otherwise, we should update
the virtual devices at least at DataChangedEventType::DISPLAY since some
systems allow to change the resolution and color depth during
runtime. Or the virtual devices have to be updated when the color
palette has changed since a different color matching can be used
when outputting. */
}
if ( rDCEvt.GetType() == DataChangedEventType::FONTS )
{
/* If the document provides font choose boxes, we have to update
them. I don't know how this looks like (also not really me, I
only translated the comment ;). We may can handle it global. We
have to discuss it with PB, but he is ill at the moment.
Before we handle it here, discuss it with PB and me. */
}
if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
(rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) )
{
/* Do reformatting since the fonts of the document may no longer
exist, or exist now, or are replaced with others. */
if( mpViewShell )
{
DrawDocShell* pDocSh = mpViewShell->GetDocSh();
if( pDocSh )
pDocSh->SetPrinter( pDocSh->GetPrinter( true ) );
}
}
if ( rDCEvt.GetType() == DataChangedEventType::PRINTER )
{
/* I don't know how the handling should look like. Maybe we delete a
printer and look what we have to do. Maybe I have to add
something to the VCL, in case the used printer is deleted.
Otherwise I may recalculate the formatting here if the current
printer is destroyed. */
if( mpViewShell )
{
DrawDocShell* pDocSh = mpViewShell->GetDocSh();
if( pDocSh )
pDocSh->SetPrinter( pDocSh->GetPrinter( true ) );
}
}
// Update everything
Invalidate();
}
sal_Int8 Window::AcceptDrop( const AcceptDropEvent& rEvt )
{
sal_Int8 nRet = DND_ACTION_NONE;
if( mpViewShell && !mpViewShell->GetDocSh()->IsReadOnly() )
{
nRet = mpViewShell->AcceptDrop( rEvt, *this, this, SDRPAGE_NOTFOUND, SDRLAYER_NOTFOUND );
if (mbUseDropScroll && dynamic_cast< OutlineViewShell *>( mpViewShell ) == nullptr)
DropScroll( rEvt.maPosPixel );
}
return nRet;
}
sal_Int8 Window::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
sal_Int8 nRet = DND_ACTION_NONE;
if( mpViewShell )
{
nRet = mpViewShell->ExecuteDrop( rEvt, *this, this, SDRPAGE_NOTFOUND, SDRLAYER_NOTFOUND );
}
return nRet;
}
void Window::SetUseDropScroll (bool bUseDropScroll)
{
mbUseDropScroll = bUseDropScroll;
}
void Window::DropScroll(const Point& rMousePos)
{
short nDx = 0;
short nDy = 0;
Size aSize = GetOutputSizePixel();
if (aSize.Width() > SCROLL_SENSITIVE * 3)
{
if ( rMousePos.X() < SCROLL_SENSITIVE )
{
nDx = -1;
}
if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE )
{
nDx = 1;
}
}
if (aSize.Height() > SCROLL_SENSITIVE * 3)
{
if ( rMousePos.Y() < SCROLL_SENSITIVE )
{
nDy = -1;
}
if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE )
{
nDy = 1;
}
}
if ( (nDx || nDy) && (rMousePos.X()!=0 || rMousePos.Y()!=0 ) )
{
if (mnTicks > 20)
mpViewShell->ScrollLines(nDx, nDy);
else
mnTicks ++;
}
}
css::uno::Reference<css::accessibility::XAccessible>
Window::CreateAccessible()
{
// If current viewshell is PresentationViewShell, just return empty because the correct ShowWin will be created later.
if (dynamic_cast< PresentationViewShell *>( mpViewShell ))
{
return vcl::Window::CreateAccessible ();
}
css::uno::Reference< css::accessibility::XAccessible > xAcc = GetAccessible(false);
if (xAcc)
{
return xAcc;
}
if (mpViewShell != nullptr)
{
xAcc = mpViewShell->CreateAccessibleDocumentView (this);
SetAccessible(xAcc);
return xAcc;
}
else
{
SAL_WARN("sd", "::sd::Window::CreateAccessible: no view shell");
return vcl::Window::CreateAccessible ();
}
}
OutlinerView* Window::GetOutlinerView() const
{
OutlinerView *pOLV = nullptr;
sd::View* pView = mpViewShell->GetView();
if (mpViewShell->GetShellType() == ViewShell::ST_OUTLINE)
{
if (OutlineView* pOView = dynamic_cast<OutlineView*>(pView))
pOLV = pOView->GetViewByWindow(this);
}
else if (pView->IsTextEdit())
{
pOLV = pView->GetTextEditOutlinerView();
}
return pOLV;
}
OUString Window::GetSurroundingText() const
{
OutlinerView *pOLV = GetOutlinerView();
if (pOLV)
return pOLV->GetEditView().GetSurroundingText();
return OUString();
}
Selection Window::GetSurroundingTextSelection() const
{
OutlinerView *pOLV = GetOutlinerView();
if (pOLV)
return pOLV->GetEditView().GetSurroundingTextSelection();
return Selection( 0, 0 );
}
bool Window::DeleteSurroundingText(const Selection& rSelection)
{
OutlinerView *pOLV = GetOutlinerView();
if (pOLV)
return pOLV->GetEditView().DeleteSurroundingText(rSelection);
return false;
}
void Window::LogicInvalidate(const ::tools::Rectangle* pRectangle)
{
DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(mpViewShell);
if (!pDrawViewShell || pDrawViewShell->IsInSwitchPage())
return;
if (!comphelper::LibreOfficeKit::isActive())
return;
::tools::Rectangle aRectangle;
::tools::Rectangle* pResultRectangle;
if (!pRectangle)
pResultRectangle = nullptr;
else
{
aRectangle = *pRectangle;
if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
{
aRectangle = o3tl::convert(aRectangle, o3tl::Length::mm100, o3tl::Length::twip);
}
pResultRectangle = &aRectangle;
}
SfxViewShell& rSfxViewShell = pDrawViewShell->GetViewShellBase();
SfxLokHelper::notifyInvalidation(&rSfxViewShell, pResultRectangle);
}
FactoryFunction Window::GetUITestFactory() const
{
if (get_id() == "impress_win")
return ImpressWindowUIObject::create;
return WindowUIObject::create;
}
} // end of namespace sd
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V1053 Calling the 'EnableRTL' virtual function in the constructor may lead to unexpected result at runtime.