nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / view / pagepreviewlayout.cxx
blob57fda67e4e2cab1be096871b10f278b816ddd0cc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <pagepreviewlayout.hxx>
21 #include <prevwpage.hxx>
23 #include <algorithm>
24 #include <tools/fract.hxx>
25 #include <vcl/window.hxx>
26 #include <vcl/settings.hxx>
28 #include <rootfrm.hxx>
29 #include <pagefrm.hxx>
30 #include <viewsh.hxx>
31 #include <viewimp.hxx>
32 #include <viewopt.hxx>
33 #include <swregion.hxx>
34 #include <strings.hrc>
35 #include <frmtool.hxx>
36 #include <sfx2/zoomitem.hxx>
37 #include <printdata.hxx>
38 #include <paintfrm.hxx>
40 #include <IDocumentDeviceAccess.hxx>
42 // methods to initialize page preview layout
44 SwPagePreviewLayout::SwPagePreviewLayout( SwViewShell& _rParentViewShell,
45 const SwRootFrame& _rLayoutRootFrame )
46 : mrParentViewShell( _rParentViewShell ),
47 mrLayoutRootFrame ( _rLayoutRootFrame )
49 Clear_();
51 mbBookPreview = false;
52 mbBookPreviewModeToggled = false;
54 mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages();
57 void SwPagePreviewLayout::Clear_()
59 mbLayoutInfoValid = mbLayoutSizesValid = mbPaintInfoValid = false;
61 maWinSize.setWidth( 0 );
62 maWinSize.setHeight( 0 );
63 mnCols = mnRows = 0;
65 ClearPreviewLayoutSizes();
67 mbDoesLayoutRowsFitIntoWindow = false;
68 mbDoesLayoutColsFitIntoWindow = false;
70 mnPaintPhyStartPageNum = 0;
71 mnPaintStartCol = mnPaintStartRow = 0;
72 mbNoPageVisible = false;
73 maPaintStartPageOffset.setX( 0 );
74 maPaintStartPageOffset.setY( 0 );
75 maPaintPreviewDocOffset.setX( 0 );
76 maPaintPreviewDocOffset.setY( 0 );
77 maAdditionalPaintOffset.setX( 0 );
78 maAdditionalPaintOffset.setY( 0 );
79 maPaintedPreviewDocRect.SetLeft( 0 );
80 maPaintedPreviewDocRect.SetTop( 0 );
81 maPaintedPreviewDocRect.SetRight( 0 );
82 maPaintedPreviewDocRect.SetBottom( 0 );
83 mnSelectedPageNum = 0;
84 ClearPreviewPageData();
86 mbInPaint = false;
87 mbNewLayoutDuringPaint = false;
90 void SwPagePreviewLayout::ClearPreviewLayoutSizes()
92 mnPages = 0;
94 maMaxPageSize.setWidth( 0 );
95 maMaxPageSize.setHeight( 0 );
96 maPreviewDocRect.SetLeft( 0 );
97 maPreviewDocRect.SetTop( 0 );
98 maPreviewDocRect.SetRight( 0 );
99 maPreviewDocRect.SetBottom( 0 );
100 mnColWidth = mnRowHeight = 0;
101 mnPreviewLayoutWidth = mnPreviewLayoutHeight = 0;
104 void SwPagePreviewLayout::ClearPreviewPageData()
106 maPreviewPages.clear();
109 /** calculate page preview layout sizes
112 void SwPagePreviewLayout::CalcPreviewLayoutSizes()
114 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
115 // calculate maximal page size; calculate also number of pages
117 const SwPageFrame* pPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
118 while ( pPage )
120 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
122 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
123 continue;
126 ++mnPages;
127 pPage->Calc(pRenderContext);
128 const Size& rPageSize = pPage->getFrameArea().SSize();
129 if ( rPageSize.Width() > maMaxPageSize.Width() )
130 maMaxPageSize.setWidth( rPageSize.Width() );
131 if ( rPageSize.Height() > maMaxPageSize.Height() )
132 maMaxPageSize.setHeight( rPageSize.Height() );
133 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
135 // calculate and set column width and row height
136 mnColWidth = maMaxPageSize.Width() + gnXFree;
137 mnRowHeight = maMaxPageSize.Height() + gnYFree;
139 // calculate and set preview layout width and height
140 mnPreviewLayoutWidth = mnCols * mnColWidth + gnXFree;
141 mnPreviewLayoutHeight = mnRows * mnRowHeight + gnYFree;
143 // calculate document rectangle in preview layout
145 Size aDocSize;
146 // document width
147 aDocSize.setWidth( mnPreviewLayoutWidth );
149 // document height
150 // determine number of rows needed for <nPages> in preview layout
151 // use method <GetRowOfPage(..)>.
152 const sal_uInt16 nDocRows = GetRowOfPage( mnPages );
153 aDocSize.setHeight( nDocRows * maMaxPageSize.Height() +
154 (nDocRows+1) * gnYFree );
155 maPreviewDocRect.SetPos( Point( 0, 0 ) );
156 maPreviewDocRect.SetSize( aDocSize );
160 /** init page preview layout
162 initialize the page preview settings for a given layout.
164 side effects:
165 (1) If parameter <_bCalcScale> is true, mapping mode with calculated
166 scaling is set at the output device and the zoom at the view options of
167 the given view shell is set with the calculated scaling.
169 void SwPagePreviewLayout::Init( const sal_uInt16 _nCols,
170 const sal_uInt16 _nRows,
171 const Size& _rPxWinSize
174 // check environment and parameters
176 bool bColsRowsValid = (_nCols != 0) && (_nRows != 0);
177 OSL_ENSURE( bColsRowsValid, "preview layout parameters not correct - preview layout can *not* be initialized" );
178 if ( !bColsRowsValid )
179 return;
181 bool bPxWinSizeValid = (_rPxWinSize.Width() >= 0) &&
182 (_rPxWinSize.Height() >= 0);
183 OSL_ENSURE( bPxWinSizeValid, "no window size - preview layout can *not* be initialized" );
184 if ( !bPxWinSizeValid )
185 return;
188 // environment and parameters ok
190 // clear existing preview settings
191 Clear_();
193 // set layout information columns and rows
194 mnCols = _nCols;
195 mnRows = _nRows;
197 CalcPreviewLayoutSizes();
199 // validate layout information
200 mbLayoutInfoValid = true;
202 // calculate scaling
203 MapMode aMapMode( MapUnit::MapTwip );
204 Size aWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize, aMapMode );
205 Fraction aXScale( aWinSize.Width(), mnPreviewLayoutWidth );
206 Fraction aYScale( aWinSize.Height(), mnPreviewLayoutHeight );
207 if( aXScale < aYScale )
208 aYScale = aXScale;
210 // adjust scaling for Drawing layer.
211 aYScale *= Fraction( 1000, 1 );
212 tools::Long nNewNuminator = aYScale.operator long();
213 if( nNewNuminator < 1 )
214 nNewNuminator = 1;
215 aYScale = Fraction( nNewNuminator, 1000 );
216 // propagate scaling as zoom percentage to view options for font cache
217 ApplyNewZoomAtViewShell( static_cast<sal_uInt8>(nNewNuminator/10) );
219 aMapMode.SetScaleY( aYScale );
220 aMapMode.SetScaleX( aYScale );
221 // set created mapping mode with calculated scaling at output device.
222 mrParentViewShell.GetOut()->SetMapMode( aMapMode );
223 // update statics for paint.
224 ::SwCalcPixStatics( mrParentViewShell.GetOut() );
227 // set window size in twips
228 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
229 // validate layout sizes
230 mbLayoutSizesValid = true;
233 /** apply new zoom at given view shell */
234 void SwPagePreviewLayout::ApplyNewZoomAtViewShell( sal_uInt8 _aNewZoom )
236 SwViewOption aNewViewOptions = *(mrParentViewShell.GetViewOptions());
237 if ( aNewViewOptions.GetZoom() != _aNewZoom )
239 aNewViewOptions.SetZoom( _aNewZoom );
240 //#i19975# - consider zoom type.
241 aNewViewOptions.SetZoomType( SvxZoomType::PERCENT );
242 mrParentViewShell.ApplyViewOptions( aNewViewOptions );
246 /** method to adjust page preview layout to document changes
249 void SwPagePreviewLayout::ReInit()
251 // check environment and parameters
253 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
254 OSL_ENSURE( bLayoutSettingsValid,
255 "no valid preview layout info/sizes - no re-init of page preview layout");
256 if ( !bLayoutSettingsValid )
257 return;
260 ClearPreviewLayoutSizes();
261 CalcPreviewLayoutSizes();
264 // methods to prepare paint of page preview
266 /** prepare paint of page preview
268 delete parameter _onStartPageVirtNum
270 @note _nProposedStartPageNum, _onStartPageNum are absolute
272 bool SwPagePreviewLayout::Prepare( const sal_uInt16 _nProposedStartPageNum,
273 const Point& rProposedStartPos,
274 const Size& _rPxWinSize,
275 sal_uInt16& _onStartPageNum,
276 tools::Rectangle& _orDocPreviewPaintRect,
277 const bool _bStartWithPageAtFirstCol
280 sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
281 // check environment and parameters
283 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
284 OSL_ENSURE( bLayoutSettingsValid,
285 "no valid preview layout info/sizes - no prepare of preview paint");
286 if ( !bLayoutSettingsValid )
287 return false;
289 bool bStartPageRangeValid = nProposedStartPageNum <= mnPages;
290 OSL_ENSURE( bStartPageRangeValid,
291 "proposed start page not existing - no prepare of preview paint");
292 if ( !bStartPageRangeValid )
293 return false;
295 bool bStartPosRangeValid =
296 rProposedStartPos.X() >= 0 && rProposedStartPos.Y() >= 0 &&
297 rProposedStartPos.X() <= maPreviewDocRect.Right() &&
298 rProposedStartPos.Y() <= maPreviewDocRect.Bottom();
299 OSL_ENSURE( bStartPosRangeValid,
300 "proposed start position out of range - no prepare of preview paint");
301 if ( !bStartPosRangeValid )
302 return false;
304 bool bWinSizeValid = !_rPxWinSize.IsEmpty();
305 OSL_ENSURE( bWinSizeValid, "no window size - no prepare of preview paint");
306 if ( !bWinSizeValid )
307 return false;
309 bool bStartInfoValid = _nProposedStartPageNum > 0 ||
310 rProposedStartPos != Point(0,0);
311 if ( !bStartInfoValid )
312 nProposedStartPageNum = 1;
315 // environment and parameter ok
317 // update window size at preview setting data
318 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
320 mbNoPageVisible = false;
321 if ( nProposedStartPageNum > 0 )
323 // determine column and row of proposed start page in virtual preview layout
324 const sal_uInt16 nColOfProposed = GetColOfPage( nProposedStartPageNum );
325 const sal_uInt16 nRowOfProposed = GetRowOfPage( nProposedStartPageNum );
326 // determine start page
327 if ( _bStartWithPageAtFirstCol )
329 // leaving left-top-corner blank is
330 // controlled by <mbBookPreview>.
331 if ( mbBookPreview &&
332 ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
334 mnPaintPhyStartPageNum = 1;
335 else
336 mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
338 else
339 mnPaintPhyStartPageNum = nProposedStartPageNum;
341 mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
343 // set starting column
344 if ( _bStartWithPageAtFirstCol )
345 mnPaintStartCol = 1;
346 else
347 mnPaintStartCol = nColOfProposed;
348 // set starting row
349 mnPaintStartRow = nRowOfProposed;
350 // page offset == (-1,-1), indicating no offset and paint of free space.
351 maPaintStartPageOffset.setX( -1 );
352 maPaintStartPageOffset.setY( -1 );
353 // virtual preview document offset.
354 if ( _bStartWithPageAtFirstCol )
355 maPaintPreviewDocOffset.setX( 0 );
356 else
357 maPaintPreviewDocOffset.setX( (nColOfProposed-1) * mnColWidth );
358 maPaintPreviewDocOffset.setY( (nRowOfProposed-1) * mnRowHeight );
360 else
362 // determine column and row of proposed start position.
363 // Note: paint starts at point (0,0)
364 const sal_uInt16 nColOfProposed =
365 static_cast<sal_uInt16>(rProposedStartPos.X() / mnColWidth) + 1;
366 const sal_uInt16 nRowOfProposed =
367 static_cast<sal_uInt16>(rProposedStartPos.Y() / mnRowHeight) + 1;
368 // determine start page == page at proposed start position
369 // leaving left-top-corner blank is
370 // controlled by <mbBookPreview>.
371 if ( mbBookPreview &&
372 ( nRowOfProposed == 1 && nColOfProposed == 1 )
374 mnPaintPhyStartPageNum = 1;
375 else
377 // leaving left-top-corner blank is
378 // controlled by <mbBookPreview>.
379 mnPaintPhyStartPageNum = (nRowOfProposed-1) * mnCols + nColOfProposed;
380 if ( mbBookPreview )
381 --mnPaintPhyStartPageNum;
382 if ( mnPaintPhyStartPageNum > mnPages )
384 // no page will be visible, because shown part of document
385 // preview is the last row to the right of the last page
386 mnPaintPhyStartPageNum = mnPages;
387 mbNoPageVisible = true;
390 // set starting column and starting row
391 mnPaintStartCol = nColOfProposed;
392 mnPaintStartRow = nRowOfProposed;
393 // page offset
394 maPaintStartPageOffset.setX(
395 (rProposedStartPos.X() % mnColWidth) - gnXFree );
396 maPaintStartPageOffset.setY(
397 (rProposedStartPos.Y() % mnRowHeight) - gnYFree );
398 // virtual preview document offset.
399 maPaintPreviewDocOffset = rProposedStartPos;
402 // determine additional paint offset, if preview layout fits into window.
403 CalcAdditionalPaintOffset();
405 // determine rectangle to be painted from document preview
406 CalcDocPreviewPaintRect();
407 _orDocPreviewPaintRect = maPaintedPreviewDocRect;
409 // shift visible preview document area to the left,
410 // if on the right is an area left blank.
411 if ( !mbDoesLayoutColsFitIntoWindow &&
412 maPaintedPreviewDocRect.GetWidth() < maWinSize.Width() )
414 maPaintedPreviewDocRect.Move(
415 -(maWinSize.Width() - maPaintedPreviewDocRect.GetWidth()), 0 );
416 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
417 _rPxWinSize, _onStartPageNum,
418 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
421 // shift visible preview document area to the top,
422 // if on the bottom is an area left blank.
423 if ( mbBookPreviewModeToggled &&
424 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom() &&
425 maPaintedPreviewDocRect.GetHeight() < maWinSize.Height() )
427 if ( mbDoesLayoutRowsFitIntoWindow )
429 if ( maPaintedPreviewDocRect.GetHeight() < mnPreviewLayoutHeight)
431 maPaintedPreviewDocRect.Move(
432 0, -(mnPreviewLayoutHeight - maPaintedPreviewDocRect.GetHeight()) );
433 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
434 _rPxWinSize, _onStartPageNum,
435 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
438 else
440 maPaintedPreviewDocRect.Move(
441 0, -(maWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) );
442 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
443 _rPxWinSize, _onStartPageNum,
444 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
448 // determine preview pages - visible pages with needed data for paint and
449 // accessible pages with needed data.
450 CalcPreviewPages();
452 // OD 07.11.2003 #i22014# - indicate new layout, if print preview is in paint
453 if ( mbInPaint )
455 mbNewLayoutDuringPaint = true;
458 // validate paint data
459 mbPaintInfoValid = true;
461 // return start page
462 _onStartPageNum = mnPaintPhyStartPageNum;
464 return true;
467 /** calculate additional paint offset
470 void SwPagePreviewLayout::CalcAdditionalPaintOffset()
472 if ( mnPreviewLayoutWidth <= maWinSize.Width() &&
473 maPaintStartPageOffset.X() <= 0 )
475 mbDoesLayoutColsFitIntoWindow = true;
476 maAdditionalPaintOffset.setX( (maWinSize.Width() - mnPreviewLayoutWidth) / 2 );
478 else
480 mbDoesLayoutColsFitIntoWindow = false;
481 maAdditionalPaintOffset.setX( 0 );
484 if ( mnPreviewLayoutHeight <= maWinSize.Height() &&
485 maPaintStartPageOffset.Y() <= 0 )
487 mbDoesLayoutRowsFitIntoWindow = true;
488 maAdditionalPaintOffset.setY( (maWinSize.Height() - mnPreviewLayoutHeight) / 2 );
490 else
492 mbDoesLayoutRowsFitIntoWindow = false;
493 maAdditionalPaintOffset.setY( 0 );
497 /** calculate painted preview document rectangle
500 void SwPagePreviewLayout::CalcDocPreviewPaintRect()
502 Point aTopLeftPos = maPaintPreviewDocOffset;
503 maPaintedPreviewDocRect.SetPos( aTopLeftPos );
505 Size aSize;
506 if ( mbDoesLayoutColsFitIntoWindow )
507 aSize.setWidth( std::min( tools::Long(mnPreviewLayoutWidth),
508 maPreviewDocRect.GetWidth() - aTopLeftPos.X() ) );
509 else
510 aSize.setWidth( std::min( maPreviewDocRect.GetWidth() - aTopLeftPos.X(),
511 maWinSize.Width() - maAdditionalPaintOffset.X() ) );
512 if ( mbDoesLayoutRowsFitIntoWindow )
513 aSize.setHeight( std::min( tools::Long(mnPreviewLayoutHeight),
514 maPreviewDocRect.GetHeight() - aTopLeftPos.Y() ) );
515 else
516 aSize.setHeight( std::min( maPreviewDocRect.GetHeight() - aTopLeftPos.Y(),
517 maWinSize.Height() - maAdditionalPaintOffset.Y() ) );
518 maPaintedPreviewDocRect.SetSize( aSize );
521 /** calculate preview pages
524 void SwPagePreviewLayout::CalcPreviewPages()
526 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
527 ClearPreviewPageData();
529 if ( mbNoPageVisible )
530 return;
532 // determine start page frame
533 const SwPageFrame* pStartPage = mrLayoutRootFrame.GetPageByPageNum( mnPaintPhyStartPageNum );
535 // calculate initial paint offset
536 Point aInitialPaintOffset;
537 /// check whether RTL interface or not
538 if(!AllSettings::GetLayoutRTL()){
539 if ( maPaintStartPageOffset != Point( -1, -1 ) )
540 aInitialPaintOffset = Point(0,0) - maPaintStartPageOffset;
541 else
542 aInitialPaintOffset = Point( gnXFree, gnYFree );
544 else {
545 if ( maPaintStartPageOffset != Point( -1, -1 ) )
546 aInitialPaintOffset = Point(0 + ((SwPagePreviewLayout::mnCols-1)*mnColWidth),0) - maPaintStartPageOffset;
547 else
548 aInitialPaintOffset = Point( gnXFree + ((SwPagePreviewLayout::mnCols-1)*mnColWidth), gnYFree );
550 aInitialPaintOffset += maAdditionalPaintOffset;
552 // prepare loop data
553 const SwPageFrame* pPage = pStartPage;
554 sal_uInt16 nCurrCol = mnPaintStartCol;
555 sal_uInt16 nConsideredRows = 0;
556 Point aCurrPaintOffset = aInitialPaintOffset;
557 // loop on pages to determine preview background rectangles
558 while ( pPage &&
559 (!mbDoesLayoutRowsFitIntoWindow || nConsideredRows < mnRows) &&
560 aCurrPaintOffset.Y() < maWinSize.Height()
563 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
565 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
566 continue;
569 pPage->Calc(pRenderContext);
571 // consider only pages, which have to be painted.
572 if ( nCurrCol < mnPaintStartCol )
574 // calculate data of unvisible page needed for accessibility
575 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
576 Point aCurrAccOffset = aCurrPaintOffset -
577 Point( (mnPaintStartCol-nCurrCol) * mnColWidth, 0 );
578 CalcPreviewDataForPage( *pPage, aCurrAccOffset, pPreviewPage.get() );
579 pPreviewPage->bVisible = false;
580 maPreviewPages.push_back( std::move(pPreviewPage) );
581 // continue with next page and next column
582 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
583 ++nCurrCol;
584 continue;
586 if ( aCurrPaintOffset.X() < maWinSize.Width() )
588 // leaving left-top-corner blank is
589 // controlled by <mbBookPreview>.
590 if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1
593 // first page in 2nd column
594 // --> continue with increased paint offset and next column
595 /// check whether RTL interface or not
596 if(!AllSettings::GetLayoutRTL())
597 aCurrPaintOffset.AdjustX(mnColWidth );
598 else aCurrPaintOffset.AdjustX( -mnColWidth );
599 ++nCurrCol;
600 continue;
603 // calculate data of visible page
604 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
605 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
606 pPreviewPage->bVisible = true;
607 maPreviewPages.push_back( std::move(pPreviewPage) );
609 else
611 // calculate data of unvisible page needed for accessibility
612 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
613 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
614 pPreviewPage->bVisible = false;
615 maPreviewPages.push_back( std::move(pPreviewPage) );
618 // prepare data for next loop
619 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
621 /// check whether RTL interface or not
622 if(!AllSettings::GetLayoutRTL())
623 aCurrPaintOffset.AdjustX(mnColWidth );
624 else aCurrPaintOffset.AdjustX( -mnColWidth );
625 ++nCurrCol;
626 if ( nCurrCol > mnCols )
628 ++nConsideredRows;
629 aCurrPaintOffset.setX( aInitialPaintOffset.X() );
630 nCurrCol = 1;
631 aCurrPaintOffset.AdjustY(mnRowHeight );
636 /** determines preview data for a given page and a given preview offset
638 OD 13.12.2002 #103492#
640 void SwPagePreviewLayout::CalcPreviewDataForPage( const SwPageFrame& _rPage,
641 const Point& _rPreviewOffset,
642 PreviewPage* _opPreviewPage )
644 // page frame
645 _opPreviewPage->pPage = &_rPage;
646 // size of page frame
647 if ( _rPage.IsEmptyPage() )
649 if ( _rPage.GetPhyPageNum() % 2 == 0 )
650 _opPreviewPage->aPageSize = _rPage.GetPrev()->getFrameArea().SSize();
651 else
652 _opPreviewPage->aPageSize = _rPage.GetNext()->getFrameArea().SSize();
654 else
655 _opPreviewPage->aPageSize = _rPage.getFrameArea().SSize();
656 // position of page in preview window
657 Point aPreviewWinOffset( _rPreviewOffset );
658 if ( _opPreviewPage->aPageSize.Width() < maMaxPageSize.Width() )
659 aPreviewWinOffset.AdjustX(( maMaxPageSize.Width() - _opPreviewPage->aPageSize.Width() ) / 2 );
660 if ( _opPreviewPage->aPageSize.Height() < maMaxPageSize.Height() )
661 aPreviewWinOffset.AdjustY(( maMaxPageSize.Height() - _opPreviewPage->aPageSize.Height() ) / 2 );
662 _opPreviewPage->aPreviewWinPos = aPreviewWinOffset;
663 // logic position of page and mapping offset for paint
664 if ( _rPage.IsEmptyPage() )
666 _opPreviewPage->aLogicPos = _opPreviewPage->aPreviewWinPos;
667 _opPreviewPage->aMapOffset = Point( 0, 0 );
669 else
671 _opPreviewPage->aLogicPos = _rPage.getFrameArea().Pos();
672 _opPreviewPage->aMapOffset = _opPreviewPage->aPreviewWinPos - _opPreviewPage->aLogicPos;
676 /** enable/disable book preview
678 OD 2004-03-04 #i18143#
680 bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
681 sal_uInt16& _onStartPageNum,
682 tools::Rectangle& _orDocPreviewPaintRect )
684 if ( mbBookPreview != _bEnableBookPreview)
686 mbBookPreview = _bEnableBookPreview;
687 // re-initialize page preview layout
688 ReInit();
689 // re-prepare page preview layout
691 mbBookPreviewModeToggled = true;
692 Point aProposedStartPos( maPaintPreviewDocOffset );
693 // if proposed start position is below virtual preview document
694 // bottom, adjust it to the virtual preview document bottom
695 if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
697 aProposedStartPos.setY( maPreviewDocRect.Bottom() );
699 Prepare( 0, aProposedStartPos,
700 mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
701 _onStartPageNum, _orDocPreviewPaintRect );
702 mbBookPreviewModeToggled = false;
705 return true;
708 return false;
711 // methods to determine new data for changing the current shown part of the
712 // document preview.
714 /** calculate start position for new scale
717 Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
718 const Fraction& _aNewScale,
719 const Fraction& _aOldScale,
720 const Size& _aNewWinSize ) const
722 Point aNewPaintStartPos = maPaintedPreviewDocRect.TopLeft();
723 if ( _aNewScale < _aOldScale )
725 // increase paint width by moving start point to left.
726 if ( mnPreviewLayoutWidth < _aNewWinSize.Width() )
727 aNewPaintStartPos.setX( 0 );
728 else if ( maPaintedPreviewDocRect.GetWidth() < _aNewWinSize.Width() )
730 aNewPaintStartPos.AdjustX( -(
731 (_aNewWinSize.Width() - maPaintedPreviewDocRect.GetWidth()) / 2) );
732 if ( aNewPaintStartPos.X() < 0)
733 aNewPaintStartPos.setX( 0 );
736 if ( !mbDoesLayoutRowsFitIntoWindow )
738 // increase paint height by moving start point to top.
739 if ( mnPreviewLayoutHeight < _aNewWinSize.Height() )
741 aNewPaintStartPos.setY(
742 (mnPaintStartRow - 1) * mnRowHeight );
744 else if ( maPaintedPreviewDocRect.GetHeight() < _aNewWinSize.Height() )
746 aNewPaintStartPos.AdjustY( -(
747 (_aNewWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) / 2) );
748 if ( aNewPaintStartPos.Y() < 0)
749 aNewPaintStartPos.setY( 0 );
753 else
755 // decrease paint width by moving start point to right
756 if ( maPaintedPreviewDocRect.GetWidth() > _aNewWinSize.Width() )
757 aNewPaintStartPos.AdjustX(
758 (maPaintedPreviewDocRect.GetWidth() - _aNewWinSize.Width()) / 2 );
759 // decrease paint height by moving start point to bottom
760 if ( maPaintedPreviewDocRect.GetHeight() > _aNewWinSize.Height() )
762 aNewPaintStartPos.AdjustY(
763 (maPaintedPreviewDocRect.GetHeight() - _aNewWinSize.Height()) / 2 );
764 // check, if new y-position is outside document preview
765 if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
766 aNewPaintStartPos.setY(
767 std::max( tools::Long(0), maPreviewDocRect.Bottom() - mnPreviewLayoutHeight ) );
771 return aNewPaintStartPos;
774 /** determines, if page with given page number is visible in preview
776 @note _nPageNum is absolute
778 bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
780 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
781 return pPreviewPage && pPreviewPage->bVisible;
784 /** calculate data to bring new selected page into view.
786 @note IN/OUT parameters are absolute page numbers!!!
788 void SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
789 const sal_Int16 _nHoriMove,
790 const sal_Int16 _nVertMove,
791 sal_uInt16& _orNewSelectedPage,
792 sal_uInt16& _orNewStartPage,
793 Point& _orNewStartPos ) const
795 // determine position of current selected page
796 sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
797 sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
799 const sal_uInt16 nCurrRow = GetRowOfPage(nTmpRelSelPageNum);
801 // determine new selected page number
803 if ( _nHoriMove != 0 )
805 if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
806 nNewRelSelectedPageNum = 1;
807 else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
808 nNewRelSelectedPageNum = mnPages;
809 else
810 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
812 if ( _nVertMove != 0 )
814 if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
815 nNewRelSelectedPageNum = 1;
816 else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
817 nNewRelSelectedPageNum = mnPages;
818 else
819 nNewRelSelectedPageNum += ( _nVertMove * mnCols );
823 sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
824 Point aNewStartPos(0,0);
826 const sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
827 if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
829 if ( _nHoriMove != 0 && _nVertMove != 0 )
831 OSL_FAIL( "missing implementation for moving preview selected page horizontal AND vertical");
832 return;
835 // new selected page has to be brought into view considering current
836 // visible preview.
837 const sal_uInt16 nTotalRows = GetRowOfPage( mnPages );
838 if ( (_nHoriMove > 0 || _nVertMove > 0) &&
839 mbDoesLayoutRowsFitIntoWindow &&
840 mbDoesLayoutColsFitIntoWindow &&
841 nCurrRow > nTotalRows - mnRows )
843 // new proposed start page = left-top-corner of last possible
844 // preview page.
845 nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
846 // leaving left-top-corner blank is controlled
847 // by <mbBookPreview>.
848 if ( mbBookPreview )
850 // Note: decrease new proposed start page number by one,
851 // because of blank left-top-corner
852 --nNewStartPage;
854 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
856 else
858 // new proposed start page = new selected page.
859 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
863 _orNewSelectedPage = nNewAbsSelectedPageNum;
864 _orNewStartPage = nNewStartPage;
865 _orNewStartPos = aNewStartPos;
868 namespace {
870 /** checks, if given position is inside a shown document page */
871 struct PreviewPosInsidePagePred
873 const Point mnPreviewPos;
874 explicit PreviewPosInsidePagePred(const Point& rPreviewPos)
875 : mnPreviewPos( rPreviewPos )
877 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
879 if ( _pPreviewPage->bVisible )
881 tools::Rectangle aPreviewPageRect( _pPreviewPage->aPreviewWinPos, _pPreviewPage->aPageSize );
882 return aPreviewPageRect.IsInside( mnPreviewPos );
884 return false;
890 bool SwPagePreviewLayout::IsPreviewPosInDocPreviewPage( const Point& rPreviewPos,
891 Point& _orDocPos,
892 bool& _obPosInEmptyPage,
893 sal_uInt16& _onPageNum ) const
895 // initialize variable parameter values.
896 _orDocPos.setX( 0 );
897 _orDocPos.setY( 0 );
898 _obPosInEmptyPage = false;
899 _onPageNum = 0;
901 auto aFoundPreviewPageIter =
902 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
903 PreviewPosInsidePagePred( rPreviewPos ) );
905 if ( aFoundPreviewPageIter != maPreviewPages.end() )
907 // given preview position is inside a document page.
908 _onPageNum = (*aFoundPreviewPageIter)->pPage->GetPhyPageNum();
909 _obPosInEmptyPage = (*aFoundPreviewPageIter)->pPage->IsEmptyPage();
910 if ( !_obPosInEmptyPage )
912 // given preview position inside a normal page
913 _orDocPos = rPreviewPos -
914 (*aFoundPreviewPageIter)->aPreviewWinPos +
915 (*aFoundPreviewPageIter)->aLogicPos;
916 return true;
920 return false;
923 /** determine window page scroll amount */
924 SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
925 const sal_Int16 _nWinPagesToScroll ) const
927 SwTwips nScrollAmount;
928 if ( mbDoesLayoutRowsFitIntoWindow )
930 nScrollAmount = (mnPreviewLayoutHeight - gnYFree) * _nWinPagesToScroll;
932 else
933 nScrollAmount = _nWinPagesToScroll * maPaintedPreviewDocRect.GetHeight();
935 // check, if preview layout size values are valid.
936 // If not, the checks for an adjustment of the scroll amount aren't useful.
937 if ( mbLayoutSizesValid )
939 if ( (maPaintedPreviewDocRect.Top() + nScrollAmount) <= 0 )
940 nScrollAmount = -maPaintedPreviewDocRect.Top();
942 // correct scroll amount
943 if ( nScrollAmount > 0 &&
944 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom()
947 nScrollAmount = 0;
949 else
951 while ( (maPaintedPreviewDocRect.Top() + nScrollAmount + gnYFree) >= maPreviewDocRect.GetHeight() )
953 nScrollAmount -= mnRowHeight;
958 return nScrollAmount;
961 // methods to paint page preview layout
963 namespace
965 /// Similar to RenderContextGuard, but does not touch the draw view.
966 class PreviewRenderContextGuard
968 VclPtr<vcl::RenderContext> m_pOriginalValue;
969 SwViewShell& m_rShell;
971 public:
972 PreviewRenderContextGuard(SwViewShell& rShell, vcl::RenderContext* pValue)
973 : m_pOriginalValue(rShell.GetOut()),
974 m_rShell(rShell)
976 m_rShell.SetOut(pValue);
979 ~PreviewRenderContextGuard()
981 m_rShell.SetOut(m_pOriginalValue);
986 /** paint prepared preview
989 bool SwPagePreviewLayout::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rOutRect) const
991 PreviewRenderContextGuard aGuard(mrParentViewShell, &rRenderContext);
992 // check environment and parameters
994 if (!mrParentViewShell.GetWin() && !mrParentViewShell.GetOut()->GetConnectMetaFile())
996 return false;
999 OSL_ENSURE(mbPaintInfoValid, "invalid preview settings - no paint of preview");
1000 if (!mbPaintInfoValid)
1001 return false;
1004 // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1005 if (mrLayoutRootFrame.IsSuperfluous())
1007 return true;
1010 // environment and parameter ok
1012 if (mbInPaint)
1014 return false;
1016 mbInPaint = true;
1018 OutputDevice* pOutputDev = &rRenderContext;
1020 // prepare paint
1021 if ( !maPreviewPages.empty() )
1023 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1024 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1025 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1028 // paint preview background
1030 SwRegionRects aPreviewBackgrdRegion(rOutRect);
1031 // calculate preview background rectangles
1032 for ( auto & rpPreviewPage : maPreviewPages )
1034 if ( rpPreviewPage->bVisible )
1036 aPreviewBackgrdRegion -=
1037 SwRect( rpPreviewPage->aPreviewWinPos, rpPreviewPage->aPageSize );
1040 // paint preview background rectangles
1041 mrParentViewShell.PaintDesktop_(aPreviewBackgrdRegion);
1044 // prepare data for paint of pages
1045 const tools::Rectangle aPxOutRect( pOutputDev->LogicToPixel(rOutRect) );
1047 MapMode aMapMode( pOutputDev->GetMapMode() );
1048 MapMode aSavedMapMode = aMapMode;
1050 const vcl::Font& rEmptyPgFont = SwPageFrame::GetEmptyPageFont();
1052 for ( auto & rpPreviewPage : maPreviewPages )
1054 if ( !rpPreviewPage->bVisible )
1055 continue;
1057 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1058 aMapMode.SetOrigin( rpPreviewPage->aMapOffset );
1059 pOutputDev->SetMapMode( aMapMode );
1060 tools::Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1061 if ( aPxOutRect.IsOver( aPxPaintRect) )
1063 const SwPageFrame* pPage = rpPreviewPage->pPage;
1065 if (pPage->IsEmptyPage())
1067 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1068 if( pOutputDev->GetFillColor() != aRetouche )
1069 pOutputDev->SetFillColor( aRetouche );
1070 pOutputDev->SetLineColor(); // no line color
1071 // use aligned page rectangle
1073 SwRect aTmpPageRect( aPageRect );
1074 ::SwAlignRect( aTmpPageRect, &mrParentViewShell, &rRenderContext );
1075 aPageRect = aTmpPageRect.SVRect();
1077 pOutputDev->DrawRect( aPageRect );
1079 // paint empty page text
1080 vcl::Font aOldFont( pOutputDev->GetFont() );
1081 pOutputDev->SetFont( rEmptyPgFont );
1082 pOutputDev->DrawText( aPageRect, SwResId( STR_EMPTYPAGE ),
1083 DrawTextFlags::VCenter |
1084 DrawTextFlags::Center |
1085 DrawTextFlags::Clip );
1086 pOutputDev->SetFont( aOldFont );
1087 // paint shadow and border for empty page
1088 // use new method to paint page border and shadow
1089 SwPageFrame::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
1091 else
1093 const bool bIsLeftShadowed = pPage->IsLeftShadowNeeded();
1094 const bool bIsRightShadowed = pPage->IsRightShadowNeeded();
1096 mrParentViewShell.maVisArea = aPageRect;
1097 aPxPaintRect.Intersection( aPxOutRect );
1098 tools::Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1099 mrParentViewShell.Paint(rRenderContext, aPaintRect);
1101 // --> OD 2007-08-15 #i80691#
1102 // paint page border and shadow
1104 SwRect aPageBorderRect;
1105 SwPageFrame::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, &rRenderContext, aPageBorderRect,
1106 bIsLeftShadowed, bIsRightShadowed, true );
1107 const vcl::Region aDLRegion(aPageBorderRect.SVRect());
1108 mrParentViewShell.DLPrePaint2(aDLRegion);
1109 SwPageFrame::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
1110 mrParentViewShell.DLPostPaint2(true);
1112 // <--
1114 // OD 07.11.2003 #i22014# - stop painting, because new print
1115 // preview layout is created during paint.
1116 if ( mbNewLayoutDuringPaint )
1118 break;
1121 if (pPage->GetPhyPageNum() == mnSelectedPageNum)
1123 PaintSelectMarkAtPage(rRenderContext, rpPreviewPage.get());
1128 // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1129 // print preview layout is created during paint.
1130 if ( !mbNewLayoutDuringPaint )
1132 // update at accessibility interface
1133 mrParentViewShell.Imp()->UpdateAccessiblePreview(
1134 maPreviewPages,
1135 aMapMode.GetScaleX(),
1136 mrLayoutRootFrame.GetPageByPageNum( mnSelectedPageNum ),
1137 maWinSize );
1140 pOutputDev->SetMapMode( aSavedMapMode );
1141 mrParentViewShell.maVisArea.Clear();
1143 // OD 07.11.2003 #i22014#
1144 mbInPaint = false;
1145 mbNewLayoutDuringPaint = false;
1147 return true;
1150 /** repaint pages on page preview
1152 OD 18.12.2002 #103492#
1154 void SwPagePreviewLayout::Repaint( const tools::Rectangle& rInvalidCoreRect ) const
1156 // check environment and parameters
1158 if ( !mrParentViewShell.GetWin() &&
1159 !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1160 return;
1162 OSL_ENSURE( mbPaintInfoValid,
1163 "invalid preview settings - no paint of preview" );
1164 if ( !mbPaintInfoValid )
1165 return;
1168 // environment and parameter ok
1170 // prepare paint
1171 if ( !maPreviewPages.empty() )
1173 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1174 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1175 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1178 // invalidate visible pages, which overlap the invalid core rectangle
1179 for ( auto & rpPreviewPage : maPreviewPages )
1181 if ( !rpPreviewPage->bVisible )
1182 continue;
1184 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1185 if ( rInvalidCoreRect.IsOver( aPageRect ) )
1187 aPageRect.Intersection(rInvalidCoreRect);
1188 tools::Rectangle aInvalidPreviewRect = aPageRect;
1189 aInvalidPreviewRect.SetPos( aInvalidPreviewRect.TopLeft() -
1190 rpPreviewPage->aLogicPos +
1191 rpPreviewPage->aPreviewWinPos );
1192 mrParentViewShell.GetWin()->Invalidate( aInvalidPreviewRect );
1197 /** paint selection mark at page
1199 OD 17.12.2002 #103492#
1201 void SwPagePreviewLayout::PaintSelectMarkAtPage(vcl::RenderContext& rRenderContext,
1202 const PreviewPage* _aSelectedPreviewPage ) const
1204 OutputDevice* pOutputDev = &rRenderContext;
1205 MapMode aMapMode( pOutputDev->GetMapMode() );
1206 // save mapping mode of output device
1207 MapMode aSavedMapMode = aMapMode;
1208 // save fill and line color of output device
1209 Color aFill( pOutputDev->GetFillColor() );
1210 Color aLine( pOutputDev->GetLineColor() );
1212 // determine selection mark color
1213 Color aSelPgLineColor(117, 114, 106);
1214 const StyleSettings& rSettings =
1215 mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1216 if ( rSettings.GetHighContrastMode() )
1217 aSelPgLineColor = rSettings.GetHighlightTextColor();
1219 // set needed mapping mode at output device
1220 aMapMode.SetOrigin( _aSelectedPreviewPage->aMapOffset );
1221 pOutputDev->SetMapMode( aMapMode );
1223 // calculate page rectangle in pixel coordinates
1224 SwRect aPageRect( _aSelectedPreviewPage->aLogicPos,
1225 _aSelectedPreviewPage->aPageSize );
1226 // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1227 // page border and shadow paint - see <SwPageFrame::PaintBorderAndShadow(..)>
1228 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1229 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1231 // draw two rectangle
1232 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1233 tools::Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1234 aPxPageRect.Right(), aPxPageRect.Bottom() );
1235 aRect = pOutputDev->PixelToLogic( aRect );
1236 pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1237 pOutputDev->SetLineColor( aSelPgLineColor );
1238 pOutputDev->DrawRect( aRect );
1239 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1240 aRect = tools::Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1241 aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1242 aRect = pOutputDev->PixelToLogic( aRect );
1243 pOutputDev->DrawRect( aRect );
1245 // reset fill and line color of output device
1246 pOutputDev->SetFillColor( aFill );
1247 pOutputDev->SetLineColor( aLine );
1249 // reset mapping mode of output device
1250 pOutputDev->SetMapMode( aSavedMapMode );
1253 /** paint to mark new selected page
1255 OD 17.12.2002 #103492#
1256 Perform paint for current selected page in order to unmark it.
1257 Set new selected page and perform paint to mark this page.
1259 @note _nSelectedPage, mnSelectedPage are absolute
1261 void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1263 const sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1264 mnSelectedPageNum = _nSelectedPage;
1266 // re-paint for current selected page in order to unmark it.
1267 const PreviewPage* pOldSelectedPreviewPage = GetPreviewPageByPageNum( nOldSelectedPageNum );
1268 OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1269 if ( pOldSelectedPreviewPage && pOldSelectedPreviewPage->bVisible )
1271 // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1272 SwRect aPageRect( pOldSelectedPreviewPage->aPreviewWinPos,
1273 pOldSelectedPreviewPage->aPageSize );
1274 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1275 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1276 // invalidate top mark line
1277 tools::Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1278 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1279 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1280 // invalidate right mark line
1281 aInvalPxRect = tools::Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1282 aPxPageRect.Right(), aPxPageRect.Bottom() );
1283 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1284 // invalidate bottom mark line
1285 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1286 aPxPageRect.Right(), aPxPageRect.Bottom() );
1287 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1288 // invalidate left mark line
1289 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1290 aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1291 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1294 // re-paint for new selected page in order to mark it.
1295 const PreviewPage* pNewSelectedPreviewPage = GetPreviewPageByPageNum( _nSelectedPage );
1296 if ( pNewSelectedPreviewPage && pNewSelectedPreviewPage->bVisible )
1298 const PreviewPage* pSelectedPreviewPage = GetPreviewPageByPageNum(mnSelectedPageNum);
1299 SwRect aPageRect(pSelectedPreviewPage->aPreviewWinPos, pSelectedPreviewPage->aPageSize);
1300 ::SwAlignRect(aPageRect, &mrParentViewShell, pOutputDev);
1301 mrParentViewShell.GetWin()->Invalidate(aPageRect.SVRect());
1305 // helper methods
1307 namespace {
1309 /** get preview page by physical page number
1311 OD 17.12.2002 #103492#
1313 struct EqualsPageNumPred
1315 const sal_uInt16 mnPageNum;
1316 explicit EqualsPageNumPred(const sal_uInt16 _nPageNum)
1317 : mnPageNum( _nPageNum )
1319 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
1321 return _pPreviewPage->pPage->GetPhyPageNum() == mnPageNum;
1327 const PreviewPage* SwPagePreviewLayout::GetPreviewPageByPageNum( const sal_uInt16 _nPageNum ) const
1329 auto aFoundPreviewPageIter =
1330 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
1331 EqualsPageNumPred( _nPageNum ) );
1333 if ( aFoundPreviewPageIter == maPreviewPages.end() )
1334 return nullptr;
1336 return aFoundPreviewPageIter->get();
1339 /** determine row the page with the given number is in
1341 OD 17.01.2003 #103492#
1343 @note _nPageNum is relative
1345 sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1347 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1348 // by <mbBookPreview>.
1349 if ( mbBookPreview )
1351 // Note: increase given physical page number by one, because left-top-corner
1352 // in the preview layout is left blank.
1353 ++_nPageNum;
1356 return _nPageNum / mnCols + ((_nPageNum % mnCols)>0 ? 1 : 0);
1359 /** determine column the page with the given number is in
1361 OD 17.01.2003 #103492#
1363 @note _nPageNum is relative
1365 sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1367 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1368 // by <mbBookPreview>.
1369 if ( mbBookPreview )
1371 // Note: increase given physical page number by one, because left-top-corner
1372 // in the preview layout is left blank.
1373 ++_nPageNum;
1376 const sal_uInt16 nCol = _nPageNum % mnCols;
1377 return nCol ? nCol : mnCols;
1380 Size SwPagePreviewLayout::GetPreviewDocSize() const
1382 OSL_ENSURE( PreviewLayoutValid(), "PagePreviewLayout not valid" );
1383 return maPreviewDocRect.GetSize();
1386 /** get size of a preview page by its physical page number
1388 OD 15.01.2003 #103492#
1390 Size SwPagePreviewLayout::GetPreviewPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1392 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1393 if ( pPreviewPage )
1395 return pPreviewPage->aPageSize;
1397 return Size( 0, 0 );
1400 /** get virtual page number by its physical page number
1402 OD 21.03.2003 #108282#
1404 sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1406 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1407 if ( pPreviewPage )
1409 return pPreviewPage->pPage->GetVirtPageNum();
1411 return 0;
1414 /** Convert absolute to relative page numbers (see PrintEmptyPages) */
1415 sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1417 if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
1419 return _nAbsPageNum;
1422 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1424 sal_uInt16 nRet = 1;
1426 while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
1428 if ( !pTmpPage->IsEmptyPage() )
1429 ++nRet;
1431 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1434 return nRet;
1437 /** Convert relative to absolute page numbers (see PrintEmptyPages) */
1438 sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1440 if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
1442 return _nRelPageNum;
1445 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1446 const SwPageFrame* pRet = nullptr;
1448 sal_uInt16 i = 0;
1449 while( pTmpPage && i != _nRelPageNum )
1451 if ( !pTmpPage->IsEmptyPage() )
1452 ++i;
1454 pRet = pTmpPage;
1455 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1458 return pRet->GetPhyPageNum();
1461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */