Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / view / pagepreviewlayout.cxx
blob5fc740ebfda997024c3a8a74372fe54c5fcfdd59
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 <config_wasm_strip.h>
22 #include <pagepreviewlayout.hxx>
23 #include <prevwpage.hxx>
25 #include <algorithm>
26 #include <osl/diagnose.h>
27 #include <tools/fract.hxx>
28 #include <vcl/settings.hxx>
30 #include <rootfrm.hxx>
31 #include <pagefrm.hxx>
32 #include <viewsh.hxx>
33 #include <viewimp.hxx>
34 #include <viewopt.hxx>
35 #include <swregion.hxx>
36 #include <strings.hrc>
37 #include <frmtool.hxx>
38 #include <sfx2/zoomitem.hxx>
39 #include <printdata.hxx>
40 #include <paintfrm.hxx>
42 #include <IDocumentDeviceAccess.hxx>
44 // methods to initialize page preview layout
46 SwPagePreviewLayout::SwPagePreviewLayout( SwViewShell& _rParentViewShell,
47 const SwRootFrame& _rLayoutRootFrame )
48 : mrParentViewShell( _rParentViewShell ),
49 mrLayoutRootFrame ( _rLayoutRootFrame )
51 Clear_();
53 mbBookPreview = false;
54 mbBookPreviewModeToggled = false;
56 mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages();
59 void SwPagePreviewLayout::Clear_()
61 mbLayoutInfoValid = mbLayoutSizesValid = mbPaintInfoValid = false;
63 maWinSize.setWidth( 0 );
64 maWinSize.setHeight( 0 );
65 mnCols = mnRows = 0;
67 ClearPreviewLayoutSizes();
69 mbDoesLayoutRowsFitIntoWindow = false;
70 mbDoesLayoutColsFitIntoWindow = false;
72 mnPaintPhyStartPageNum = 0;
73 mnPaintStartCol = mnPaintStartRow = 0;
74 mbNoPageVisible = false;
75 maPaintStartPageOffset.setX( 0 );
76 maPaintStartPageOffset.setY( 0 );
77 maPaintPreviewDocOffset.setX( 0 );
78 maPaintPreviewDocOffset.setY( 0 );
79 maAdditionalPaintOffset.setX( 0 );
80 maAdditionalPaintOffset.setY( 0 );
81 maPaintedPreviewDocRect.SetLeft( 0 );
82 maPaintedPreviewDocRect.SetTop( 0 );
83 maPaintedPreviewDocRect.SetRight( 0 );
84 maPaintedPreviewDocRect.SetBottom( 0 );
85 mnSelectedPageNum = 0;
86 ClearPreviewPageData();
88 mbInPaint = false;
89 mbNewLayoutDuringPaint = false;
92 void SwPagePreviewLayout::ClearPreviewLayoutSizes()
94 mnPages = 0;
96 maMaxPageSize.setWidth( 0 );
97 maMaxPageSize.setHeight( 0 );
98 maPreviewDocRect.SetLeft( 0 );
99 maPreviewDocRect.SetTop( 0 );
100 maPreviewDocRect.SetRight( 0 );
101 maPreviewDocRect.SetBottom( 0 );
102 mnColWidth = mnRowHeight = 0;
103 mnPreviewLayoutWidth = mnPreviewLayoutHeight = 0;
106 void SwPagePreviewLayout::ClearPreviewPageData()
108 maPreviewPages.clear();
111 /** calculate page preview layout sizes
114 void SwPagePreviewLayout::CalcPreviewLayoutSizes()
116 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
117 // calculate maximal page size; calculate also number of pages
119 const SwPageFrame* pPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
120 while ( pPage )
122 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
124 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
125 continue;
128 ++mnPages;
129 pPage->Calc(pRenderContext);
130 const Size& rPageSize = pPage->getFrameArea().SSize();
131 if ( rPageSize.Width() > maMaxPageSize.Width() )
132 maMaxPageSize.setWidth( rPageSize.Width() );
133 if ( rPageSize.Height() > maMaxPageSize.Height() )
134 maMaxPageSize.setHeight( rPageSize.Height() );
135 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
137 // calculate and set column width and row height
138 mnColWidth = maMaxPageSize.Width() + gnXFree;
139 mnRowHeight = maMaxPageSize.Height() + gnYFree;
141 // calculate and set preview layout width and height
142 mnPreviewLayoutWidth = mnCols * mnColWidth + gnXFree;
143 mnPreviewLayoutHeight = mnRows * mnRowHeight + gnYFree;
145 // calculate document rectangle in preview layout
147 Size aDocSize;
148 // document width
149 aDocSize.setWidth( mnPreviewLayoutWidth );
151 // document height
152 // determine number of rows needed for <nPages> in preview layout
153 // use method <GetRowOfPage(..)>.
154 const sal_uInt16 nDocRows = GetRowOfPage( mnPages );
155 aDocSize.setHeight( nDocRows * maMaxPageSize.Height() +
156 (nDocRows+1) * gnYFree );
157 maPreviewDocRect.SetPos( Point( 0, 0 ) );
158 maPreviewDocRect.SetSize( aDocSize );
162 /** init page preview layout
164 initialize the page preview settings for a given layout.
166 side effects:
167 (1) If parameter <_bCalcScale> is true, mapping mode with calculated
168 scaling is set at the output device and the zoom at the view options of
169 the given view shell is set with the calculated scaling.
171 void SwPagePreviewLayout::Init( const sal_uInt16 _nCols,
172 const sal_uInt16 _nRows,
173 const Size& _rPxWinSize
176 // check environment and parameters
178 bool bColsRowsValid = (_nCols != 0) && (_nRows != 0);
179 OSL_ENSURE( bColsRowsValid, "preview layout parameters not correct - preview layout can *not* be initialized" );
180 if ( !bColsRowsValid )
181 return;
183 bool bPxWinSizeValid = (_rPxWinSize.Width() >= 0) &&
184 (_rPxWinSize.Height() >= 0);
185 OSL_ENSURE( bPxWinSizeValid, "no window size - preview layout can *not* be initialized" );
186 if ( !bPxWinSizeValid )
187 return;
190 // environment and parameters ok
192 // clear existing preview settings
193 Clear_();
195 // set layout information columns and rows
196 mnCols = _nCols;
197 mnRows = _nRows;
199 CalcPreviewLayoutSizes();
201 // validate layout information
202 mbLayoutInfoValid = true;
204 // calculate scaling
205 MapMode aMapMode( MapUnit::MapTwip );
206 Size aWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize, aMapMode );
207 Fraction aXScale( aWinSize.Width(), mnPreviewLayoutWidth );
208 Fraction aYScale( aWinSize.Height(), mnPreviewLayoutHeight );
209 if( aXScale < aYScale )
210 aYScale = aXScale;
212 // adjust scaling for Drawing layer.
213 aYScale *= Fraction( 1000, 1 );
214 tools::Long nNewNuminator = aYScale.operator long();
215 if( nNewNuminator < 1 )
216 nNewNuminator = 1;
217 aYScale = Fraction( nNewNuminator, 1000 );
218 // propagate scaling as zoom percentage to view options for font cache
219 ApplyNewZoomAtViewShell( static_cast<sal_uInt8>(nNewNuminator/10) );
221 aMapMode.SetScaleY( aYScale );
222 aMapMode.SetScaleX( aYScale );
223 // set created mapping mode with calculated scaling at output device.
224 mrParentViewShell.GetOut()->SetMapMode( aMapMode );
225 // update statics for paint.
226 ::SwCalcPixStatics( mrParentViewShell.GetOut() );
229 // set window size in twips
230 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
231 // validate layout sizes
232 mbLayoutSizesValid = true;
235 /** apply new zoom at given view shell */
236 void SwPagePreviewLayout::ApplyNewZoomAtViewShell( sal_uInt8 _aNewZoom )
238 SwViewOption aNewViewOptions = *(mrParentViewShell.GetViewOptions());
239 if ( aNewViewOptions.GetZoom() != _aNewZoom )
241 aNewViewOptions.SetZoom( _aNewZoom );
242 //#i19975# - consider zoom type.
243 aNewViewOptions.SetZoomType( SvxZoomType::PERCENT );
244 mrParentViewShell.ApplyViewOptions( aNewViewOptions );
248 /** method to adjust page preview layout to document changes
251 void SwPagePreviewLayout::ReInit()
253 // check environment and parameters
255 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
256 OSL_ENSURE( bLayoutSettingsValid,
257 "no valid preview layout info/sizes - no re-init of page preview layout");
258 if ( !bLayoutSettingsValid )
259 return;
262 ClearPreviewLayoutSizes();
263 CalcPreviewLayoutSizes();
266 // methods to prepare paint of page preview
268 /** prepare paint of page preview
270 delete parameter _onStartPageVirtNum
272 @note _nProposedStartPageNum, _onStartPageNum are absolute
274 bool SwPagePreviewLayout::Prepare( const sal_uInt16 _nProposedStartPageNum,
275 const Point& rProposedStartPos,
276 const Size& _rPxWinSize,
277 sal_uInt16& _onStartPageNum,
278 tools::Rectangle& _orDocPreviewPaintRect,
279 const bool _bStartWithPageAtFirstCol
282 sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
283 // check environment and parameters
285 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
286 OSL_ENSURE( bLayoutSettingsValid,
287 "no valid preview layout info/sizes - no prepare of preview paint");
288 if ( !bLayoutSettingsValid )
289 return false;
291 bool bStartPageRangeValid = nProposedStartPageNum <= mnPages;
292 OSL_ENSURE( bStartPageRangeValid,
293 "proposed start page not existing - no prepare of preview paint");
294 if ( !bStartPageRangeValid )
295 return false;
297 bool bStartPosRangeValid =
298 rProposedStartPos.X() >= 0 && rProposedStartPos.Y() >= 0 &&
299 rProposedStartPos.X() <= maPreviewDocRect.Right() &&
300 rProposedStartPos.Y() <= maPreviewDocRect.Bottom();
301 OSL_ENSURE( bStartPosRangeValid,
302 "proposed start position out of range - no prepare of preview paint");
303 if ( !bStartPosRangeValid )
304 return false;
306 bool bWinSizeValid = !_rPxWinSize.IsEmpty();
307 OSL_ENSURE( bWinSizeValid, "no window size - no prepare of preview paint");
308 if ( !bWinSizeValid )
309 return false;
311 bool bStartInfoValid = _nProposedStartPageNum > 0 ||
312 rProposedStartPos != Point(0,0);
313 if ( !bStartInfoValid )
314 nProposedStartPageNum = 1;
317 // environment and parameter ok
319 // update window size at preview setting data
320 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
322 mbNoPageVisible = false;
323 if ( nProposedStartPageNum > 0 )
325 // determine column and row of proposed start page in virtual preview layout
326 const sal_uInt16 nColOfProposed = GetColOfPage( nProposedStartPageNum );
327 const sal_uInt16 nRowOfProposed = GetRowOfPage( nProposedStartPageNum );
328 // determine start page
329 if ( _bStartWithPageAtFirstCol )
331 // leaving left-top-corner blank is
332 // controlled by <mbBookPreview>.
333 if ( mbBookPreview &&
334 ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
336 mnPaintPhyStartPageNum = 1;
337 else
338 mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
340 else
341 mnPaintPhyStartPageNum = nProposedStartPageNum;
343 mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
345 // set starting column
346 if ( _bStartWithPageAtFirstCol )
347 mnPaintStartCol = 1;
348 else
349 mnPaintStartCol = nColOfProposed;
350 // set starting row
351 mnPaintStartRow = nRowOfProposed;
352 // page offset == (-1,-1), indicating no offset and paint of free space.
353 maPaintStartPageOffset.setX( -1 );
354 maPaintStartPageOffset.setY( -1 );
355 // virtual preview document offset.
356 if ( _bStartWithPageAtFirstCol )
357 maPaintPreviewDocOffset.setX( 0 );
358 else
359 maPaintPreviewDocOffset.setX( (nColOfProposed-1) * mnColWidth );
360 maPaintPreviewDocOffset.setY( (nRowOfProposed-1) * mnRowHeight );
362 else
364 // determine column and row of proposed start position.
365 // Note: paint starts at point (0,0)
366 const sal_uInt16 nColOfProposed =
367 o3tl::narrowing<sal_uInt16>(rProposedStartPos.X() / mnColWidth) + 1;
368 const sal_uInt16 nRowOfProposed =
369 o3tl::narrowing<sal_uInt16>(rProposedStartPos.Y() / mnRowHeight) + 1;
370 // determine start page == page at proposed start position
371 // leaving left-top-corner blank is
372 // controlled by <mbBookPreview>.
373 if ( mbBookPreview &&
374 ( nRowOfProposed == 1 && nColOfProposed == 1 )
376 mnPaintPhyStartPageNum = 1;
377 else
379 // leaving left-top-corner blank is
380 // controlled by <mbBookPreview>.
381 mnPaintPhyStartPageNum = (nRowOfProposed-1) * mnCols + nColOfProposed;
382 if ( mbBookPreview )
383 --mnPaintPhyStartPageNum;
384 if ( mnPaintPhyStartPageNum > mnPages )
386 // no page will be visible, because shown part of document
387 // preview is the last row to the right of the last page
388 mnPaintPhyStartPageNum = mnPages;
389 mbNoPageVisible = true;
392 // set starting column and starting row
393 mnPaintStartCol = nColOfProposed;
394 mnPaintStartRow = nRowOfProposed;
395 // page offset
396 maPaintStartPageOffset.setX(
397 (rProposedStartPos.X() % mnColWidth) - gnXFree );
398 maPaintStartPageOffset.setY(
399 (rProposedStartPos.Y() % mnRowHeight) - gnYFree );
400 // virtual preview document offset.
401 maPaintPreviewDocOffset = rProposedStartPos;
404 // determine additional paint offset, if preview layout fits into window.
405 CalcAdditionalPaintOffset();
407 // determine rectangle to be painted from document preview
408 CalcDocPreviewPaintRect();
409 _orDocPreviewPaintRect = maPaintedPreviewDocRect;
411 // shift visible preview document area to the left,
412 // if on the right is an area left blank.
413 if ( !mbDoesLayoutColsFitIntoWindow &&
414 maPaintedPreviewDocRect.GetWidth() < maWinSize.Width() )
416 maPaintedPreviewDocRect.Move(
417 -(maWinSize.Width() - maPaintedPreviewDocRect.GetWidth()), 0 );
418 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
419 _rPxWinSize, _onStartPageNum,
420 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
423 // shift visible preview document area to the top,
424 // if on the bottom is an area left blank.
425 if ( mbBookPreviewModeToggled &&
426 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom() &&
427 maPaintedPreviewDocRect.GetHeight() < maWinSize.Height() )
429 if ( mbDoesLayoutRowsFitIntoWindow )
431 if ( maPaintedPreviewDocRect.GetHeight() < mnPreviewLayoutHeight)
433 maPaintedPreviewDocRect.Move(
434 0, -(mnPreviewLayoutHeight - maPaintedPreviewDocRect.GetHeight()) );
435 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
436 _rPxWinSize, _onStartPageNum,
437 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
440 else
442 maPaintedPreviewDocRect.Move(
443 0, -(maWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) );
444 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
445 _rPxWinSize, _onStartPageNum,
446 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
450 // determine preview pages - visible pages with needed data for paint and
451 // accessible pages with needed data.
452 CalcPreviewPages();
454 // OD 07.11.2003 #i22014# - indicate new layout, if print preview is in paint
455 if ( mbInPaint )
457 mbNewLayoutDuringPaint = true;
460 // validate paint data
461 mbPaintInfoValid = true;
463 // return start page
464 _onStartPageNum = mnPaintPhyStartPageNum;
466 return true;
469 /** calculate additional paint offset
472 void SwPagePreviewLayout::CalcAdditionalPaintOffset()
474 if ( mnPreviewLayoutWidth <= maWinSize.Width() &&
475 maPaintStartPageOffset.X() <= 0 )
477 mbDoesLayoutColsFitIntoWindow = true;
478 maAdditionalPaintOffset.setX( (maWinSize.Width() - mnPreviewLayoutWidth) / 2 );
480 else
482 mbDoesLayoutColsFitIntoWindow = false;
483 maAdditionalPaintOffset.setX( 0 );
486 if ( mnPreviewLayoutHeight <= maWinSize.Height() &&
487 maPaintStartPageOffset.Y() <= 0 )
489 mbDoesLayoutRowsFitIntoWindow = true;
490 maAdditionalPaintOffset.setY( (maWinSize.Height() - mnPreviewLayoutHeight) / 2 );
492 else
494 mbDoesLayoutRowsFitIntoWindow = false;
495 maAdditionalPaintOffset.setY( 0 );
499 /** calculate painted preview document rectangle
502 void SwPagePreviewLayout::CalcDocPreviewPaintRect()
504 Point aTopLeftPos = maPaintPreviewDocOffset;
505 maPaintedPreviewDocRect.SetPos( aTopLeftPos );
507 Size aSize;
508 if ( mbDoesLayoutColsFitIntoWindow )
509 aSize.setWidth( std::min( tools::Long(mnPreviewLayoutWidth),
510 maPreviewDocRect.GetWidth() - aTopLeftPos.X() ) );
511 else
512 aSize.setWidth( std::min( maPreviewDocRect.GetWidth() - aTopLeftPos.X(),
513 maWinSize.Width() - maAdditionalPaintOffset.X() ) );
514 if ( mbDoesLayoutRowsFitIntoWindow )
515 aSize.setHeight( std::min( tools::Long(mnPreviewLayoutHeight),
516 maPreviewDocRect.GetHeight() - aTopLeftPos.Y() ) );
517 else
518 aSize.setHeight( std::min( maPreviewDocRect.GetHeight() - aTopLeftPos.Y(),
519 maWinSize.Height() - maAdditionalPaintOffset.Y() ) );
520 maPaintedPreviewDocRect.SetSize( aSize );
523 /** calculate preview pages
526 void SwPagePreviewLayout::CalcPreviewPages()
528 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
529 ClearPreviewPageData();
531 if ( mbNoPageVisible )
532 return;
534 // determine start page frame
535 const SwPageFrame* pStartPage = mrLayoutRootFrame.GetPageByPageNum( mnPaintPhyStartPageNum );
537 // calculate initial paint offset
538 Point aInitialPaintOffset;
539 /// check whether RTL interface or not
540 if(!AllSettings::GetLayoutRTL()){
541 if ( maPaintStartPageOffset != Point( -1, -1 ) )
542 aInitialPaintOffset = Point(0,0) - maPaintStartPageOffset;
543 else
544 aInitialPaintOffset = Point( gnXFree, gnYFree );
546 else {
547 if ( maPaintStartPageOffset != Point( -1, -1 ) )
548 aInitialPaintOffset = Point(0 + ((SwPagePreviewLayout::mnCols-1)*mnColWidth),0) - maPaintStartPageOffset;
549 else
550 aInitialPaintOffset = Point( gnXFree + ((SwPagePreviewLayout::mnCols-1)*mnColWidth), gnYFree );
552 aInitialPaintOffset += maAdditionalPaintOffset;
554 // prepare loop data
555 const SwPageFrame* pPage = pStartPage;
556 sal_uInt16 nCurrCol = mnPaintStartCol;
557 sal_uInt16 nConsideredRows = 0;
558 Point aCurrPaintOffset = aInitialPaintOffset;
559 // loop on pages to determine preview background rectangles
560 while ( pPage &&
561 (!mbDoesLayoutRowsFitIntoWindow || nConsideredRows < mnRows) &&
562 aCurrPaintOffset.Y() < maWinSize.Height()
565 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
567 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
568 continue;
571 pPage->Calc(pRenderContext);
573 // consider only pages, which have to be painted.
574 if ( nCurrCol < mnPaintStartCol )
576 // calculate data of unvisible page needed for accessibility
577 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
578 Point aCurrAccOffset = aCurrPaintOffset -
579 Point( (mnPaintStartCol-nCurrCol) * mnColWidth, 0 );
580 CalcPreviewDataForPage( *pPage, aCurrAccOffset, pPreviewPage.get() );
581 pPreviewPage->bVisible = false;
582 maPreviewPages.push_back( std::move(pPreviewPage) );
583 // continue with next page and next column
584 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
585 ++nCurrCol;
586 continue;
588 if ( aCurrPaintOffset.X() < maWinSize.Width() )
590 // leaving left-top-corner blank is
591 // controlled by <mbBookPreview>.
592 if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1
595 // first page in 2nd column
596 // --> continue with increased paint offset and next column
597 /// check whether RTL interface or not
598 if(!AllSettings::GetLayoutRTL())
599 aCurrPaintOffset.AdjustX(mnColWidth );
600 else aCurrPaintOffset.AdjustX( -mnColWidth );
601 ++nCurrCol;
602 continue;
605 // calculate data of visible page
606 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
607 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
608 pPreviewPage->bVisible = true;
609 maPreviewPages.push_back( std::move(pPreviewPage) );
611 else
613 // calculate data of unvisible page needed for accessibility
614 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
615 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
616 pPreviewPage->bVisible = false;
617 maPreviewPages.push_back( std::move(pPreviewPage) );
620 // prepare data for next loop
621 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
623 /// check whether RTL interface or not
624 if(!AllSettings::GetLayoutRTL())
625 aCurrPaintOffset.AdjustX(mnColWidth );
626 else aCurrPaintOffset.AdjustX( -mnColWidth );
627 ++nCurrCol;
628 if ( nCurrCol > mnCols )
630 ++nConsideredRows;
631 aCurrPaintOffset.setX( aInitialPaintOffset.X() );
632 nCurrCol = 1;
633 aCurrPaintOffset.AdjustY(mnRowHeight );
638 /** determines preview data for a given page and a given preview offset
640 OD 13.12.2002 #103492#
642 void SwPagePreviewLayout::CalcPreviewDataForPage( const SwPageFrame& _rPage,
643 const Point& _rPreviewOffset,
644 PreviewPage* _opPreviewPage )
646 // page frame
647 _opPreviewPage->pPage = &_rPage;
648 // size of page frame
649 if ( _rPage.IsEmptyPage() )
651 if ( _rPage.GetPhyPageNum() % 2 == 0 )
652 _opPreviewPage->aPageSize = _rPage.GetPrev()->getFrameArea().SSize();
653 else
654 _opPreviewPage->aPageSize = _rPage.GetNext()->getFrameArea().SSize();
656 else
657 _opPreviewPage->aPageSize = _rPage.getFrameArea().SSize();
658 // position of page in preview window
659 Point aPreviewWinOffset( _rPreviewOffset );
660 if ( _opPreviewPage->aPageSize.Width() < maMaxPageSize.Width() )
661 aPreviewWinOffset.AdjustX(( maMaxPageSize.Width() - _opPreviewPage->aPageSize.Width() ) / 2 );
662 if ( _opPreviewPage->aPageSize.Height() < maMaxPageSize.Height() )
663 aPreviewWinOffset.AdjustY(( maMaxPageSize.Height() - _opPreviewPage->aPageSize.Height() ) / 2 );
664 _opPreviewPage->aPreviewWinPos = aPreviewWinOffset;
665 // logic position of page and mapping offset for paint
666 if ( _rPage.IsEmptyPage() )
668 _opPreviewPage->aLogicPos = _opPreviewPage->aPreviewWinPos;
669 _opPreviewPage->aMapOffset = Point( 0, 0 );
671 else
673 _opPreviewPage->aLogicPos = _rPage.getFrameArea().Pos();
674 _opPreviewPage->aMapOffset = _opPreviewPage->aPreviewWinPos - _opPreviewPage->aLogicPos;
678 /** enable/disable book preview
680 OD 2004-03-04 #i18143#
682 bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
683 sal_uInt16& _onStartPageNum,
684 tools::Rectangle& _orDocPreviewPaintRect )
686 if ( mbBookPreview != _bEnableBookPreview)
688 mbBookPreview = _bEnableBookPreview;
689 // re-initialize page preview layout
690 ReInit();
691 // re-prepare page preview layout
693 mbBookPreviewModeToggled = true;
694 Point aProposedStartPos( maPaintPreviewDocOffset );
695 // if proposed start position is below virtual preview document
696 // bottom, adjust it to the virtual preview document bottom
697 if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
699 aProposedStartPos.setY( maPreviewDocRect.Bottom() );
701 Prepare( 0, aProposedStartPos,
702 mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
703 _onStartPageNum, _orDocPreviewPaintRect );
704 mbBookPreviewModeToggled = false;
707 return true;
710 return false;
713 // methods to determine new data for changing the current shown part of the
714 // document preview.
716 /** calculate start position for new scale
719 Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
720 const Fraction& _aNewScale,
721 const Fraction& _aOldScale,
722 const Size& _aNewWinSize ) const
724 Point aNewPaintStartPos = maPaintedPreviewDocRect.TopLeft();
725 if ( _aNewScale < _aOldScale )
727 // increase paint width by moving start point to left.
728 if ( mnPreviewLayoutWidth < _aNewWinSize.Width() )
729 aNewPaintStartPos.setX( 0 );
730 else if ( maPaintedPreviewDocRect.GetWidth() < _aNewWinSize.Width() )
732 aNewPaintStartPos.AdjustX( -(
733 (_aNewWinSize.Width() - maPaintedPreviewDocRect.GetWidth()) / 2) );
734 if ( aNewPaintStartPos.X() < 0)
735 aNewPaintStartPos.setX( 0 );
738 if ( !mbDoesLayoutRowsFitIntoWindow )
740 // increase paint height by moving start point to top.
741 if ( mnPreviewLayoutHeight < _aNewWinSize.Height() )
743 aNewPaintStartPos.setY(
744 (mnPaintStartRow - 1) * mnRowHeight );
746 else if ( maPaintedPreviewDocRect.GetHeight() < _aNewWinSize.Height() )
748 aNewPaintStartPos.AdjustY( -(
749 (_aNewWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) / 2) );
750 if ( aNewPaintStartPos.Y() < 0)
751 aNewPaintStartPos.setY( 0 );
755 else
757 // decrease paint width by moving start point to right
758 if ( maPaintedPreviewDocRect.GetWidth() > _aNewWinSize.Width() )
759 aNewPaintStartPos.AdjustX(
760 (maPaintedPreviewDocRect.GetWidth() - _aNewWinSize.Width()) / 2 );
761 // decrease paint height by moving start point to bottom
762 if ( maPaintedPreviewDocRect.GetHeight() > _aNewWinSize.Height() )
764 aNewPaintStartPos.AdjustY(
765 (maPaintedPreviewDocRect.GetHeight() - _aNewWinSize.Height()) / 2 );
766 // check, if new y-position is outside document preview
767 if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
768 aNewPaintStartPos.setY(
769 std::max( tools::Long(0), maPreviewDocRect.Bottom() - mnPreviewLayoutHeight ) );
773 return aNewPaintStartPos;
776 /** determines, if page with given page number is visible in preview
778 @note _nPageNum is absolute
780 bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
782 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
783 return pPreviewPage && pPreviewPage->bVisible;
786 /** calculate data to bring new selected page into view.
788 @note IN/OUT parameters are absolute page numbers!!!
790 void SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
791 const sal_Int16 _nHoriMove,
792 const sal_Int16 _nVertMove,
793 sal_uInt16& _orNewSelectedPage,
794 sal_uInt16& _orNewStartPage,
795 Point& _orNewStartPos ) const
797 // determine position of current selected page
798 sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
799 sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
801 const sal_uInt16 nCurrRow = GetRowOfPage(nTmpRelSelPageNum);
803 // determine new selected page number
805 if ( _nHoriMove != 0 )
807 if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
808 nNewRelSelectedPageNum = 1;
809 else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
810 nNewRelSelectedPageNum = mnPages;
811 else
812 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
814 if ( _nVertMove != 0 )
816 if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
817 nNewRelSelectedPageNum = 1;
818 else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
819 nNewRelSelectedPageNum = mnPages;
820 else
821 nNewRelSelectedPageNum += ( _nVertMove * mnCols );
825 sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
826 Point aNewStartPos(0,0);
828 const sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
829 if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
831 if ( _nHoriMove != 0 && _nVertMove != 0 )
833 OSL_FAIL( "missing implementation for moving preview selected page horizontal AND vertical");
834 return;
837 // new selected page has to be brought into view considering current
838 // visible preview.
839 const sal_uInt16 nTotalRows = GetRowOfPage( mnPages );
840 if ( (_nHoriMove > 0 || _nVertMove > 0) &&
841 mbDoesLayoutRowsFitIntoWindow &&
842 mbDoesLayoutColsFitIntoWindow &&
843 nCurrRow > nTotalRows - mnRows )
845 // new proposed start page = left-top-corner of last possible
846 // preview page.
847 nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
848 // leaving left-top-corner blank is controlled
849 // by <mbBookPreview>.
850 if ( mbBookPreview )
852 // Note: decrease new proposed start page number by one,
853 // because of blank left-top-corner
854 --nNewStartPage;
856 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
858 else
860 // new proposed start page = new selected page.
861 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
865 _orNewSelectedPage = nNewAbsSelectedPageNum;
866 _orNewStartPage = nNewStartPage;
867 _orNewStartPos = aNewStartPos;
870 namespace {
872 /** checks, if given position is inside a shown document page */
873 struct PreviewPosInsidePagePred
875 const Point mnPreviewPos;
876 explicit PreviewPosInsidePagePred(const Point& rPreviewPos)
877 : mnPreviewPos( rPreviewPos )
879 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
881 if ( _pPreviewPage->bVisible )
883 tools::Rectangle aPreviewPageRect( _pPreviewPage->aPreviewWinPos, _pPreviewPage->aPageSize );
884 return aPreviewPageRect.Contains( mnPreviewPos );
886 return false;
892 bool SwPagePreviewLayout::IsPreviewPosInDocPreviewPage( const Point& rPreviewPos,
893 Point& _orDocPos,
894 bool& _obPosInEmptyPage,
895 sal_uInt16& _onPageNum ) const
897 // initialize variable parameter values.
898 _orDocPos.setX( 0 );
899 _orDocPos.setY( 0 );
900 _obPosInEmptyPage = false;
901 _onPageNum = 0;
903 auto aFoundPreviewPageIter =
904 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
905 PreviewPosInsidePagePred( rPreviewPos ) );
907 if ( aFoundPreviewPageIter != maPreviewPages.end() )
909 // given preview position is inside a document page.
910 _onPageNum = (*aFoundPreviewPageIter)->pPage->GetPhyPageNum();
911 _obPosInEmptyPage = (*aFoundPreviewPageIter)->pPage->IsEmptyPage();
912 if ( !_obPosInEmptyPage )
914 // given preview position inside a normal page
915 _orDocPos = rPreviewPos -
916 (*aFoundPreviewPageIter)->aPreviewWinPos +
917 (*aFoundPreviewPageIter)->aLogicPos;
918 return true;
922 return false;
925 /** determine window page scroll amount */
926 SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
927 const sal_Int16 _nWinPagesToScroll ) const
929 SwTwips nScrollAmount;
930 if ( mbDoesLayoutRowsFitIntoWindow )
932 nScrollAmount = (mnPreviewLayoutHeight - gnYFree) * _nWinPagesToScroll;
934 else
935 nScrollAmount = _nWinPagesToScroll * maPaintedPreviewDocRect.GetHeight();
937 // check, if preview layout size values are valid.
938 // If not, the checks for an adjustment of the scroll amount aren't useful.
939 if ( mbLayoutSizesValid )
941 if ( (maPaintedPreviewDocRect.Top() + nScrollAmount) <= 0 )
942 nScrollAmount = -maPaintedPreviewDocRect.Top();
944 // correct scroll amount
945 if ( nScrollAmount > 0 &&
946 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom()
949 nScrollAmount = 0;
951 else
953 while ( (maPaintedPreviewDocRect.Top() + nScrollAmount + gnYFree) >= maPreviewDocRect.GetHeight() )
955 nScrollAmount -= mnRowHeight;
960 return nScrollAmount;
963 // methods to paint page preview layout
965 namespace
967 /// Similar to RenderContextGuard, but does not touch the draw view.
968 class PreviewRenderContextGuard
970 VclPtr<vcl::RenderContext> m_pOriginalValue;
971 SwViewShell& m_rShell;
973 public:
974 PreviewRenderContextGuard(SwViewShell& rShell, vcl::RenderContext* pValue)
975 : m_pOriginalValue(rShell.GetOut()),
976 m_rShell(rShell)
978 m_rShell.SetOut(pValue);
981 ~PreviewRenderContextGuard()
983 m_rShell.SetOut(m_pOriginalValue);
988 /** paint prepared preview
991 bool SwPagePreviewLayout::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rOutRect) const
993 PreviewRenderContextGuard aGuard(mrParentViewShell, &rRenderContext);
994 // check environment and parameters
996 if (!mrParentViewShell.GetWin() && !mrParentViewShell.GetOut()->GetConnectMetaFile())
998 return false;
1001 OSL_ENSURE(mbPaintInfoValid, "invalid preview settings - no paint of preview");
1002 if (!mbPaintInfoValid)
1003 return false;
1006 // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1007 if (mrLayoutRootFrame.IsSuperfluous())
1009 return true;
1012 // environment and parameter ok
1014 if (mbInPaint)
1016 return false;
1018 mbInPaint = true;
1020 OutputDevice* pOutputDev = &rRenderContext;
1022 // prepare paint
1023 if ( !maPreviewPages.empty() )
1025 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1026 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1027 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1030 // paint preview background
1032 SwRegionRects aPreviewBackgrdRegion((SwRect(rOutRect)));
1033 // calculate preview background rectangles
1034 for ( auto & rpPreviewPage : maPreviewPages )
1036 if ( rpPreviewPage->bVisible )
1038 aPreviewBackgrdRegion -=
1039 SwRect( rpPreviewPage->aPreviewWinPos, rpPreviewPage->aPageSize );
1042 // paint preview background rectangles
1043 mrParentViewShell.PaintDesktop_(aPreviewBackgrdRegion);
1046 // prepare data for paint of pages
1047 const tools::Rectangle aPxOutRect( pOutputDev->LogicToPixel(rOutRect) );
1049 MapMode aMapMode( pOutputDev->GetMapMode() );
1050 MapMode aSavedMapMode = aMapMode;
1052 const vcl::Font& rEmptyPgFont = SwPageFrame::GetEmptyPageFont();
1054 for ( auto & rpPreviewPage : maPreviewPages )
1056 if ( !rpPreviewPage->bVisible )
1057 continue;
1059 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1060 aMapMode.SetOrigin( rpPreviewPage->aMapOffset );
1061 pOutputDev->SetMapMode( aMapMode );
1062 tools::Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1063 if ( aPxOutRect.Overlaps( aPxPaintRect) )
1065 const SwPageFrame* pPage = rpPreviewPage->pPage;
1067 if (pPage->IsEmptyPage())
1069 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1070 if( pOutputDev->GetFillColor() != aRetouche )
1071 pOutputDev->SetFillColor( aRetouche );
1072 pOutputDev->SetLineColor(); // no line color
1073 // use aligned page rectangle
1075 SwRect aTmpPageRect( aPageRect );
1076 ::SwAlignRect( aTmpPageRect, &mrParentViewShell, &rRenderContext );
1077 aPageRect = aTmpPageRect.SVRect();
1079 pOutputDev->DrawRect( aPageRect );
1081 // paint empty page text
1082 vcl::Font aOldFont( pOutputDev->GetFont() );
1083 pOutputDev->SetFont( rEmptyPgFont );
1084 pOutputDev->DrawText( aPageRect, SwResId( STR_EMPTYPAGE ),
1085 DrawTextFlags::VCenter |
1086 DrawTextFlags::Center |
1087 DrawTextFlags::Clip );
1088 pOutputDev->SetFont( aOldFont );
1089 // paint shadow and border for empty page
1090 // use new method to paint page border and shadow
1091 SwPageFrame::PaintBorderAndShadow( SwRect(aPageRect), &mrParentViewShell, true, false, true );
1093 else
1095 const bool bIsLeftShadowed = pPage->IsLeftShadowNeeded();
1096 const bool bIsRightShadowed = pPage->IsRightShadowNeeded();
1098 mrParentViewShell.maVisArea = SwRect(aPageRect);
1099 aPxPaintRect.Intersection( aPxOutRect );
1100 tools::Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1101 mrParentViewShell.Paint(rRenderContext, aPaintRect);
1103 // --> OD 2007-08-15 #i80691#
1104 // paint page border and shadow
1106 SwRect aPageBorderRect;
1107 SwPageFrame::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, &rRenderContext, aPageBorderRect,
1108 bIsLeftShadowed, bIsRightShadowed, true );
1109 const vcl::Region aDLRegion(aPageBorderRect.SVRect());
1110 mrParentViewShell.DLPrePaint2(aDLRegion);
1111 SwPageFrame::PaintBorderAndShadow( SwRect(aPageRect), &mrParentViewShell, true, false, true );
1112 mrParentViewShell.DLPostPaint2(true);
1114 // <--
1116 // OD 07.11.2003 #i22014# - stop painting, because new print
1117 // preview layout is created during paint.
1118 if ( mbNewLayoutDuringPaint )
1120 break;
1123 if (pPage->GetPhyPageNum() == mnSelectedPageNum)
1125 PaintSelectMarkAtPage(rRenderContext, rpPreviewPage.get());
1130 // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1131 // print preview layout is created during paint.
1132 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1133 if ( !mbNewLayoutDuringPaint )
1135 // update at accessibility interface
1136 mrParentViewShell.Imp()->UpdateAccessiblePreview(
1137 maPreviewPages,
1138 aMapMode.GetScaleX(),
1139 mrLayoutRootFrame.GetPageByPageNum( mnSelectedPageNum ),
1140 maWinSize );
1142 #endif
1144 pOutputDev->SetMapMode( aSavedMapMode );
1145 mrParentViewShell.maVisArea.Clear();
1147 // OD 07.11.2003 #i22014#
1148 mbInPaint = false;
1149 mbNewLayoutDuringPaint = false;
1151 return true;
1154 /** repaint pages on page preview
1156 OD 18.12.2002 #103492#
1158 void SwPagePreviewLayout::Repaint( const tools::Rectangle& rInvalidCoreRect ) const
1160 // check environment and parameters
1162 if ( !mrParentViewShell.GetWin() &&
1163 !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1164 return;
1166 OSL_ENSURE( mbPaintInfoValid,
1167 "invalid preview settings - no paint of preview" );
1168 if ( !mbPaintInfoValid )
1169 return;
1172 // environment and parameter ok
1174 // prepare paint
1175 if ( !maPreviewPages.empty() )
1177 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1178 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1179 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1182 // invalidate visible pages, which overlap the invalid core rectangle
1183 for ( auto & rpPreviewPage : maPreviewPages )
1185 if ( !rpPreviewPage->bVisible )
1186 continue;
1188 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1189 if ( rInvalidCoreRect.Overlaps( aPageRect ) )
1191 aPageRect.Intersection(rInvalidCoreRect);
1192 tools::Rectangle aInvalidPreviewRect = aPageRect;
1193 aInvalidPreviewRect.SetPos( aInvalidPreviewRect.TopLeft() -
1194 rpPreviewPage->aLogicPos +
1195 rpPreviewPage->aPreviewWinPos );
1196 mrParentViewShell.GetWin()->Invalidate( aInvalidPreviewRect );
1201 /** paint selection mark at page
1203 OD 17.12.2002 #103492#
1205 void SwPagePreviewLayout::PaintSelectMarkAtPage(vcl::RenderContext& rRenderContext,
1206 const PreviewPage* _aSelectedPreviewPage ) const
1208 OutputDevice* pOutputDev = &rRenderContext;
1209 MapMode aMapMode( pOutputDev->GetMapMode() );
1210 // save mapping mode of output device
1211 MapMode aSavedMapMode = aMapMode;
1212 // save fill and line color of output device
1213 Color aFill( pOutputDev->GetFillColor() );
1214 Color aLine( pOutputDev->GetLineColor() );
1216 // determine selection mark color
1217 Color aSelPgLineColor(117, 114, 106);
1218 const StyleSettings& rSettings =
1219 mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1220 if ( rSettings.GetHighContrastMode() )
1221 aSelPgLineColor = rSettings.GetHighlightTextColor();
1223 // set needed mapping mode at output device
1224 aMapMode.SetOrigin( _aSelectedPreviewPage->aMapOffset );
1225 pOutputDev->SetMapMode( aMapMode );
1227 // calculate page rectangle in pixel coordinates
1228 SwRect aPageRect( _aSelectedPreviewPage->aLogicPos,
1229 _aSelectedPreviewPage->aPageSize );
1230 // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1231 // page border and shadow paint - see <SwPageFrame::PaintBorderAndShadow(..)>
1232 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1233 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1235 // draw two rectangle
1236 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1237 tools::Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1238 aPxPageRect.Right(), aPxPageRect.Bottom() );
1239 aRect = pOutputDev->PixelToLogic( aRect );
1240 pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1241 pOutputDev->SetLineColor( aSelPgLineColor );
1242 pOutputDev->DrawRect( aRect );
1243 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1244 aRect = tools::Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1245 aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1246 aRect = pOutputDev->PixelToLogic( aRect );
1247 pOutputDev->DrawRect( aRect );
1249 // reset fill and line color of output device
1250 pOutputDev->SetFillColor( aFill );
1251 pOutputDev->SetLineColor( aLine );
1253 // reset mapping mode of output device
1254 pOutputDev->SetMapMode( aSavedMapMode );
1257 /** paint to mark new selected page
1259 OD 17.12.2002 #103492#
1260 Perform paint for current selected page in order to unmark it.
1261 Set new selected page and perform paint to mark this page.
1263 @note _nSelectedPage, mnSelectedPage are absolute
1265 void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1267 const sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1268 mnSelectedPageNum = _nSelectedPage;
1270 // re-paint for current selected page in order to unmark it.
1271 const PreviewPage* pOldSelectedPreviewPage = GetPreviewPageByPageNum( nOldSelectedPageNum );
1272 OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1273 if ( pOldSelectedPreviewPage && pOldSelectedPreviewPage->bVisible )
1275 // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1276 SwRect aPageRect( pOldSelectedPreviewPage->aPreviewWinPos,
1277 pOldSelectedPreviewPage->aPageSize );
1278 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1279 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1280 // invalidate top mark line
1281 tools::Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1282 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1283 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1284 // invalidate right mark line
1285 aInvalPxRect = tools::Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1286 aPxPageRect.Right(), aPxPageRect.Bottom() );
1287 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1288 // invalidate bottom mark line
1289 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1290 aPxPageRect.Right(), aPxPageRect.Bottom() );
1291 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1292 // invalidate left mark line
1293 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1294 aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1295 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1298 // re-paint for new selected page in order to mark it.
1299 const PreviewPage* pNewSelectedPreviewPage = GetPreviewPageByPageNum( _nSelectedPage );
1300 if ( pNewSelectedPreviewPage && pNewSelectedPreviewPage->bVisible )
1302 const PreviewPage* pSelectedPreviewPage = GetPreviewPageByPageNum(mnSelectedPageNum);
1303 SwRect aPageRect(pSelectedPreviewPage->aPreviewWinPos, pSelectedPreviewPage->aPageSize);
1304 ::SwAlignRect(aPageRect, &mrParentViewShell, pOutputDev);
1305 mrParentViewShell.GetWin()->Invalidate(aPageRect.SVRect());
1309 // helper methods
1311 namespace {
1313 /** get preview page by physical page number
1315 OD 17.12.2002 #103492#
1317 struct EqualsPageNumPred
1319 const sal_uInt16 mnPageNum;
1320 explicit EqualsPageNumPred(const sal_uInt16 _nPageNum)
1321 : mnPageNum( _nPageNum )
1323 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
1325 return _pPreviewPage->pPage->GetPhyPageNum() == mnPageNum;
1331 const PreviewPage* SwPagePreviewLayout::GetPreviewPageByPageNum( const sal_uInt16 _nPageNum ) const
1333 auto aFoundPreviewPageIter =
1334 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
1335 EqualsPageNumPred( _nPageNum ) );
1337 if ( aFoundPreviewPageIter == maPreviewPages.end() )
1338 return nullptr;
1340 return aFoundPreviewPageIter->get();
1343 /** determine row the page with the given number is in
1345 OD 17.01.2003 #103492#
1347 @note _nPageNum is relative
1349 sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1351 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1352 // by <mbBookPreview>.
1353 if ( mbBookPreview )
1355 // Note: increase given physical page number by one, because left-top-corner
1356 // in the preview layout is left blank.
1357 ++_nPageNum;
1360 return _nPageNum / mnCols + ((_nPageNum % mnCols)>0 ? 1 : 0);
1363 /** determine column the page with the given number is in
1365 OD 17.01.2003 #103492#
1367 @note _nPageNum is relative
1369 sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1371 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1372 // by <mbBookPreview>.
1373 if ( mbBookPreview )
1375 // Note: increase given physical page number by one, because left-top-corner
1376 // in the preview layout is left blank.
1377 ++_nPageNum;
1380 const sal_uInt16 nCol = _nPageNum % mnCols;
1381 return nCol ? nCol : mnCols;
1384 Size SwPagePreviewLayout::GetPreviewDocSize() const
1386 OSL_ENSURE( PreviewLayoutValid(), "PagePreviewLayout not valid" );
1387 return maPreviewDocRect.GetSize();
1390 /** get size of a preview page by its physical page number
1392 OD 15.01.2003 #103492#
1394 Size SwPagePreviewLayout::GetPreviewPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1396 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1397 if ( pPreviewPage )
1399 return pPreviewPage->aPageSize;
1401 return Size( 0, 0 );
1404 /** get virtual page number by its physical page number
1406 OD 21.03.2003 #108282#
1408 sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1410 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1411 if ( pPreviewPage )
1413 return pPreviewPage->pPage->GetVirtPageNum();
1415 return 0;
1418 /** Convert absolute to relative page numbers (see PrintEmptyPages) */
1419 sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1421 if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
1423 return _nAbsPageNum;
1426 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1428 sal_uInt16 nRet = 1;
1430 while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
1432 if ( !pTmpPage->IsEmptyPage() )
1433 ++nRet;
1435 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1438 return nRet;
1441 /** Convert relative to absolute page numbers (see PrintEmptyPages) */
1442 sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1444 if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
1446 return _nRelPageNum;
1449 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1450 const SwPageFrame* pRet = nullptr;
1452 sal_uInt16 i = 0;
1453 while( pTmpPage && i != _nRelPageNum )
1455 if ( !pTmpPage->IsEmptyPage() )
1456 ++i;
1458 pRet = pTmpPage;
1459 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1462 return pRet->GetPhyPageNum();
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */