/* -*- 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 <sfx2/objface.hxx>
#include <vcl/timer.hxx>
#include <vcl/field.hxx>
#include <vcl/fixed.hxx>
#include <vcl/help.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/button.hxx>
#include <vcl/settings.hxx>
#include <vcl/weld.hxx>
#include <svl/whiter.hxx>
#include <svl/stritem.hxx>
#include <svl/eitem.hxx>
#include <sfx2/printer.hxx>
#include <sfx2/progress.hxx>
#include <sfx2/app.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/request.hxx>
#include <sfx2/dispatch.hxx>
#include <svx/stddlg.hxx>
#include <editeng/paperinf.hxx>
#include <svl/srchitem.hxx>
#include <svx/svdview.hxx>
#include <svx/dlgutil.hxx>
#include <svx/zoomslideritem.hxx>
#include <svx/svxids.hrc>
#include <swwait.hxx>
#include <globdoc.hxx>
#include <wdocsh.hxx>
#include <pvprtdat.hxx>
#include <swmodule.hxx>
#include <modcfg.hxx>
#include <wrtsh.hxx>
#include <docsh.hxx>
#include <viewopt.hxx>
#include <doc.hxx>
#include <IDocumentDeviceAccess.hxx>
#include <pview.hxx>
#include <view.hxx>
#include <textsh.hxx>
#include <scroll.hxx>
#include <prtopt.hxx>
#include <docstat.hxx>
#include <usrpref.hxx>
#include "viewfunc.hxx"
#include <helpids.h>
#include <cmdid.h>
#include <globals.hrc>
#include <strings.hrc>
#define ShellClass_SwPagePreview
#include <sfx2/msg.hxx>
#include <swslots.hxx>
#include <pagepreviewlayout.hxx>
#include <svx/svxdlg.hxx>
#include <svx/dialogs.hrc>
#include <memory>
#include <vcl/EnumContext.hxx>
#include <vcl/notebookbar.hxx>
#include <prevwpage.hxx>
using namespace ::com::sun::star;
SFX_IMPL_NAMED_VIEWFACTORY(SwPagePreview, "PrintPreview")
{
SFX_VIEW_REGISTRATION(SwDocShell);
SFX_VIEW_REGISTRATION(SwWebDocShell);
SFX_VIEW_REGISTRATION(SwGlobalDocShell);
}
SFX_IMPL_INTERFACE(SwPagePreview, SfxViewShell)
void SwPagePreview::InitInterface_Impl()
{
GetStaticInterface()->RegisterPopupMenu("preview");
GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
SfxVisibilityFlags::Standard|SfxVisibilityFlags::Client|SfxVisibilityFlags::FullScreen|SfxVisibilityFlags::ReadonlyDoc,
ToolbarId::PView_Toolbox);
}
#define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
#define MIN_PREVIEW_ZOOM 25
#define MAX_PREVIEW_ZOOM 600
static sal_uInt16 lcl_GetNextZoomStep(sal_uInt16 nCurrentZoom, bool bZoomIn)
{
static const sal_uInt16 aZoomArr[] =
{
25, 50, 75, 100, 150, 200, 400, 600
};
const int nZoomArrSize = static_cast<int>(SAL_N_ELEMENTS(aZoomArr));
if (bZoomIn)
{
for(int i = nZoomArrSize - 1; i >= 0; --i)
{
if(nCurrentZoom > aZoomArr[i] || !i)
return aZoomArr[i];
}
}
else
{
for(sal_uInt16 i : aZoomArr)
{
if(nCurrentZoom < i)
return i;
}
}
return bZoomIn ? MAX_PREVIEW_ZOOM : MIN_PREVIEW_ZOOM;
};
static void lcl_InvalidateZoomSlots(SfxBindings& rBindings)
{
static sal_uInt16 const aInval[] =
{
SID_ATTR_ZOOM, SID_ZOOM_OUT, SID_ZOOM_IN, SID_ATTR_ZOOMSLIDER, FN_PREVIEW_ZOOM, FN_STAT_ZOOM,
0
};
rBindings.Invalidate( aInval );
}
// At first the zoom dialog
class SwPreviewZoomDlg : public weld::GenericDialogController
{
SwPagePreviewWin& m_rParent;
std::unique_ptr<weld::SpinButton> m_xRowEdit;
std::unique_ptr<weld::SpinButton> m_xColEdit;
public:
SwPreviewZoomDlg(SwPagePreviewWin& rParent)
: GenericDialogController(rParent.GetFrameWeld(), "modules/swriter/ui/previewzoomdialog.ui", "PreviewZoomDialog")
, m_rParent(rParent)
, m_xRowEdit(m_xBuilder->weld_spin_button("rows"))
, m_xColEdit(m_xBuilder->weld_spin_button("cols"))
{
m_xRowEdit->set_value(rParent.GetRow());
m_xColEdit->set_value(rParent.GetCol());
}
void execute()
{
if (run() == RET_OK)
{
m_rParent.CalcWish(sal_uInt8(m_xRowEdit->get_value()), sal_uInt8(m_xColEdit->get_value()));
}
}
};
// all for SwPagePreviewWin
SwPagePreviewWin::SwPagePreviewWin( vcl::Window *pParent, SwPagePreview& rPView )
: Window(pParent, WinBits(WB_CLIPCHILDREN))
, mpViewShell(nullptr)
, mrView(rPView)
, mbCalcScaleForPreviewLayout(true)
, maPaintedPreviewDocRect(tools::Rectangle(0,0,0,0))
, mpPgPreviewLayout(nullptr)
{
SetOutDevViewType( OutDevViewType::PrintPreview );
SetHelpId(HID_PAGEPREVIEW);
SetFillColor( GetBackground().GetColor() );
SetLineColor( GetBackground().GetColor());
SetMapMode( MapMode(MapUnit::MapTwip) );
const SwMasterUsrPref *pUsrPref = SW_MOD()->GetUsrPref(false);
mnRow = pUsrPref->GetPagePrevRow(); // 1 row
mnCol = pUsrPref->GetPagePrevCol(); // 1 column
mnSttPage = USHRT_MAX;
}
SwPagePreviewWin::~SwPagePreviewWin()
{
}
void SwPagePreviewWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
{
if (!mpViewShell || !mpViewShell->GetLayout())
return;
if (USHRT_MAX == mnSttPage) // was never calculated ? (Init-Phase!)
{
// This is the size to which I always relate.
if (!maPxWinSize.Height() || !maPxWinSize.Width())
maPxWinSize = GetOutputSizePixel();
tools::Rectangle aRect(rRenderContext.LogicToPixel(rRect));
mpPgPreviewLayout->Prepare(1, Point(0,0), maPxWinSize,
mnSttPage, maPaintedPreviewDocRect);
SetSelectedPage(1);
mpPgPreviewLayout->Paint(rRenderContext, rRenderContext.PixelToLogic(aRect));
SetPagePreview(mnRow, mnCol);
}
else
{
MapMode aMM(rRenderContext.GetMapMode());
aMM.SetScaleX(maScale);
aMM.SetScaleY(maScale);
rRenderContext.SetMapMode(aMM);
mpPgPreviewLayout->GetParentViewShell().setOutputToWindow(true);
mpPgPreviewLayout->Paint(rRenderContext, rRect);
mpPgPreviewLayout->GetParentViewShell().setOutputToWindow(false);
}
}
void SwPagePreviewWin::CalcWish( sal_uInt8 nNewRow, sal_uInt8 nNewCol )
{
if( !mpViewShell || !mpViewShell->GetLayout() )
return;
const sal_uInt8 nOldCol = mnCol;
mnRow = nNewRow;
mnCol = nNewCol;
const sal_uInt16 nPages = mnRow * mnCol;
const sal_uInt16 nLastSttPg = mrView.GetPageCount()+1 > nPages
? mrView.GetPageCount()+1 - nPages : 0;
if( mnSttPage > nLastSttPg )
mnSttPage = nLastSttPg;
mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
mnSttPage, maPaintedPreviewDocRect );
SetSelectedPage( mnSttPage );
SetPagePreview(mnRow, mnCol);
maScale = GetMapMode().GetScaleX();
// If changes have taken place at the columns, the special case "single column"
// must be considered and corrected if necessary.
if( (1 == nOldCol) != (1 == mnCol) )
mrView.ScrollDocSzChg();
// Order must be maintained!
// additional invalidate page status.
static sal_uInt16 aInval[] =
{
SID_ATTR_ZOOM, SID_ZOOM_OUT, SID_ZOOM_IN,
FN_PREVIEW_ZOOM,
FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
FN_STAT_PAGE, FN_STAT_ZOOM,
FN_SHOW_TWO_PAGES, FN_SHOW_MULTIPLE_PAGES,
0
};
SfxBindings& rBindings = mrView.GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
rBindings.Update( FN_SHOW_TWO_PAGES );
rBindings.Update( FN_SHOW_MULTIPLE_PAGES );
// adjust scrollbars
mrView.ScrollViewSzChg();
}
// mnSttPage is Absolute
bool SwPagePreviewWin::MovePage( int eMoveMode )
{
// number of pages up
const sal_uInt16 nPages = mnRow * mnCol;
sal_uInt16 nNewSttPage = mnSttPage;
const sal_uInt16 nPageCount = mrView.GetPageCount();
const sal_uInt16 nDefSttPg = GetDefSttPage();
bool bPaintPageAtFirstCol = true;
switch( eMoveMode )
{
case MV_PAGE_UP:
{
const sal_uInt16 nRelSttPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( mnSttPage );
const sal_uInt16 nNewAbsSttPage = nRelSttPage - nPages > 0 ?
mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSttPage - nPages ) :
nDefSttPg;
nNewSttPage = nNewAbsSttPage;
const sal_uInt16 nRelSelPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( SelectedPage() );
const sal_uInt16 nNewRelSelPage = nRelSelPage - nPages > 0 ?
nRelSelPage - nPages :
1;
SetSelectedPage( mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nNewRelSelPage ) );
break;
}
case MV_PAGE_DOWN:
{
const sal_uInt16 nRelSttPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( mnSttPage );
const sal_uInt16 nNewAbsSttPage = mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSttPage + nPages );
nNewSttPage = std::min(nNewAbsSttPage, nPageCount);
const sal_uInt16 nRelSelPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( SelectedPage() );
const sal_uInt16 nNewAbsSelPage = mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSelPage + nPages );
SetSelectedPage( std::min(nNewAbsSelPage, nPageCount) );
break;
}
case MV_DOC_STT:
nNewSttPage = nDefSttPg;
SetSelectedPage( mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nNewSttPage ? nNewSttPage : 1 ) );
break;
case MV_DOC_END:
// correct calculation of new start page.
nNewSttPage = nPageCount;
SetSelectedPage( nPageCount );
break;
case MV_SELPAGE:
// <nNewSttPage> and <SelectedPage()> are already set.
// not start at first column, only if the
// complete preview layout columns doesn't fit into window.
if ( !mpPgPreviewLayout->DoesPreviewLayoutColsFitIntoWindow() )
bPaintPageAtFirstCol = false;
break;
case MV_SCROLL:
// check, if paint page at first column
// has to be avoided
if ( !mpPgPreviewLayout->DoesPreviewLayoutRowsFitIntoWindow() ||
!mpPgPreviewLayout->DoesPreviewLayoutColsFitIntoWindow() )
bPaintPageAtFirstCol = false;
break;
case MV_NEWWINSIZE:
// nothing special to do.
break;
case MV_CALC:
// re-init page preview layout.
mpPgPreviewLayout->ReInit();
// correct calculation of new start page.
if( nNewSttPage > nPageCount )
nNewSttPage = nPageCount;
// correct selected page number
if( SelectedPage() > nPageCount )
SetSelectedPage( nNewSttPage ? nNewSttPage : 1 );
}
mpPgPreviewLayout->Prepare( nNewSttPage, Point(0,0), maPxWinSize,
nNewSttPage,
maPaintedPreviewDocRect, bPaintPageAtFirstCol );
if( nNewSttPage == mnSttPage &&
eMoveMode != MV_SELPAGE )
return false;
SetPagePreview(mnRow, mnCol);
mnSttPage = nNewSttPage;
// additional invalidate page status.
static sal_uInt16 aInval[] =
{
FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
FN_STAT_PAGE, 0
};
SfxBindings& rBindings = mrView.GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
return true;
}
void SwPagePreviewWin::SetWinSize( const Size& rNewSize )
{
// We always want the size as pixel units.
maPxWinSize = LogicToPixel( rNewSize );
if( USHRT_MAX == mnSttPage )
{
mnSttPage = GetDefSttPage();
SetSelectedPage( GetDefSttPage() );
}
if ( mbCalcScaleForPreviewLayout )
{
mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
maScale = GetMapMode().GetScaleX();
}
mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
mnSttPage, maPaintedPreviewDocRect );
if ( mbCalcScaleForPreviewLayout )
{
SetSelectedPage( mnSttPage );
mbCalcScaleForPreviewLayout = false;
}
SetPagePreview(mnRow, mnCol);
maScale = GetMapMode().GetScaleX();
}
OUString SwPagePreviewWin::GetStatusStr( sal_uInt16 nPageCnt ) const
{
// show physical and virtual page number of
// selected page, if it's visible.
const sal_uInt16 nPageNum = mpPgPreviewLayout->IsPageVisible( mpPgPreviewLayout->SelectedPage() )
? mpPgPreviewLayout->SelectedPage() : std::max<sal_uInt16>(mnSttPage, 1);
OUStringBuffer aStatusStr;
const sal_uInt16 nVirtPageNum = mpPgPreviewLayout->GetVirtPageNumByPageNum( nPageNum );
if( nVirtPageNum && nVirtPageNum != nPageNum )
{
aStatusStr.append( OUString::number(nVirtPageNum) ).append( " " );
}
aStatusStr.append( OUString::number(nPageNum) ).append( " / " ).append( OUString::number(nPageCnt) );
return aStatusStr.makeStringAndClear();
}
void SwPagePreviewWin::KeyInput( const KeyEvent &rKEvt )
{
const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
bool bHandled = false;
if(!rKeyCode.GetModifier())
{
sal_uInt16 nSlot = 0;
switch(rKeyCode.GetCode())
{
case KEY_ADD : nSlot = SID_ZOOM_OUT; break;
case KEY_ESCAPE: nSlot = FN_CLOSE_PAGEPREVIEW; break;
case KEY_SUBTRACT : nSlot = SID_ZOOM_IN; break;
}
if(nSlot)
{
bHandled = true;
mrView.GetViewFrame()->GetDispatcher()->Execute(
nSlot, SfxCallMode::ASYNCHRON );
}
}
if( !bHandled && !mrView.KeyInput( rKEvt ) )
Window::KeyInput( rKEvt );
}
void SwPagePreviewWin::Command( const CommandEvent& rCEvt )
{
bool bCallBase = true;
switch( rCEvt.GetCommand() )
{
case CommandEventId::ContextMenu:
SfxDispatcher::ExecutePopup();
bCallBase = false;
break;
case CommandEventId::Wheel:
case CommandEventId::StartAutoScroll:
case CommandEventId::AutoScroll:
{
const CommandWheelData* pData = rCEvt.GetWheelData();
if( pData )
{
const CommandWheelData aDataNew(pData->GetDelta(),pData->GetNotchDelta(),COMMAND_WHEEL_PAGESCROLL,
pData->GetMode(),pData->GetModifier(),pData->IsHorz(), pData->IsDeltaPixel());
const CommandEvent aEvent( rCEvt.GetMousePosPixel(),rCEvt.GetCommand(),rCEvt.IsMouseEvent(),&aDataNew);
bCallBase = !mrView.HandleWheelCommands( aEvent );
}
else
bCallBase = !mrView.HandleWheelCommands( rCEvt );
}
break;
default:
;
}
if( bCallBase )
Window::Command( rCEvt );
}
void SwPagePreviewWin::MouseButtonDown( const MouseEvent& rMEvt )
{
// consider single-click to set selected page
if( MOUSE_LEFT == ( rMEvt.GetModifier() + rMEvt.GetButtons() ) )
{
Point aPreviewPos( PixelToLogic( rMEvt.GetPosPixel() ) );
Point aDocPos;
bool bPosInEmptyPage;
sal_uInt16 nNewSelectedPage;
bool bIsDocPos =
mpPgPreviewLayout->IsPreviewPosInDocPreviewPage( aPreviewPos,
aDocPos, bPosInEmptyPage, nNewSelectedPage );
if ( bIsDocPos && rMEvt.GetClicks() == 2 )
{
// close page preview, set new cursor position and switch to
// normal view.
OUString sNewCursorPos = OUString::number( aDocPos.X() ) + ";" +
OUString::number( aDocPos.Y() ) + ";";
mrView.SetNewCursorPos( sNewCursorPos );
SfxViewFrame *pTmpFrame = mrView.GetViewFrame();
pTmpFrame->GetBindings().Execute( SID_VIEWSHELL0, nullptr,
SfxCallMode::ASYNCHRON );
}
else if ( bIsDocPos || bPosInEmptyPage )
{
// show clicked page as the selected one
mpPgPreviewLayout->MarkNewSelectedPage( nNewSelectedPage );
GetViewShell()->ShowPreviewSelection( nNewSelectedPage );
// adjust position at vertical scrollbar.
if ( mpPgPreviewLayout->DoesPreviewLayoutRowsFitIntoWindow() )
{
mrView.SetVScrollbarThumbPos( nNewSelectedPage );
}
// invalidate page status.
static sal_uInt16 aInval[] =
{
FN_STAT_PAGE, 0
};
SfxBindings& rBindings = mrView.GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
}
}
}
// Set user prefs or view options
void SwPagePreviewWin::SetPagePreview( sal_uInt8 nRow, sal_uInt8 nCol )
{
SwMasterUsrPref *pOpt = const_cast<SwMasterUsrPref *>(SW_MOD()->GetUsrPref(false));
if (nRow != pOpt->GetPagePrevRow() || nCol != pOpt->GetPagePrevCol())
{
pOpt->SetPagePrevRow( nRow );
pOpt->SetPagePrevCol( nCol );
pOpt->SetModified();
// Update scrollbar!
mrView.ScrollViewSzChg();
}
}
/** get selected page in document preview */
sal_uInt16 SwPagePreviewWin::SelectedPage() const
{
return mpPgPreviewLayout->SelectedPage();
}
/** set selected page number in document preview */
void SwPagePreviewWin::SetSelectedPage( sal_uInt16 _nSelectedPageNum )
{
mpPgPreviewLayout->SetSelectedPage( _nSelectedPageNum );
}
/** method to enable/disable book preview */
bool SwPagePreviewWin::SetBookPreviewMode( const bool _bBookPreview )
{
return mpPgPreviewLayout->SetBookPreviewMode( _bBookPreview,
mnSttPage,
maPaintedPreviewDocRect );
}
void SwPagePreviewWin::DataChanged( const DataChangedEvent& rDCEvt )
{
Window::DataChanged( rDCEvt );
switch( rDCEvt.GetType() )
{
case DataChangedEventType::SETTINGS:
// Rearrange the scrollbars or trigger resize, because the
// size of the scrollbars may have be changed. Also the
// size of the scrollbars has to be retrieved from the settings
// out of the resize handler.
if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
mrView.InvalidateBorder(); // Scrollbar widths
// zoom has to be disabled if Accessibility support is switched on
lcl_InvalidateZoomSlots(mrView.GetViewFrame()->GetBindings());
break;
case DataChangedEventType::PRINTER:
case DataChangedEventType::DISPLAY:
case DataChangedEventType::FONTS:
case DataChangedEventType::FONTSUBSTITUTION:
mrView.GetDocShell()->UpdateFontList(); // Font change
mpViewShell->InvalidateLayout(true);
if ( mpViewShell->GetWin() )
mpViewShell->GetWin()->Invalidate();
break;
default: break;
}
}
/** help method to execute SfxRequest FN_PAGEUP and FN_PAGEDOWN */
void SwPagePreview::ExecPgUpAndPgDown( const bool _bPgUp,
SfxRequest* _pReq )
{
SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
// check, if top/bottom of preview is *not* already visible.
if( pPagePreviewLay->GetWinPagesScrollAmount( _bPgUp ? -1 : 1 ) != 0 )
{
if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() &&
pPagePreviewLay->DoesPreviewLayoutColsFitIntoWindow() )
{
const int eMvMode = _bPgUp ?
SwPagePreviewWin::MV_PAGE_UP :
SwPagePreviewWin::MV_PAGE_DOWN;
if ( ChgPage( eMvMode ) )
m_pViewWin->Invalidate();
}
else
{
SwTwips nScrollAmount;
sal_uInt16 nNewSelectedPageNum = 0;
const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
if( _bPgUp )
{
if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() )
{
nScrollAmount = pPagePreviewLay->GetWinPagesScrollAmount( -1 );
if ( (m_pViewWin->SelectedPage() - nVisPages) > 0 )
nNewSelectedPageNum = m_pViewWin->SelectedPage() - nVisPages;
else
nNewSelectedPageNum = 1;
}
else
nScrollAmount = - std::min( m_pViewWin->GetOutputSize().Height(),
m_pViewWin->GetPaintedPreviewDocRect().Top() );
}
else
{
if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() )
{
nScrollAmount = pPagePreviewLay->GetWinPagesScrollAmount( 1 );
if ( (m_pViewWin->SelectedPage() + nVisPages) <= mnPageCount )
nNewSelectedPageNum = m_pViewWin->SelectedPage() + nVisPages;
else
nNewSelectedPageNum = mnPageCount;
}
else
nScrollAmount = std::min( m_pViewWin->GetOutputSize().Height(),
( pPagePreviewLay->GetPreviewDocSize().Height() -
m_pViewWin->GetPaintedPreviewDocRect().Bottom() ) );
}
m_pViewWin->Scroll( 0, nScrollAmount );
if ( nNewSelectedPageNum != 0 )
{
m_pViewWin->SetSelectedPage( nNewSelectedPageNum );
}
ScrollViewSzChg();
// additional invalidate page status.
static sal_uInt16 aInval[] =
{
FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
FN_STAT_PAGE, 0
};
SfxBindings& rBindings = GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
m_pViewWin->Invalidate();
}
}
if ( _pReq )
_pReq->Done();
}
// Then all for the SwPagePreview
void SwPagePreview::Execute( SfxRequest &rReq )
{
int eMvMode;
sal_uInt8 nRow = 1;
bool bRetVal = false;
bool bRefresh = true;
switch(rReq.GetSlot())
{
case FN_REFRESH_VIEW:
case FN_STAT_PAGE:
case FN_STAT_ZOOM:
break;
case FN_SHOW_MULTIPLE_PAGES:
{
const SfxItemSet *pArgs = rReq.GetArgs();
if( pArgs && pArgs->Count() >= 2 )
{
sal_uInt8 nCols = static_cast<sal_uInt8>(pArgs->Get(SID_ATTR_TABLE_COLUMN).GetValue());
sal_uInt8 nRows = static_cast<sal_uInt8>(pArgs->Get(SID_ATTR_TABLE_ROW).GetValue());
m_pViewWin->CalcWish( nRows, nCols );
}
else
{
SwPreviewZoomDlg aDlg(*m_pViewWin);
aDlg.execute();
}
}
break;
case FN_SHOW_BOOKVIEW:
{
const SfxItemSet* pArgs = rReq.GetArgs();
const SfxPoolItem* pItem;
bool bBookPreview = GetViewShell()->GetViewOptions()->IsPagePrevBookview();
if( pArgs && SfxItemState::SET == pArgs->GetItemState( FN_SHOW_BOOKVIEW, false, &pItem ) )
{
bBookPreview = static_cast< const SfxBoolItem* >( pItem )->GetValue();
const_cast<SwViewOption*>(GetViewShell()->GetViewOptions())->SetPagePrevBookview( bBookPreview );
// cast is not gentleman like, but it's common use in writer and in this case
}
if ( m_pViewWin->SetBookPreviewMode( bBookPreview ) )
{
// book preview mode changed. Thus, adjust scrollbars and
// invalidate corresponding states.
ScrollViewSzChg();
static sal_uInt16 aInval[] =
{
FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
FN_STAT_PAGE, FN_SHOW_BOOKVIEW, 0
};
SfxBindings& rBindings = GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
m_pViewWin->Invalidate();
}
}
break;
case FN_SHOW_TWO_PAGES:
m_pViewWin->CalcWish( nRow, 2 );
break;
case FN_SHOW_SINGLE_PAGE:
m_pViewWin->CalcWish( nRow, 1 );
break;
case FN_PREVIEW_ZOOM:
case SID_ATTR_ZOOM:
{
const SfxItemSet *pArgs = rReq.GetArgs();
const SfxPoolItem* pItem;
ScopedVclPtr<AbstractSvxZoomDialog> pDlg;
if(!pArgs)
{
SfxItemSet aCoreSet(GetPool(), svl::Items<SID_ATTR_ZOOM, SID_ATTR_ZOOM>{});
const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
SvxZoomItem aZoom( pVOpt->GetZoomType(), pVOpt->GetZoom() );
aZoom.SetValueSet(
SvxZoomEnableFlags::N50|
SvxZoomEnableFlags::N75|
SvxZoomEnableFlags::N100|
SvxZoomEnableFlags::N150|
SvxZoomEnableFlags::N200|
SvxZoomEnableFlags::WHOLEPAGE);
aCoreSet.Put( aZoom );
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
pDlg.disposeAndReset(pFact->CreateSvxZoomDialog(GetViewFrame()->GetWindow().GetFrameWeld(), aCoreSet));
pDlg->SetLimits( MINZOOM, MAXZOOM );
if( pDlg->Execute() != RET_CANCEL )
pArgs = pDlg->GetOutputItemSet();
}
if( pArgs )
{
SvxZoomType eType = SvxZoomType::PERCENT;
sal_uInt16 nZoomFactor = USHRT_MAX;
if(SfxItemState::SET == pArgs->GetItemState(SID_ATTR_ZOOM, true, &pItem))
{
eType = static_cast<const SvxZoomItem *>(pItem)->GetType();
nZoomFactor = static_cast<const SvxZoomItem *>(pItem)->GetValue();
}
else if(SfxItemState::SET == pArgs->GetItemState(FN_PREVIEW_ZOOM, true, &pItem))
nZoomFactor = static_cast<const SfxUInt16Item *>(pItem)->GetValue();
if(USHRT_MAX != nZoomFactor)
SetZoom(eType, nZoomFactor);
}
}
break;
case SID_ATTR_ZOOMSLIDER :
{
const SfxItemSet *pArgs = rReq.GetArgs();
const SfxPoolItem* pItem;
if ( pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_ZOOMSLIDER, true, &pItem ) )
{
const sal_uInt16 nCurrentZoom = static_cast<const SvxZoomSliderItem *>(pItem)->GetValue();
SetZoom( SvxZoomType::PERCENT, nCurrentZoom );
}
}
break;
case SID_ZOOM_IN:
case SID_ZOOM_OUT:
{
const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
SetZoom(SvxZoomType::PERCENT,
lcl_GetNextZoomStep(pVOpt->GetZoom(), SID_ZOOM_IN == rReq.GetSlot()));
}
break;
case FN_CHAR_LEFT:
case FN_CHAR_RIGHT:
case FN_LINE_UP:
case FN_LINE_DOWN:
{
SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
sal_uInt16 nNewSelectedPage;
sal_uInt16 nNewStartPage;
Point aNewStartPos;
sal_Int16 nHoriMove = 0;
sal_Int16 nVertMove = 0;
switch(rReq.GetSlot())
{
case FN_CHAR_LEFT: nHoriMove = -1; break;
case FN_CHAR_RIGHT: nHoriMove = 1; break;
case FN_LINE_UP: nVertMove = -1; break;
case FN_LINE_DOWN: nVertMove = 1; break;
}
pPagePreviewLay->CalcStartValuesForSelectedPageMove( nHoriMove, nVertMove,
nNewSelectedPage, nNewStartPage, aNewStartPos );
if ( m_pViewWin->SelectedPage() != nNewSelectedPage )
{
if ( pPagePreviewLay->IsPageVisible( nNewSelectedPage ) )
{
pPagePreviewLay->MarkNewSelectedPage( nNewSelectedPage );
// adjust position at vertical scrollbar.
SetVScrollbarThumbPos( nNewSelectedPage );
bRefresh = false;
}
else
{
m_pViewWin->SetSelectedPage( nNewSelectedPage );
m_pViewWin->SetSttPage( nNewStartPage );
bRefresh = ChgPage( SwPagePreviewWin::MV_SELPAGE );
}
GetViewShell()->ShowPreviewSelection( nNewSelectedPage );
// invalidate page status.
static sal_uInt16 aInval[] =
{
FN_STAT_PAGE, 0
};
SfxBindings& rBindings = GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
rReq.Done();
}
else
{
bRefresh = false;
}
break;
}
case FN_PAGEUP:
case FN_PAGEDOWN:
{
ExecPgUpAndPgDown( rReq.GetSlot() == FN_PAGEUP, &rReq );
break;
}
case SID_JUMP_TO_SPECIFIC_PAGE:
{
sal_uInt16 nPageNum = 1;
const SfxItemSet *pArgs = rReq.GetArgs();
if( pArgs && pArgs->Count())
{
nPageNum = static_cast<const SfxUInt16Item &>(pArgs->Get(SID_JUMP_TO_SPECIFIC_PAGE)).GetValue();
if( nPageNum > 0 && nPageNum <= mnPageCount )
{
m_pViewWin->SetSttPage( nPageNum);
m_pViewWin->SetSelectedPage( nPageNum );
ChgPage( SwPagePreviewWin::MV_SPECIFIC_PAGE, false );
ScrollViewSzChg();
}
}
}
break;
case FN_START_OF_LINE:
case FN_START_OF_DOCUMENT:
m_pViewWin->SetSelectedPage( 1 );
eMvMode = SwPagePreviewWin::MV_DOC_STT; bRetVal = true; goto MOVEPAGE;
case FN_END_OF_LINE:
case FN_END_OF_DOCUMENT:
m_pViewWin->SetSelectedPage( mnPageCount );
eMvMode = SwPagePreviewWin::MV_DOC_END; bRetVal = true; goto MOVEPAGE;
MOVEPAGE:
{
bool bRet = ChgPage( eMvMode );
// return value for Basic
if(bRetVal)
rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), !bRet));
bRefresh = bRet;
rReq.Done();
}
break;
case FN_PRINT_PAGEPREVIEW:
{
const SwPagePreviewPrtData* pPPVPD = m_pViewWin->GetViewShell()->GetDoc()->GetPreviewPrtData();
// The thing with the orientation
if(pPPVPD)
{
SfxPrinter* pPrinter = GetPrinter( true );
if((pPrinter->GetOrientation() == Orientation::Landscape)
!= pPPVPD->GetLandscape())
pPrinter->SetOrientation(pPPVPD->GetLandscape() ? Orientation::Landscape : Orientation::Portrait);
}
::SetAppPrintOptions( m_pViewWin->GetViewShell(), false );
m_bNormalPrint = false;
rReq.SetSlot( SID_PRINTDOC );
SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
rReq.SetSlot( FN_PRINT_PAGEPREVIEW );
return;
}
case SID_PRINTDOCDIRECT:
case SID_PRINTDOC:
::SetAppPrintOptions( m_pViewWin->GetViewShell(), false );
m_bNormalPrint = true;
SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
return;
case FN_CLOSE_PAGEPREVIEW:
case SID_PRINTPREVIEW:
// print preview is now always in the same frame as the tab view
// -> always switch this frame back to normal view
// (ScTabViewShell ctor reads stored view data)
GetViewFrame()->GetDispatcher()->Execute( SID_VIEWSHELL0, SfxCallMode::ASYNCHRON );
break;
case FN_INSERT_BREAK:
{
sal_uInt16 nSelPage = m_pViewWin->SelectedPage();
//if a dummy page is selected (e.g. a non-existing right/left page)
//the direct neighbor is used
if(GetViewShell()->IsDummyPage( nSelPage ) && GetViewShell()->IsDummyPage( --nSelPage ))
nSelPage +=2;
m_nNewPage = nSelPage;
SfxViewFrame *pTmpFrame = GetViewFrame();
pTmpFrame->GetBindings().Execute( SID_VIEWSHELL0, nullptr,
SfxCallMode::ASYNCHRON );
}
break;
default:
OSL_ENSURE(false, "wrong dispatcher");
return;
}
if( bRefresh )
m_pViewWin->Invalidate();
}
void SwPagePreview::GetState( SfxItemSet& rSet )
{
SfxWhichIter aIter(rSet);
sal_uInt16 nWhich = aIter.FirstWhich();
OSL_ENSURE(nWhich, "empty set");
SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
while(nWhich)
{
switch(nWhich)
{
case SID_BROWSER_MODE:
case FN_PRINT_LAYOUT:
rSet.DisableItem(nWhich);
break;
case FN_START_OF_DOCUMENT:
{
if ( pPagePreviewLay->IsPageVisible( 1 ) )
rSet.DisableItem(nWhich);
break;
}
case FN_END_OF_DOCUMENT:
{
if ( pPagePreviewLay->IsPageVisible( mnPageCount ) )
rSet.DisableItem(nWhich);
break;
}
case FN_PAGEUP:
{
if( pPagePreviewLay->GetWinPagesScrollAmount( -1 ) == 0 )
rSet.DisableItem(nWhich);
break;
}
case FN_PAGEDOWN:
{
if( pPagePreviewLay->GetWinPagesScrollAmount( 1 ) == 0 )
rSet.DisableItem(nWhich);
break;
}
case FN_STAT_PAGE:
{
OUString aStr = m_sPageStr + m_pViewWin->GetStatusStr( mnPageCount );
rSet.Put( SfxStringItem( nWhich, aStr) );
}
break;
case SID_ATTR_ZOOM:
case FN_STAT_ZOOM:
{
const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
SvxZoomItem aZoom(pVOpt->GetZoomType(), pVOpt->GetZoom());
aZoom.SetValueSet(
SvxZoomEnableFlags::N50|
SvxZoomEnableFlags::N75|
SvxZoomEnableFlags::N100|
SvxZoomEnableFlags::N150|
SvxZoomEnableFlags::N200);
rSet.Put( aZoom );
}
break;
case SID_ATTR_ZOOMSLIDER :
{
const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
const sal_uInt16 nCurrentZoom = pVOpt->GetZoom();
SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM );
aZoomSliderItem.AddSnappingPoint( 100 );
rSet.Put( aZoomSliderItem );
}
break;
case FN_PREVIEW_ZOOM:
{
const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
rSet.Put(SfxUInt16Item(nWhich, pVOpt->GetZoom()));
}
break;
case SID_ZOOM_IN:
case SID_ZOOM_OUT:
{
const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
if((SID_ZOOM_OUT == nWhich && pVOpt->GetZoom() >= MAX_PREVIEW_ZOOM)||
(SID_ZOOM_IN == nWhich && pVOpt->GetZoom() <= MIN_PREVIEW_ZOOM))
{
rSet.DisableItem(nWhich);
}
}
break;
case FN_SHOW_MULTIPLE_PAGES:
// should never be disabled
break;
case FN_SHOW_BOOKVIEW:
{
bool b = GetViewShell()->GetViewOptions()->IsPagePrevBookview();
rSet.Put(SfxBoolItem(nWhich, b));
}
break;
case FN_SHOW_TWO_PAGES:
if( 2 == m_pViewWin->GetCol() && 1 == m_pViewWin->GetRow() )
rSet.DisableItem( nWhich );
break;
case FN_PRINT_PAGEPREVIEW:
// has the same status like the normal printing
{
const SfxPoolItem* pItem;
SfxItemSet aSet( *rSet.GetPool(), svl::Items<SID_PRINTDOC, SID_PRINTDOC>{} );
GetSlotState( SID_PRINTDOC, SfxViewShell::GetInterface(), &aSet );
if( SfxItemState::DISABLED == aSet.GetItemState( SID_PRINTDOC,
false, &pItem ))
rSet.DisableItem( nWhich );
else if( SfxItemState::SET == aSet.GetItemState( SID_PRINTDOC,
false, &pItem ))
{
const_cast<SfxPoolItem*>(pItem)->SetWhich( FN_PRINT_PAGEPREVIEW );
rSet.Put( *pItem );
}
}
break;
case SID_PRINTPREVIEW:
rSet.Put( SfxBoolItem( nWhich, true ) );
break;
case SID_PRINTDOC:
case SID_PRINTDOCDIRECT:
GetSlotState( nWhich, SfxViewShell::GetInterface(), &rSet );
break;
}
nWhich = aIter.NextWhich();
}
}
void SwPagePreview::StateUndo(SfxItemSet& rSet)
{
SfxWhichIter aIter(rSet);
sal_uInt16 nWhich = aIter.FirstWhich();
while (nWhich)
{
rSet.DisableItem(nWhich);
nWhich = aIter.NextWhich();
}
}
void SwPagePreview::Init()
{
if ( GetViewShell()->HasDrawView() )
GetViewShell()->GetDrawView()->SetAnimationEnabled( false );
m_bNormalPrint = true;
// Check and process the DocSize. The shell could not be found via
// the handler, because the shell is unknown to the SFX management
// within the CTOR phase.
const SwViewOption * pPrefs = SW_MOD()->GetUsrPref(false);
mbHScrollbarEnabled = pPrefs->IsViewHScrollBar();
mbVScrollbarEnabled = pPrefs->IsViewVScrollBar();
// Update the fields
// ATTENTION: Do cast the EditShell up, to use the SS.
// At the methods the current shell will be queried!
SwEditShell* pESh = dynamic_cast<SwEditShell*>(GetViewShell());
bool bIsModified = pESh != nullptr && pESh->IsModified();
SwViewOption aOpt( *pPrefs );
aOpt.SetPagePreview(true);
aOpt.SetTab( false );
aOpt.SetBlank( false );
aOpt.SetHardBlank( false );
aOpt.SetParagraph( false );
aOpt.SetLineBreak( false );
aOpt.SetPageBreak( false );
aOpt.SetColumnBreak( false );
aOpt.SetSoftHyph( false );
aOpt.SetFieldName( false );
aOpt.SetPostIts( false );
aOpt.SetShowHiddenChar( false );
aOpt.SetShowHiddenField( false );
aOpt.SetShowHiddenPara( false );
aOpt.SetViewHRuler( false );
aOpt.SetViewVRuler( false );
aOpt.SetGraphic( true );
aOpt.SetTable( true );
aOpt.SetSnap( false );
aOpt.SetGridVisible( false );
aOpt.SetOnlineSpell( false );
aOpt.SetHideWhitespaceMode( false );
GetViewShell()->ApplyViewOptions( aOpt );
GetViewShell()->ApplyAccessiblityOptions(SW_MOD()->GetAccessibilityOptions());
// adjust view shell option to the same as for print
SwPrintData const aPrintOptions = *SW_MOD()->GetPrtOptions(false);
GetViewShell()->AdjustOptionsForPagePreview( aPrintOptions );
GetViewShell()->CalcLayout();
DocSzChgd( GetViewShell()->GetDocSize() );
if( !bIsModified && pESh != nullptr )
pESh->ResetModified();
}
SwPagePreview::SwPagePreview(SfxViewFrame *pViewFrame, SfxViewShell* pOldSh):
SfxViewShell( pViewFrame, SWVIEWFLAGS ),
m_pViewWin( VclPtr<SwPagePreviewWin>::Create(&GetViewFrame()->GetWindow(), *this ) ),
m_nNewPage(USHRT_MAX),
m_sPageStr(SwResId(STR_PAGE)),
m_pHScrollbar(nullptr),
m_pVScrollbar(nullptr),
m_pScrollFill(VclPtr<ScrollBarBox>::Create( &pViewFrame->GetWindow(), WB_SIZEABLE )),
mnPageCount( 0 ),
mbResetFormDesignMode( false ),
mbFormDesignModeToReset( false )
{
SetName("PageView");
SetWindow( m_pViewWin );
CreateScrollbar( true );
CreateScrollbar( false );
//notify notebookbar change in context
SfxShell::SetContextBroadcasterEnabled(true);
SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Printpreview));
SfxShell::BroadcastContextForActivation(true);
//removelisteners for notebookbar
if (auto& pBar = SfxViewFrame::Current()->GetWindow().GetSystemWindow()->GetNotebookBar())
pBar->ControlListener(true);
SfxObjectShell* pObjShell = pViewFrame->GetObjectShell();
if ( !pOldSh )
{
// Exists already a view on the document?
SfxViewFrame *pF = SfxViewFrame::GetFirst( pObjShell );
if ( pF == pViewFrame )
pF = SfxViewFrame::GetNext( *pF, pObjShell );
if ( pF )
pOldSh = pF->GetViewShell();
}
SwViewShell *pVS, *pNew;
if (SwPagePreview* pPagePreview = dynamic_cast<SwPagePreview*>(pOldSh))
pVS = pPagePreview->GetViewShell();
else
{
if (SwView* pView = dynamic_cast<SwView *>(pOldSh))
{
pVS = pView->GetWrtShellPtr();
// save the current ViewData of the previous SwView
pOldSh->WriteUserData( m_sSwViewData );
}
else
pVS = GetDocShell()->GetWrtShell();
if( pVS )
{
// Set the current page as the first.
sal_uInt16 nPhysPg, nVirtPg;
static_cast<SwCursorShell*>(pVS)->GetPageNum( nPhysPg, nVirtPg, true, false );
if( 1 != m_pViewWin->GetCol() && 1 == nPhysPg )
--nPhysPg;
m_pViewWin->SetSttPage( nPhysPg );
}
}
// for form shell remember design mode of draw view
// of previous view shell
if ( pVS && pVS->HasDrawView() )
{
mbResetFormDesignMode = true;
mbFormDesignModeToReset = pVS->GetDrawView()->IsDesignMode();
}
if( pVS )
pNew = new SwViewShell( *pVS, m_pViewWin, nullptr, VSHELLFLAG_ISPREVIEW );
else
pNew = new SwViewShell(
*static_cast<SwDocShell*>(pViewFrame->GetObjectShell())->GetDoc(),
m_pViewWin, nullptr, nullptr, VSHELLFLAG_ISPREVIEW );
m_pViewWin->SetViewShell( pNew );
pNew->SetSfxViewShell( this );
Init();
}
SwPagePreview::~SwPagePreview()
{
SetWindow( nullptr );
SwViewShell* pVShell = m_pViewWin->GetViewShell();
pVShell->SetWin(nullptr);
delete pVShell;
m_pViewWin.disposeAndClear();
if (SfxViewFrame* pCurrent = SfxViewFrame::Current())
if (auto& pBar = pCurrent->GetWindow().GetSystemWindow()->GetNotebookBar())
pBar->ControlListener(false);
m_pScrollFill.disposeAndClear();
m_pHScrollbar.disposeAndClear();
m_pVScrollbar.disposeAndClear();
}
SwDocShell* SwPagePreview::GetDocShell()
{
return dynamic_cast<SwDocShell*>( GetViewFrame()->GetObjectShell() );
}
void SwPagePreview::CreateScrollbar( bool bHori )
{
vcl::Window *pMDI = &GetViewFrame()->GetWindow();
VclPtr<SwScrollbar>& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar;
assert(!ppScrollbar.get()); //check beforehand!
ppScrollbar = VclPtr<SwScrollbar>::Create( pMDI, bHori );
ScrollDocSzChg();
ppScrollbar->EnableDrag();
ppScrollbar->SetEndScrollHdl( LINK( this, SwPagePreview, EndScrollHdl ));
ppScrollbar->SetScrollHdl( LINK( this, SwPagePreview, ScrollHdl ));
InvalidateBorder();
ppScrollbar->ExtendedShow();
}
bool SwPagePreview::ChgPage( int eMvMode, bool bUpdateScrollbar )
{
tools::Rectangle aPixVisArea( m_pViewWin->LogicToPixel( m_aVisArea ) );
bool bChg = m_pViewWin->MovePage( eMvMode ) ||
eMvMode == SwPagePreviewWin::MV_CALC ||
eMvMode == SwPagePreviewWin::MV_NEWWINSIZE;
m_aVisArea = m_pViewWin->PixelToLogic( aPixVisArea );
if( bChg )
{
// Update statusbar
OUString aStr = m_sPageStr + m_pViewWin->GetStatusStr( mnPageCount );
SfxBindings& rBindings = GetViewFrame()->GetBindings();
if( bUpdateScrollbar )
{
ScrollViewSzChg();
static sal_uInt16 aInval[] =
{
FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT,
FN_PAGEUP, FN_PAGEDOWN, 0
};
rBindings.Invalidate( aInval );
}
rBindings.SetState( SfxStringItem( FN_STAT_PAGE, aStr ) );
}
return bChg;
}
// From here, everything was taken from the SwView.
void SwPagePreview::CalcAndSetBorderPixel( SvBorder &rToFill )
{
const StyleSettings &rSet = m_pViewWin->GetSettings().GetStyleSettings();
const long nTmp = rSet.GetScrollBarSize();
if ( m_pVScrollbar->IsVisible( true ) )
rToFill.Right() = nTmp;
if ( m_pHScrollbar->IsVisible( true ) )
rToFill.Bottom() = nTmp;
SetBorderPixel( rToFill );
}
void SwPagePreview::InnerResizePixel( const Point &rOfst, const Size &rSize, bool )
{
SvBorder aBorder;
CalcAndSetBorderPixel( aBorder );
tools::Rectangle aRect( rOfst, rSize );
aRect += aBorder;
ViewResizePixel( *m_pViewWin, aRect.TopLeft(), aRect.GetSize(),
m_pViewWin->GetOutputSizePixel(),
*m_pVScrollbar, *m_pHScrollbar, *m_pScrollFill );
// Never set EditWin !
// Never set VisArea !
}
void SwPagePreview::OuterResizePixel( const Point &rOfst, const Size &rSize )
{
SvBorder aBorder;
CalcAndSetBorderPixel( aBorder );
// Never set EditWin !
Size aTmpSize( m_pViewWin->GetOutputSizePixel() );
Point aBottomRight( m_pViewWin->PixelToLogic( Point( aTmpSize.Width(), aTmpSize.Height() ) ) );
SetVisArea( tools::Rectangle( Point(), aBottomRight ) );
// Call of the DocSzChgd-Method of the scrollbars is necessary,
// because from the maximum scroll range half the height of the
// VisArea is always deducted.
if ( m_pVScrollbar && aTmpSize.Width() > 0 && aTmpSize.Height() > 0 )
{
ScrollDocSzChg();
}
SvBorder aBorderNew;
CalcAndSetBorderPixel( aBorderNew );
ViewResizePixel( *m_pViewWin, rOfst, rSize, m_pViewWin->GetOutputSizePixel(),
*m_pVScrollbar, *m_pHScrollbar, *m_pScrollFill );
}
void SwPagePreview::SetVisArea( const tools::Rectangle &rRect )
{
const Point aTopLeft(AlignToPixel(rRect.TopLeft()));
const Point aBottomRight(AlignToPixel(rRect.BottomRight()));
tools::Rectangle aLR(aTopLeft,aBottomRight);
if(aLR == m_aVisArea)
return;
// No negative position, no negative size
if(aLR.Top() < 0)
{
aLR.AdjustBottom(std::abs(aLR.Top()) );
aLR.SetTop( 0 );
}
if(aLR.Left() < 0)
{
aLR.AdjustRight(std::abs(aLR.Left()) );
aLR.SetLeft( 0 );
}
if(aLR.Right() < 0) aLR.SetRight( 0 );
if(aLR.Bottom() < 0) aLR.SetBottom( 0 );
if(aLR == m_aVisArea ||
// Ignore empty rectangle
( 0 == aLR.Bottom() - aLR.Top() && 0 == aLR.Right() - aLR.Left() ) )
return;
if( aLR.Left() > aLR.Right() || aLR.Top() > aLR.Bottom() )
return;
// Before the data can be changed call an update if necessary.
// Thereby ensured, that adjacent paints are correctly converted into
// document coordinates.
// As a precaution, we do this only when at the shell runs an action,
// because then we do not really paint but the rectangles are just
// bookmarked (in document coordinates).
if( GetViewShell()->ActionPend() )
m_pViewWin->Update();
// Set at View-Win the current size
m_aVisArea = aLR;
m_pViewWin->SetWinSize( aLR.GetSize() );
ChgPage( SwPagePreviewWin::MV_NEWWINSIZE );
m_pViewWin->Invalidate();
}
IMPL_LINK( SwPagePreview, ScrollHdl, ScrollBar *, p, void )
{
SwScrollbar* pScrollbar = static_cast<SwScrollbar*>(p);
if(!GetViewShell())
return;
if( !pScrollbar->IsHoriScroll() &&
pScrollbar->GetType() == ScrollType::Drag &&
Help::IsQuickHelpEnabled() &&
GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow())
{
// Scroll how many pages??
OUString sStateStr(m_sPageStr);
long nThmbPos = pScrollbar->GetThumbPos();
if( 1 == m_pViewWin->GetCol() || !nThmbPos )
++nThmbPos;
sStateStr += OUString::number( nThmbPos );
Point aPos = pScrollbar->GetParent()->OutputToScreenPixel(
pScrollbar->GetPosPixel());
aPos.setY( pScrollbar->OutputToScreenPixel(pScrollbar->GetPointerPosPixel()).Y() );
tools::Rectangle aRect;
aRect.SetLeft( aPos.X() -8 );
aRect.SetRight( aRect.Left() );
aRect.SetTop( aPos.Y() );
aRect.SetBottom( aRect.Top() );
Help::ShowQuickHelp(pScrollbar, aRect, sStateStr,
QuickHelpFlags::Right|QuickHelpFlags::VCenter);
}
else
EndScrollHdl( pScrollbar );
}
IMPL_LINK( SwPagePreview, EndScrollHdl, ScrollBar *, p, void )
{
SwScrollbar* pScrollbar = static_cast<SwScrollbar*>(p);
if(!GetViewShell())
return;
// boolean to avoid unnecessary invalidation of the window.
bool bInvalidateWin = true;
if( !pScrollbar->IsHoriScroll() ) // scroll vertically
{
if ( Help::IsQuickHelpEnabled() )
Help::ShowQuickHelp(pScrollbar, tools::Rectangle(), OUString());
if ( GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow() )
{
// Scroll how many pages ??
const sal_uInt16 nThmbPos = static_cast<sal_uInt16>(pScrollbar->GetThumbPos());
// adjust to new preview functionality
if( nThmbPos != m_pViewWin->SelectedPage() )
{
// consider case that page <nThmbPos>
// is already visible
SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
if ( pPagePreviewLay->IsPageVisible( nThmbPos ) )
{
pPagePreviewLay->MarkNewSelectedPage( nThmbPos );
// invalidation of window is unnecessary
bInvalidateWin = false;
}
else
{
// consider whether layout columns
// fit or not.
if ( !pPagePreviewLay->DoesPreviewLayoutColsFitIntoWindow() )
{
m_pViewWin->SetSttPage( nThmbPos );
m_pViewWin->SetSelectedPage( nThmbPos );
ChgPage( SwPagePreviewWin::MV_SCROLL, false );
// update scrollbars
ScrollViewSzChg();
}
else
{
// correct scroll amount
const sal_Int16 nPageDiff = nThmbPos - m_pViewWin->SelectedPage();
const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
sal_Int16 nWinPagesToScroll = nPageDiff / nVisPages;
if ( nPageDiff % nVisPages )
{
// decrease/increase number of preview pages to scroll
nPageDiff < 0 ? --nWinPagesToScroll : ++nWinPagesToScroll;
}
m_pViewWin->SetSelectedPage( nThmbPos );
m_pViewWin->Scroll( 0, pPagePreviewLay->GetWinPagesScrollAmount( nWinPagesToScroll ) );
}
}
// update accessibility
GetViewShell()->ShowPreviewSelection( nThmbPos );
}
else
{
// invalidation of window is unnecessary
bInvalidateWin = false;
}
}
else
{
long nThmbPos = pScrollbar->GetThumbPos();
m_pViewWin->Scroll(0, nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Top());
}
}
else
{
long nThmbPos = pScrollbar->GetThumbPos();
m_pViewWin->Scroll(nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Left(), 0);
}
// additional invalidate page status.
static sal_uInt16 aInval[] =
{
FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
FN_STAT_PAGE, 0
};
SfxBindings& rBindings = GetViewFrame()->GetBindings();
rBindings.Invalidate( aInval );
// control invalidation of window
if ( bInvalidateWin )
{
m_pViewWin->Invalidate();
}
}
Point SwPagePreview::AlignToPixel(const Point &rPt) const
{
return m_pViewWin->PixelToLogic( m_pViewWin->LogicToPixel( rPt ) );
}
void SwPagePreview::DocSzChgd( const Size &rSz )
{
if( m_aDocSize == rSz )
return;
m_aDocSize = rSz;
// #i96726#
// Due to the multiple page layout it is needed to trigger recalculation
// of the page preview layout, even if the count of pages is not changing.
mnPageCount = GetViewShell()->GetNumPages();
if( m_aVisArea.GetWidth() )
{
ChgPage( SwPagePreviewWin::MV_CALC );
ScrollDocSzChg();
m_pViewWin->Invalidate();
}
}
void SwPagePreview::ScrollViewSzChg()
{
if(!GetViewShell())
return ;
bool bShowVScrollbar = false, bShowHScrollbar = false;
if(m_pVScrollbar)
{
if(GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow())
{
//vertical scrolling by row
// adjust to new preview functionality
const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
m_pVScrollbar->SetVisibleSize( nVisPages );
// set selected page as scroll bar position,
// if it is visible.
SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
if ( pPagePreviewLay->IsPageVisible( m_pViewWin->SelectedPage() ) )
{
m_pVScrollbar->SetThumbPos( m_pViewWin->SelectedPage() );
}
else
{
m_pVScrollbar->SetThumbPos( m_pViewWin->GetSttPage() );
}
m_pVScrollbar->SetLineSize( m_pViewWin->GetCol() );
m_pVScrollbar->SetPageSize( nVisPages );
// calculate and set scrollbar range
Range aScrollbarRange( 1, mnPageCount );
// increase range by one, because left-top-corner is left blank.
++aScrollbarRange.Max();
// increase range in order to access all pages
aScrollbarRange.Max() += ( nVisPages - 1 );
m_pVScrollbar->SetRange( aScrollbarRange );
bShowVScrollbar = nVisPages < mnPageCount;
}
else //vertical scrolling by pixel
{
const tools::Rectangle& rDocRect = m_pViewWin->GetPaintedPreviewDocRect();
const Size& rPreviewSize =
GetViewShell()->PagePreviewLayout()->GetPreviewDocSize();
m_pVScrollbar->SetRangeMax(rPreviewSize.Height()) ;
long nVisHeight = rDocRect.GetHeight();
m_pVScrollbar->SetVisibleSize( nVisHeight );
m_pVScrollbar->SetThumbPos( rDocRect.Top() );
m_pVScrollbar->SetLineSize( nVisHeight / 10 );
m_pVScrollbar->SetPageSize( nVisHeight / 2 );
bShowVScrollbar = true;
}
if (!mbVScrollbarEnabled)
bShowVScrollbar = false;
ShowVScrollbar(bShowVScrollbar);
}
if(m_pHScrollbar)
{
const tools::Rectangle& rDocRect = m_pViewWin->GetPaintedPreviewDocRect();
const Size& rPreviewSize =
GetViewShell()->PagePreviewLayout()->GetPreviewDocSize();
Range aRange(0,0);
if(rDocRect.GetWidth() < rPreviewSize.Width())
{
bShowHScrollbar = true;
long nVisWidth = rDocRect.GetWidth();
long nThumb = rDocRect.Left();
aRange = Range(0, rPreviewSize.Width());
m_pHScrollbar->SetRange( aRange );
m_pHScrollbar->SetVisibleSize( nVisWidth );
m_pHScrollbar->SetThumbPos( nThumb );
m_pHScrollbar->SetLineSize( nVisWidth / 10 );
m_pHScrollbar->SetPageSize( nVisWidth / 2 );
}
if (!mbHScrollbarEnabled)
bShowHScrollbar = false;
ShowHScrollbar(bShowHScrollbar);
}
m_pScrollFill->Show(bShowVScrollbar && bShowHScrollbar);
}
void SwPagePreview::ScrollDocSzChg()
{
ScrollViewSzChg();
}
// All about printing
SfxPrinter* SwPagePreview::GetPrinter( bool bCreate )
{
return m_pViewWin->GetViewShell()->getIDocumentDeviceAccess().getPrinter( bCreate );
}
sal_uInt16 SwPagePreview::SetPrinter( SfxPrinter *pNew, SfxPrinterChangeFlags nDiffFlags )
{
SwViewShell &rSh = *GetViewShell();
SfxPrinter* pOld = rSh.getIDocumentDeviceAccess().getPrinter( false );
if ( pOld && pOld->IsPrinting() )
return SFX_PRINTERROR_BUSY;
SwEditShell &rESh = static_cast<SwEditShell&>(rSh); //Buh...
if( ( SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP ) & nDiffFlags )
{
rSh.getIDocumentDeviceAccess().setPrinter( pNew, true, true );
if( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
rESh.SetModified();
}
if ( ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS ) == SfxPrinterChangeFlags::OPTIONS )
::SetPrinter( &rSh.getIDocumentDeviceAccess(), pNew, false );
const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
if ( bChgOri || bChgSize )
{
rESh.StartAllAction();
if ( bChgOri )
rSh.ChgAllPageOrientation( pNew->GetOrientation() );
if ( bChgSize )
{
Size aSz( SvxPaperInfo::GetPaperSize( pNew ) );
rSh.ChgAllPageSize( aSz );
}
if( !m_bNormalPrint )
m_pViewWin->CalcWish( m_pViewWin->GetRow(), m_pViewWin->GetCol() );
rESh.SetModified();
rESh.EndAllAction();
static sal_uInt16 aInval[] =
{
SID_ATTR_LONG_ULSPACE, SID_ATTR_LONG_LRSPACE,
SID_RULER_BORDERS, SID_RULER_PAGE_POS, 0
};
#if OSL_DEBUG_LEVEL > 0
{
const sal_uInt16* pPtr = aInval + 1;
do {
OSL_ENSURE( *(pPtr - 1) < *pPtr, "wrong sorting!" );
} while( *++pPtr );
}
#endif
GetViewFrame()->GetBindings().Invalidate(aInval);
}
return 0;
}
bool SwPagePreview::HasPrintOptionsPage() const
{
return true;
}
VclPtr<SfxTabPage> SwPagePreview::CreatePrintOptionsPage(TabPageParent pParent,
const SfxItemSet &rOptions)
{
return ::CreatePrintOptionsPage(pParent, rOptions, !m_bNormalPrint);
}
void SwPagePreviewWin::SetViewShell( SwViewShell* pShell )
{
mpViewShell = pShell;
if ( mpViewShell && mpViewShell->IsPreview() )
{
mpPgPreviewLayout = mpViewShell->PagePreviewLayout();
}
}
void SwPagePreviewWin::RepaintCoreRect( const SwRect& rRect )
{
// #i24183#
if ( mpPgPreviewLayout->PreviewLayoutValid() )
{
mpPgPreviewLayout->Repaint( tools::Rectangle( rRect.Pos(), rRect.SSize() ) );
}
}
/** method to adjust preview to a new zoom factor
#i19975# also consider zoom type - adding parameter <_eZoomType>
*/
void SwPagePreviewWin::AdjustPreviewToNewZoom( const sal_uInt16 _nZoomFactor,
const SvxZoomType _eZoomType )
{
// #i19975# consider zoom type
if ( _eZoomType == SvxZoomType::WHOLEPAGE )
{
mnRow = 1;
mnCol = 1;
mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
mnSttPage, maPaintedPreviewDocRect );
SetSelectedPage( mnSttPage );
SetPagePreview(mnRow, mnCol);
maScale = GetMapMode().GetScaleX();
}
else if ( _nZoomFactor != 0 )
{
// calculate new scaling and set mapping mode appropriately.
Fraction aNewScale( _nZoomFactor, 100 );
MapMode aNewMapMode = GetMapMode();
aNewMapMode.SetScaleX( aNewScale );
aNewMapMode.SetScaleY( aNewScale );
SetMapMode( aNewMapMode );
// calculate new start position for preview paint
Size aNewWinSize = PixelToLogic( maPxWinSize );
Point aNewPaintStartPos =
mpPgPreviewLayout->GetPreviewStartPosForNewScale( aNewScale, maScale, aNewWinSize );
// remember new scaling and prepare preview paint
// Note: paint of preview will be performed by a corresponding invalidate
// due to property changes.
maScale = aNewScale;
mpPgPreviewLayout->Prepare( 0, aNewPaintStartPos, maPxWinSize,
mnSttPage, maPaintedPreviewDocRect );
}
}
/**
* pixel scrolling - horizontally always or vertically
* when less than the desired number of rows fits into
* the view
*/
void SwPagePreviewWin::Scroll(long nXMove, long nYMove, ScrollFlags /*nFlags*/)
{
maPaintedPreviewDocRect.Move(nXMove, nYMove);
mpPgPreviewLayout->Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
maPxWinSize, mnSttPage,
maPaintedPreviewDocRect );
}
bool SwPagePreview::HandleWheelCommands( const CommandEvent& rCEvt )
{
bool bOk = false;
const CommandWheelData* pWData = rCEvt.GetWheelData();
if( pWData && CommandWheelMode::ZOOM == pWData->GetMode() )
{
//only the Preference shouldn't control the Zoom, it is better to detect AT tools running. So the bridge can be used here
if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport())
{
sal_uInt16 nFactor = GetViewShell()->GetViewOptions()->GetZoom();
const sal_uInt16 nOffset = 10;
if( 0L > pWData->GetDelta() )
{
nFactor -= nOffset;
if(nFactor < MIN_PREVIEW_ZOOM)
nFactor = MIN_PREVIEW_ZOOM;
}
else
{
nFactor += nOffset;
if(nFactor > MAX_PREVIEW_ZOOM)
nFactor = MAX_PREVIEW_ZOOM;
}
SetZoom(SvxZoomType::PERCENT, nFactor);
}
bOk = true;
}
else
bOk = m_pViewWin->HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
return bOk;
}
uno::Reference< css::accessibility::XAccessible >
SwPagePreviewWin::CreateAccessible()
{
SolarMutexGuard aGuard; // this should have happened already!!!
OSL_ENSURE( GetViewShell() != nullptr, "We need a view shell" );
css::uno::Reference< css::accessibility::XAccessible > xAcc = GetAccessible( false );
if (xAcc.is())
{
return xAcc;
}
if (mpViewShell)
{
css::uno::Reference< css::accessibility::XAccessible > xAccPreview = mpViewShell->CreateAccessiblePreview();
SetAccessible(xAccPreview);
}
return GetAccessible( false );
}
void SwPagePreview::ApplyAccessiblityOptions(SvtAccessibilityOptions const & rAccessibilityOptions)
{
GetViewShell()->ApplyAccessiblityOptions(rAccessibilityOptions);
}
void SwPagePreview::ShowHScrollbar(bool bShow)
{
m_pHScrollbar->Show(bShow);
InvalidateBorder();
}
void SwPagePreview::ShowVScrollbar(bool bShow)
{
m_pVScrollbar->Show(bShow);
InvalidateBorder();
}
void SwPagePreview::EnableHScrollbar(bool bEnable)
{
if (mbHScrollbarEnabled != bEnable)
{
mbHScrollbarEnabled = bEnable;
ScrollViewSzChg();
}
}
void SwPagePreview::EnableVScrollbar(bool bEnable)
{
if (mbVScrollbarEnabled != bEnable)
{
mbVScrollbarEnabled = bEnable;
ScrollViewSzChg();
}
}
void SwPagePreview::SetZoom(SvxZoomType eType, sal_uInt16 nFactor)
{
SwViewShell& rSh = *GetViewShell();
SwViewOption aOpt(*rSh.GetViewOptions());
// perform action only on changes of zoom or zoom type.
if ( aOpt.GetZoom() != nFactor ||
aOpt.GetZoomType() != eType )
{
aOpt.SetZoom(nFactor);
aOpt.SetZoomType(eType);
rSh.ApplyViewOptions( aOpt );
lcl_InvalidateZoomSlots(GetViewFrame()->GetBindings());
// #i19975# also consider zoom type
m_pViewWin->AdjustPreviewToNewZoom( nFactor, eType );
ScrollViewSzChg();
}
}
/** adjust position of vertical scrollbar */
void SwPagePreview::SetVScrollbarThumbPos( const sal_uInt16 _nNewThumbPos )
{
if ( m_pVScrollbar )
{
m_pVScrollbar->SetThumbPos( _nNewThumbPos );
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V547 Expression 'bRetVal' is always true.