Add Marathi autocorrect
[LibreOffice.git] / sw / source / core / view / pagepreviewlayout.cxx
bloba1627def992bd7f46d8e38346acc83dcedee9332
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 mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages();
254 // check environment and parameters
256 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
257 OSL_ENSURE( bLayoutSettingsValid,
258 "no valid preview layout info/sizes - no re-init of page preview layout");
259 if ( !bLayoutSettingsValid )
260 return;
263 ClearPreviewLayoutSizes();
264 CalcPreviewLayoutSizes();
267 // methods to prepare paint of page preview
269 /** prepare paint of page preview
271 delete parameter _onStartPageVirtNum
273 @note _nProposedStartPageNum, _onStartPageNum are absolute
275 bool SwPagePreviewLayout::Prepare( const sal_uInt16 _nProposedStartPageNum,
276 const Point& rProposedStartPos,
277 const Size& _rPxWinSize,
278 sal_uInt16& _onStartPageNum,
279 tools::Rectangle& _orDocPreviewPaintRect,
280 const bool _bStartWithPageAtFirstCol
283 sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
284 // check environment and parameters
286 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
287 OSL_ENSURE( bLayoutSettingsValid,
288 "no valid preview layout info/sizes - no prepare of preview paint");
289 if ( !bLayoutSettingsValid )
290 return false;
292 bool bStartPageRangeValid = nProposedStartPageNum <= mnPages;
293 OSL_ENSURE( bStartPageRangeValid,
294 "proposed start page not existing - no prepare of preview paint");
295 if ( !bStartPageRangeValid )
296 return false;
298 bool bStartPosRangeValid =
299 rProposedStartPos.X() >= 0 && rProposedStartPos.Y() >= 0 &&
300 rProposedStartPos.X() <= maPreviewDocRect.Right() &&
301 rProposedStartPos.Y() <= maPreviewDocRect.Bottom();
302 OSL_ENSURE( bStartPosRangeValid,
303 "proposed start position out of range - no prepare of preview paint");
304 if ( !bStartPosRangeValid )
305 return false;
307 bool bWinSizeValid = !_rPxWinSize.IsEmpty();
308 OSL_ENSURE( bWinSizeValid, "no window size - no prepare of preview paint");
309 if ( !bWinSizeValid )
310 return false;
312 bool bStartInfoValid = _nProposedStartPageNum > 0 ||
313 rProposedStartPos != Point(0,0);
314 if ( !bStartInfoValid )
315 nProposedStartPageNum = 1;
318 // environment and parameter ok
320 // update window size at preview setting data
321 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
323 mbNoPageVisible = false;
324 if ( nProposedStartPageNum > 0 )
326 // determine column and row of proposed start page in virtual preview layout
327 const sal_uInt16 nColOfProposed = GetColOfPage( nProposedStartPageNum );
328 const sal_uInt16 nRowOfProposed = GetRowOfPage( nProposedStartPageNum );
329 // determine start page
330 if ( _bStartWithPageAtFirstCol )
332 // leaving left-top-corner blank is
333 // controlled by <mbBookPreview>.
334 if ( mbBookPreview &&
335 ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
337 mnPaintPhyStartPageNum = 1;
338 else
339 mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
341 else
342 mnPaintPhyStartPageNum = nProposedStartPageNum;
344 mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
346 // set starting column
347 if ( _bStartWithPageAtFirstCol )
348 mnPaintStartCol = 1;
349 else
350 mnPaintStartCol = nColOfProposed;
351 // set starting row
352 mnPaintStartRow = nRowOfProposed;
353 // page offset == (-1,-1), indicating no offset and paint of free space.
354 maPaintStartPageOffset.setX( -1 );
355 maPaintStartPageOffset.setY( -1 );
356 // virtual preview document offset.
357 if ( _bStartWithPageAtFirstCol )
358 maPaintPreviewDocOffset.setX( 0 );
359 else
360 maPaintPreviewDocOffset.setX( (nColOfProposed-1) * mnColWidth );
361 maPaintPreviewDocOffset.setY( (nRowOfProposed-1) * mnRowHeight );
363 else
365 // determine column and row of proposed start position.
366 // Note: paint starts at point (0,0)
367 const sal_uInt16 nColOfProposed =
368 o3tl::narrowing<sal_uInt16>(rProposedStartPos.X() / mnColWidth) + 1;
369 const sal_uInt16 nRowOfProposed =
370 o3tl::narrowing<sal_uInt16>(rProposedStartPos.Y() / mnRowHeight) + 1;
371 // determine start page == page at proposed start position
372 // leaving left-top-corner blank is
373 // controlled by <mbBookPreview>.
374 if ( mbBookPreview &&
375 ( nRowOfProposed == 1 && nColOfProposed == 1 )
377 mnPaintPhyStartPageNum = 1;
378 else
380 // leaving left-top-corner blank is
381 // controlled by <mbBookPreview>.
382 mnPaintPhyStartPageNum = (nRowOfProposed-1) * mnCols + nColOfProposed;
383 if ( mbBookPreview )
384 --mnPaintPhyStartPageNum;
385 if ( mnPaintPhyStartPageNum > mnPages )
387 // no page will be visible, because shown part of document
388 // preview is the last row to the right of the last page
389 mnPaintPhyStartPageNum = mnPages;
390 mbNoPageVisible = true;
393 mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum(
394 mnPaintPhyStartPageNum );
396 // set starting column and starting row
397 mnPaintStartCol = nColOfProposed;
398 mnPaintStartRow = nRowOfProposed;
399 // page offset
400 maPaintStartPageOffset.setX(
401 (rProposedStartPos.X() % mnColWidth) - gnXFree );
402 maPaintStartPageOffset.setY(
403 (rProposedStartPos.Y() % mnRowHeight) - gnYFree );
404 // virtual preview document offset.
405 maPaintPreviewDocOffset = rProposedStartPos;
408 // determine additional paint offset, if preview layout fits into window.
409 CalcAdditionalPaintOffset();
411 // determine rectangle to be painted from document preview
412 CalcDocPreviewPaintRect();
413 _orDocPreviewPaintRect = maPaintedPreviewDocRect;
415 // shift visible preview document area to the left,
416 // if on the right is an area left blank.
417 if ( !mbDoesLayoutColsFitIntoWindow &&
418 maPaintedPreviewDocRect.GetWidth() < maWinSize.Width() )
420 maPaintedPreviewDocRect.Move(
421 -(maWinSize.Width() - maPaintedPreviewDocRect.GetWidth()), 0 );
422 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
423 _rPxWinSize, _onStartPageNum,
424 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
427 // shift visible preview document area to the top,
428 // if on the bottom is an area left blank.
429 if ( mbBookPreviewModeToggled &&
430 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom() &&
431 maPaintedPreviewDocRect.GetHeight() < maWinSize.Height() )
433 if ( mbDoesLayoutRowsFitIntoWindow )
435 if ( maPaintedPreviewDocRect.GetHeight() < mnPreviewLayoutHeight)
437 maPaintedPreviewDocRect.Move(
438 0, -(mnPreviewLayoutHeight - maPaintedPreviewDocRect.GetHeight()) );
439 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
440 _rPxWinSize, _onStartPageNum,
441 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
444 else
446 maPaintedPreviewDocRect.Move(
447 0, -(maWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) );
448 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
449 _rPxWinSize, _onStartPageNum,
450 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
454 // determine preview pages - visible pages with needed data for paint and
455 // accessible pages with needed data.
456 CalcPreviewPages();
458 // OD 07.11.2003 #i22014# - indicate new layout, if print preview is in paint
459 if ( mbInPaint )
461 mbNewLayoutDuringPaint = true;
464 // validate paint data
465 mbPaintInfoValid = true;
467 // return start page
468 _onStartPageNum = mnPaintPhyStartPageNum;
470 return true;
473 /** calculate additional paint offset
476 void SwPagePreviewLayout::CalcAdditionalPaintOffset()
478 if ( mnPreviewLayoutWidth <= maWinSize.Width() &&
479 maPaintStartPageOffset.X() <= 0 )
481 mbDoesLayoutColsFitIntoWindow = true;
482 maAdditionalPaintOffset.setX( (maWinSize.Width() - mnPreviewLayoutWidth) / 2 );
484 else
486 mbDoesLayoutColsFitIntoWindow = false;
487 maAdditionalPaintOffset.setX( 0 );
490 if ( mnPreviewLayoutHeight <= maWinSize.Height() &&
491 maPaintStartPageOffset.Y() <= 0 )
493 mbDoesLayoutRowsFitIntoWindow = true;
494 maAdditionalPaintOffset.setY( (maWinSize.Height() - mnPreviewLayoutHeight) / 2 );
496 else
498 mbDoesLayoutRowsFitIntoWindow = false;
499 maAdditionalPaintOffset.setY( 0 );
503 /** calculate painted preview document rectangle
506 void SwPagePreviewLayout::CalcDocPreviewPaintRect()
508 Point aTopLeftPos = maPaintPreviewDocOffset;
509 maPaintedPreviewDocRect.SetPos( aTopLeftPos );
511 Size aSize;
512 if ( mbDoesLayoutColsFitIntoWindow )
513 aSize.setWidth( std::min( tools::Long(mnPreviewLayoutWidth),
514 maPreviewDocRect.GetWidth() - aTopLeftPos.X() ) );
515 else
516 aSize.setWidth( std::min( maPreviewDocRect.GetWidth() - aTopLeftPos.X(),
517 maWinSize.Width() - maAdditionalPaintOffset.X() ) );
518 if ( mbDoesLayoutRowsFitIntoWindow )
519 aSize.setHeight( std::min( tools::Long(mnPreviewLayoutHeight),
520 maPreviewDocRect.GetHeight() - aTopLeftPos.Y() ) );
521 else
522 aSize.setHeight( std::min( maPreviewDocRect.GetHeight() - aTopLeftPos.Y(),
523 maWinSize.Height() - maAdditionalPaintOffset.Y() ) );
524 maPaintedPreviewDocRect.SetSize( aSize );
527 /** calculate preview pages
530 void SwPagePreviewLayout::CalcPreviewPages()
532 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
533 ClearPreviewPageData();
535 if ( mbNoPageVisible )
536 return;
538 // determine start page frame
539 const SwPageFrame* pStartPage = mrLayoutRootFrame.GetPageByPageNum( mnPaintPhyStartPageNum );
541 // calculate initial paint offset
542 Point aInitialPaintOffset;
543 /// check whether RTL interface or not
544 if(!AllSettings::GetLayoutRTL()){
545 if ( maPaintStartPageOffset != Point( -1, -1 ) )
546 aInitialPaintOffset = Point(0,0) - maPaintStartPageOffset;
547 else
548 aInitialPaintOffset = Point( gnXFree, gnYFree );
550 else {
551 if ( maPaintStartPageOffset != Point( -1, -1 ) )
552 aInitialPaintOffset = Point(0 + ((SwPagePreviewLayout::mnCols-1)*mnColWidth),0) - maPaintStartPageOffset;
553 else
554 aInitialPaintOffset = Point( gnXFree + ((SwPagePreviewLayout::mnCols-1)*mnColWidth), gnYFree );
556 aInitialPaintOffset += maAdditionalPaintOffset;
558 // prepare loop data
559 const SwPageFrame* pPage = pStartPage;
560 sal_uInt16 nCurrCol = mnPaintStartCol;
561 sal_uInt16 nConsideredRows = 0;
562 Point aCurrPaintOffset = aInitialPaintOffset;
563 // loop on pages to determine preview background rectangles
564 while ( pPage &&
565 (!mbDoesLayoutRowsFitIntoWindow || nConsideredRows < mnRows) &&
566 aCurrPaintOffset.Y() < maWinSize.Height()
569 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
571 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
572 continue;
575 pPage->Calc(pRenderContext);
577 // consider only pages, which have to be painted.
578 if ( nCurrCol < mnPaintStartCol )
580 // calculate data of unvisible page needed for accessibility
581 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
582 Point aCurrAccOffset = aCurrPaintOffset -
583 Point( (mnPaintStartCol-nCurrCol) * mnColWidth, 0 );
584 CalcPreviewDataForPage( *pPage, aCurrAccOffset, pPreviewPage.get() );
585 pPreviewPage->bVisible = false;
586 maPreviewPages.push_back( std::move(pPreviewPage) );
587 // continue with next page and next column
588 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
589 ++nCurrCol;
590 continue;
592 if ( aCurrPaintOffset.X() < maWinSize.Width() )
594 // leaving left-top-corner blank is
595 // controlled by <mbBookPreview>.
596 if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1
599 // first page in 2nd column
600 // --> continue with increased paint offset and next column
601 /// check whether RTL interface or not
602 if(!AllSettings::GetLayoutRTL())
603 aCurrPaintOffset.AdjustX(mnColWidth );
604 else aCurrPaintOffset.AdjustX( -mnColWidth );
605 ++nCurrCol;
606 continue;
609 // calculate data of visible page
610 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
611 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
612 pPreviewPage->bVisible = true;
613 maPreviewPages.push_back( std::move(pPreviewPage) );
615 else
617 // calculate data of unvisible page needed for accessibility
618 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
619 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
620 pPreviewPage->bVisible = false;
621 maPreviewPages.push_back( std::move(pPreviewPage) );
624 // prepare data for next loop
625 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
627 /// check whether RTL interface or not
628 if(!AllSettings::GetLayoutRTL())
629 aCurrPaintOffset.AdjustX(mnColWidth );
630 else aCurrPaintOffset.AdjustX( -mnColWidth );
631 ++nCurrCol;
632 if ( nCurrCol > mnCols )
634 ++nConsideredRows;
635 aCurrPaintOffset.setX( aInitialPaintOffset.X() );
636 nCurrCol = 1;
637 aCurrPaintOffset.AdjustY(mnRowHeight );
642 /** determines preview data for a given page and a given preview offset
644 OD 13.12.2002 #103492#
646 void SwPagePreviewLayout::CalcPreviewDataForPage( const SwPageFrame& _rPage,
647 const Point& _rPreviewOffset,
648 PreviewPage* _opPreviewPage )
650 // page frame
651 _opPreviewPage->pPage = &_rPage;
652 // size of page frame
653 if ( _rPage.IsEmptyPage() )
655 if ( _rPage.GetPhyPageNum() % 2 == 0 )
656 _opPreviewPage->aPageSize = _rPage.GetPrev()->getFrameArea().SSize();
657 else
658 _opPreviewPage->aPageSize = _rPage.GetNext()->getFrameArea().SSize();
660 else
661 _opPreviewPage->aPageSize = _rPage.getFrameArea().SSize();
662 // position of page in preview window
663 Point aPreviewWinOffset( _rPreviewOffset );
664 if ( _opPreviewPage->aPageSize.Width() < maMaxPageSize.Width() )
665 aPreviewWinOffset.AdjustX(( maMaxPageSize.Width() - _opPreviewPage->aPageSize.Width() ) / 2 );
666 if ( _opPreviewPage->aPageSize.Height() < maMaxPageSize.Height() )
667 aPreviewWinOffset.AdjustY(( maMaxPageSize.Height() - _opPreviewPage->aPageSize.Height() ) / 2 );
668 _opPreviewPage->aPreviewWinPos = aPreviewWinOffset;
669 // logic position of page and mapping offset for paint
670 if ( _rPage.IsEmptyPage() )
672 _opPreviewPage->aLogicPos = _opPreviewPage->aPreviewWinPos;
673 _opPreviewPage->aMapOffset = Point( 0, 0 );
675 else
677 _opPreviewPage->aLogicPos = _rPage.getFrameArea().Pos();
678 _opPreviewPage->aMapOffset = _opPreviewPage->aPreviewWinPos - _opPreviewPage->aLogicPos;
682 /** enable/disable book preview
684 OD 2004-03-04 #i18143#
686 bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
687 sal_uInt16& _onStartPageNum,
688 tools::Rectangle& _orDocPreviewPaintRect )
690 if ( mbBookPreview != _bEnableBookPreview)
692 mbBookPreview = _bEnableBookPreview;
693 // re-initialize page preview layout
694 ReInit();
695 // re-prepare page preview layout
697 mbBookPreviewModeToggled = true;
698 Point aProposedStartPos( maPaintPreviewDocOffset );
699 // if proposed start position is below virtual preview document
700 // bottom, adjust it to the virtual preview document bottom
701 if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
703 aProposedStartPos.setY( maPreviewDocRect.Bottom() );
705 Prepare( 0, aProposedStartPos,
706 mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
707 _onStartPageNum, _orDocPreviewPaintRect );
708 mbBookPreviewModeToggled = false;
711 return true;
714 return false;
717 // methods to determine new data for changing the current shown part of the
718 // document preview.
720 /** calculate start position for new scale
723 Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
724 const Fraction& _aNewScale,
725 const Fraction& _aOldScale,
726 const Size& _aNewWinSize ) const
728 Point aNewPaintStartPos = maPaintedPreviewDocRect.TopLeft();
729 if ( _aNewScale < _aOldScale )
731 // increase paint width by moving start point to left.
732 if ( mnPreviewLayoutWidth < _aNewWinSize.Width() )
733 aNewPaintStartPos.setX( 0 );
734 else if ( maPaintedPreviewDocRect.GetWidth() < _aNewWinSize.Width() )
736 aNewPaintStartPos.AdjustX( -(
737 (_aNewWinSize.Width() - maPaintedPreviewDocRect.GetWidth()) / 2) );
738 if ( aNewPaintStartPos.X() < 0)
739 aNewPaintStartPos.setX( 0 );
742 if ( !mbDoesLayoutRowsFitIntoWindow )
744 // increase paint height by moving start point to top.
745 if ( mnPreviewLayoutHeight < _aNewWinSize.Height() )
747 aNewPaintStartPos.setY(
748 (mnPaintStartRow - 1) * mnRowHeight );
750 else if ( maPaintedPreviewDocRect.GetHeight() < _aNewWinSize.Height() )
752 aNewPaintStartPos.AdjustY( -(
753 (_aNewWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) / 2) );
754 if ( aNewPaintStartPos.Y() < 0)
755 aNewPaintStartPos.setY( 0 );
759 else
761 // decrease paint width by moving start point to right
762 if ( maPaintedPreviewDocRect.GetWidth() > _aNewWinSize.Width() )
763 aNewPaintStartPos.AdjustX(
764 (maPaintedPreviewDocRect.GetWidth() - _aNewWinSize.Width()) / 2 );
765 // decrease paint height by moving start point to bottom
766 if ( maPaintedPreviewDocRect.GetHeight() > _aNewWinSize.Height() )
768 aNewPaintStartPos.AdjustY(
769 (maPaintedPreviewDocRect.GetHeight() - _aNewWinSize.Height()) / 2 );
770 // check, if new y-position is outside document preview
771 if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
772 aNewPaintStartPos.setY(
773 std::max( tools::Long(0), maPreviewDocRect.Bottom() - mnPreviewLayoutHeight ) );
777 return aNewPaintStartPos;
780 /** determines, if page with given page number is visible in preview
782 @note _nPageNum is absolute
784 bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
786 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
787 return pPreviewPage && pPreviewPage->bVisible;
790 /** calculate data to bring new selected page into view.
792 @note IN/OUT parameters are absolute page numbers!!!
794 void SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
795 const sal_Int16 _nHoriMove,
796 const sal_Int16 _nVertMove,
797 sal_uInt16& _orNewSelectedPage,
798 sal_uInt16& _orNewStartPage,
799 Point& _orNewStartPos ) const
801 // determine position of current selected page
802 sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
803 sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
805 const sal_uInt16 nCurrRow = GetRowOfPage(nTmpRelSelPageNum);
807 // determine new selected page number
809 if ( _nHoriMove != 0 )
811 if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
812 nNewRelSelectedPageNum = 1;
813 else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
814 nNewRelSelectedPageNum = mnPages;
815 else
816 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
818 if ( _nVertMove != 0 )
820 if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
821 nNewRelSelectedPageNum = 1;
822 else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
823 nNewRelSelectedPageNum = mnPages;
824 else
825 nNewRelSelectedPageNum += ( _nVertMove * mnCols );
829 sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
830 Point aNewStartPos(0,0);
832 const sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
833 if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
835 if ( _nHoriMove != 0 && _nVertMove != 0 )
837 OSL_FAIL( "missing implementation for moving preview selected page horizontal AND vertical");
838 return;
841 // new selected page has to be brought into view considering current
842 // visible preview.
843 const sal_uInt16 nTotalRows = GetRowOfPage( mnPages );
844 if ( (_nHoriMove > 0 || _nVertMove > 0) &&
845 mbDoesLayoutRowsFitIntoWindow &&
846 mbDoesLayoutColsFitIntoWindow &&
847 nCurrRow > nTotalRows - mnRows )
849 // new proposed start page = left-top-corner of last possible
850 // preview page.
851 nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
852 // leaving left-top-corner blank is controlled
853 // by <mbBookPreview>.
854 if ( mbBookPreview )
856 // Note: decrease new proposed start page number by one,
857 // because of blank left-top-corner
858 --nNewStartPage;
860 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
862 else
864 // new proposed start page = new selected page.
865 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
869 _orNewSelectedPage = nNewAbsSelectedPageNum;
870 _orNewStartPage = nNewStartPage;
871 _orNewStartPos = aNewStartPos;
874 namespace {
876 /** checks, if given position is inside a shown document page */
877 struct PreviewPosInsidePagePred
879 const Point mnPreviewPos;
880 explicit PreviewPosInsidePagePred(const Point& rPreviewPos)
881 : mnPreviewPos( rPreviewPos )
883 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
885 if ( _pPreviewPage->bVisible )
887 tools::Rectangle aPreviewPageRect( _pPreviewPage->aPreviewWinPos, _pPreviewPage->aPageSize );
888 return aPreviewPageRect.Contains( mnPreviewPos );
890 return false;
896 bool SwPagePreviewLayout::IsPreviewPosInDocPreviewPage( const Point& rPreviewPos,
897 Point& _orDocPos,
898 bool& _obPosInEmptyPage,
899 sal_uInt16& _onPageNum ) const
901 // initialize variable parameter values.
902 _orDocPos.setX( 0 );
903 _orDocPos.setY( 0 );
904 _obPosInEmptyPage = false;
905 _onPageNum = 0;
907 auto aFoundPreviewPageIter =
908 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
909 PreviewPosInsidePagePred( rPreviewPos ) );
911 if ( aFoundPreviewPageIter != maPreviewPages.end() )
913 // given preview position is inside a document page.
914 _onPageNum = (*aFoundPreviewPageIter)->pPage->GetPhyPageNum();
915 _obPosInEmptyPage = (*aFoundPreviewPageIter)->pPage->IsEmptyPage();
916 if ( !_obPosInEmptyPage )
918 // given preview position inside a normal page
919 _orDocPos = rPreviewPos -
920 (*aFoundPreviewPageIter)->aPreviewWinPos +
921 (*aFoundPreviewPageIter)->aLogicPos;
922 return true;
926 return false;
929 /** determine window page scroll amount */
930 SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
931 const sal_Int16 _nWinPagesToScroll ) const
933 SwTwips nScrollAmount;
934 if ( mbDoesLayoutRowsFitIntoWindow )
936 nScrollAmount = (mnPreviewLayoutHeight - gnYFree) * _nWinPagesToScroll;
938 else
940 // coverity[ tainted_data_return : FALSE ] version 2023.12.2
941 nScrollAmount = _nWinPagesToScroll * maPaintedPreviewDocRect.GetHeight();
944 // check, if preview layout size values are valid.
945 // If not, the checks for an adjustment of the scroll amount aren't useful.
946 if ( mbLayoutSizesValid )
948 if ( (maPaintedPreviewDocRect.Top() + nScrollAmount) <= 0 )
949 nScrollAmount = -maPaintedPreviewDocRect.Top();
951 // correct scroll amount
952 if ( nScrollAmount > 0 &&
953 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom()
956 nScrollAmount = 0;
958 else
960 while ( (maPaintedPreviewDocRect.Top() + nScrollAmount + gnYFree) >= maPreviewDocRect.GetHeight() )
962 nScrollAmount -= mnRowHeight;
967 return nScrollAmount;
970 // methods to paint page preview layout
972 namespace
974 /// Similar to RenderContextGuard, but does not touch the draw view.
975 class PreviewRenderContextGuard
977 VclPtr<vcl::RenderContext> m_pOriginalValue;
978 SwViewShell& m_rShell;
980 public:
981 PreviewRenderContextGuard(SwViewShell& rShell, vcl::RenderContext* pValue)
982 : m_pOriginalValue(rShell.GetOut()),
983 m_rShell(rShell)
985 m_rShell.SetOut(pValue);
988 ~PreviewRenderContextGuard()
990 m_rShell.SetOut(m_pOriginalValue);
995 /** paint prepared preview
998 bool SwPagePreviewLayout::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rOutRect) const
1000 PreviewRenderContextGuard aGuard(mrParentViewShell, &rRenderContext);
1001 // check environment and parameters
1003 if (!mrParentViewShell.GetWin() && !mrParentViewShell.GetOut()->GetConnectMetaFile())
1005 return false;
1008 OSL_ENSURE(mbPaintInfoValid, "invalid preview settings - no paint of preview");
1009 if (!mbPaintInfoValid)
1010 return false;
1013 // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1014 if (mrLayoutRootFrame.IsSuperfluous())
1016 return true;
1019 // environment and parameter ok
1021 if (mbInPaint)
1023 return false;
1025 mbInPaint = true;
1027 OutputDevice* pOutputDev = &rRenderContext;
1029 // prepare paint
1030 if ( !maPreviewPages.empty() )
1032 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1033 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1034 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1037 // paint preview background
1039 SwRegionRects aPreviewBackgrdRegion((SwRect(rOutRect)));
1040 // calculate preview background rectangles
1041 for ( auto & rpPreviewPage : maPreviewPages )
1043 if ( rpPreviewPage->bVisible )
1045 aPreviewBackgrdRegion -=
1046 SwRect( rpPreviewPage->aPreviewWinPos, rpPreviewPage->aPageSize );
1049 // paint preview background rectangles
1050 mrParentViewShell.PaintDesktop_(aPreviewBackgrdRegion);
1053 // prepare data for paint of pages
1054 const tools::Rectangle aPxOutRect( pOutputDev->LogicToPixel(rOutRect) );
1056 MapMode aMapMode( pOutputDev->GetMapMode() );
1057 MapMode aSavedMapMode = aMapMode;
1059 const vcl::Font& rEmptyPgFont = SwPageFrame::GetEmptyPageFont();
1061 for ( auto & rpPreviewPage : maPreviewPages )
1063 if ( !rpPreviewPage->bVisible )
1064 continue;
1066 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1067 aMapMode.SetOrigin( rpPreviewPage->aMapOffset );
1068 pOutputDev->SetMapMode( aMapMode );
1069 tools::Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1070 if ( aPxOutRect.Overlaps( aPxPaintRect) )
1072 const SwPageFrame* pPage = rpPreviewPage->pPage;
1074 if (pPage->IsEmptyPage())
1076 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1077 if( pOutputDev->GetFillColor() != aRetouche )
1078 pOutputDev->SetFillColor( aRetouche );
1079 pOutputDev->SetLineColor(); // no line color
1080 // use aligned page rectangle
1082 SwRect aTmpPageRect( aPageRect );
1083 ::SwAlignRect( aTmpPageRect, &mrParentViewShell, &rRenderContext );
1084 aPageRect = aTmpPageRect.SVRect();
1086 pOutputDev->DrawRect( aPageRect );
1088 // paint empty page text
1089 vcl::Font aOldFont( pOutputDev->GetFont() );
1090 pOutputDev->SetFont( rEmptyPgFont );
1091 pOutputDev->DrawText( aPageRect, SwResId( STR_EMPTYPAGE ),
1092 DrawTextFlags::VCenter |
1093 DrawTextFlags::Center |
1094 DrawTextFlags::Clip );
1095 pOutputDev->SetFont( aOldFont );
1096 // paint shadow and border for empty page
1097 // use new method to paint page border and shadow
1098 SwPageFrame::PaintBorderAndShadow( SwRect(aPageRect), &mrParentViewShell, true, false, true );
1100 else
1102 const bool bIsLeftShadowed = pPage->IsLeftShadowNeeded();
1103 const bool bIsRightShadowed = pPage->IsRightShadowNeeded();
1105 mrParentViewShell.maVisArea = SwRect(aPageRect);
1106 aPxPaintRect.Intersection( aPxOutRect );
1107 tools::Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1108 mrParentViewShell.Paint(rRenderContext, aPaintRect);
1110 // --> OD 2007-08-15 #i80691#
1111 // paint page border and shadow
1113 SwRect aPageBorderRect;
1114 SwPageFrame::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, &rRenderContext, aPageBorderRect,
1115 bIsLeftShadowed, bIsRightShadowed, true );
1116 const vcl::Region aDLRegion(aPageBorderRect.SVRect());
1117 mrParentViewShell.DLPrePaint2(aDLRegion);
1118 SwPageFrame::PaintBorderAndShadow( SwRect(aPageRect), &mrParentViewShell, true, false, true );
1119 mrParentViewShell.DLPostPaint2(true);
1121 // <--
1123 // OD 07.11.2003 #i22014# - stop painting, because new print
1124 // preview layout is created during paint.
1125 if ( mbNewLayoutDuringPaint )
1127 break;
1130 if (pPage->GetPhyPageNum() == mnSelectedPageNum)
1132 PaintSelectMarkAtPage(rRenderContext, rpPreviewPage.get());
1137 // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1138 // print preview layout is created during paint.
1139 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1140 if ( !mbNewLayoutDuringPaint )
1142 // update at accessibility interface
1143 mrParentViewShell.Imp()->UpdateAccessiblePreview(
1144 maPreviewPages,
1145 aMapMode.GetScaleX(),
1146 mrLayoutRootFrame.GetPageByPageNum( mnSelectedPageNum ),
1147 maWinSize );
1149 #endif
1151 pOutputDev->SetMapMode( aSavedMapMode );
1152 mrParentViewShell.maVisArea.Clear();
1154 // OD 07.11.2003 #i22014#
1155 mbInPaint = false;
1156 mbNewLayoutDuringPaint = false;
1158 return true;
1161 /** repaint pages on page preview
1163 OD 18.12.2002 #103492#
1165 void SwPagePreviewLayout::Repaint( const tools::Rectangle& rInvalidCoreRect ) const
1167 // check environment and parameters
1169 if ( !mrParentViewShell.GetWin() &&
1170 !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1171 return;
1173 OSL_ENSURE( mbPaintInfoValid,
1174 "invalid preview settings - no paint of preview" );
1175 if ( !mbPaintInfoValid )
1176 return;
1179 // environment and parameter ok
1181 // prepare paint
1182 if ( !maPreviewPages.empty() )
1184 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1185 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1186 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1189 // invalidate visible pages, which overlap the invalid core rectangle
1190 for ( auto & rpPreviewPage : maPreviewPages )
1192 if ( !rpPreviewPage->bVisible )
1193 continue;
1195 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1196 if ( rInvalidCoreRect.Overlaps( aPageRect ) )
1198 aPageRect.Intersection(rInvalidCoreRect);
1199 tools::Rectangle aInvalidPreviewRect = aPageRect;
1200 aInvalidPreviewRect.SetPos( aInvalidPreviewRect.TopLeft() -
1201 rpPreviewPage->aLogicPos +
1202 rpPreviewPage->aPreviewWinPos );
1203 mrParentViewShell.GetWin()->Invalidate( aInvalidPreviewRect );
1208 /** paint selection mark at page
1210 OD 17.12.2002 #103492#
1212 void SwPagePreviewLayout::PaintSelectMarkAtPage(vcl::RenderContext& rRenderContext,
1213 const PreviewPage* _aSelectedPreviewPage ) const
1215 OutputDevice* pOutputDev = &rRenderContext;
1216 MapMode aMapMode( pOutputDev->GetMapMode() );
1217 // save mapping mode of output device
1218 MapMode aSavedMapMode = aMapMode;
1219 // save fill and line color of output device
1220 Color aFill( pOutputDev->GetFillColor() );
1221 Color aLine( pOutputDev->GetLineColor() );
1223 // determine selection mark color
1224 Color aSelPgLineColor(117, 114, 106);
1225 const StyleSettings& rSettings =
1226 mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1227 if ( rSettings.GetHighContrastMode() )
1228 aSelPgLineColor = rSettings.GetHighlightTextColor();
1230 // set needed mapping mode at output device
1231 aMapMode.SetOrigin( _aSelectedPreviewPage->aMapOffset );
1232 pOutputDev->SetMapMode( aMapMode );
1234 // calculate page rectangle in pixel coordinates
1235 SwRect aPageRect( _aSelectedPreviewPage->aLogicPos,
1236 _aSelectedPreviewPage->aPageSize );
1237 // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1238 // page border and shadow paint - see <SwPageFrame::PaintBorderAndShadow(..)>
1239 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1240 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1242 // draw two rectangle
1243 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1244 tools::Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1245 aPxPageRect.Right(), aPxPageRect.Bottom() );
1246 aRect = pOutputDev->PixelToLogic( aRect );
1247 pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1248 pOutputDev->SetLineColor( aSelPgLineColor );
1249 pOutputDev->DrawRect( aRect );
1250 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1251 aRect = tools::Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1252 aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1253 aRect = pOutputDev->PixelToLogic( aRect );
1254 pOutputDev->DrawRect( aRect );
1256 // reset fill and line color of output device
1257 pOutputDev->SetFillColor( aFill );
1258 pOutputDev->SetLineColor( aLine );
1260 // reset mapping mode of output device
1261 pOutputDev->SetMapMode( aSavedMapMode );
1264 /** paint to mark new selected page
1266 OD 17.12.2002 #103492#
1267 Perform paint for current selected page in order to unmark it.
1268 Set new selected page and perform paint to mark this page.
1270 @note _nSelectedPage, mnSelectedPage are absolute
1272 void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1274 const sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1275 mnSelectedPageNum = _nSelectedPage;
1277 // re-paint for current selected page in order to unmark it.
1278 const PreviewPage* pOldSelectedPreviewPage = GetPreviewPageByPageNum( nOldSelectedPageNum );
1279 OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1280 if ( pOldSelectedPreviewPage && pOldSelectedPreviewPage->bVisible )
1282 // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1283 SwRect aPageRect( pOldSelectedPreviewPage->aPreviewWinPos,
1284 pOldSelectedPreviewPage->aPageSize );
1285 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1286 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1287 // invalidate top mark line
1288 tools::Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1289 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1290 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1291 // invalidate right mark line
1292 aInvalPxRect = tools::Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1293 aPxPageRect.Right(), aPxPageRect.Bottom() );
1294 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1295 // invalidate bottom mark line
1296 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1297 aPxPageRect.Right(), aPxPageRect.Bottom() );
1298 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1299 // invalidate left mark line
1300 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1301 aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1302 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1305 // re-paint for new selected page in order to mark it.
1306 const PreviewPage* pNewSelectedPreviewPage = GetPreviewPageByPageNum( _nSelectedPage );
1307 if ( pNewSelectedPreviewPage && pNewSelectedPreviewPage->bVisible )
1309 const PreviewPage* pSelectedPreviewPage = GetPreviewPageByPageNum(mnSelectedPageNum);
1310 SwRect aPageRect(pSelectedPreviewPage->aPreviewWinPos, pSelectedPreviewPage->aPageSize);
1311 ::SwAlignRect(aPageRect, &mrParentViewShell, pOutputDev);
1312 mrParentViewShell.GetWin()->Invalidate(aPageRect.SVRect());
1316 // helper methods
1318 namespace {
1320 /** get preview page by physical page number
1322 OD 17.12.2002 #103492#
1324 struct EqualsPageNumPred
1326 const sal_uInt16 mnPageNum;
1327 explicit EqualsPageNumPred(const sal_uInt16 _nPageNum)
1328 : mnPageNum( _nPageNum )
1330 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
1332 return _pPreviewPage->pPage->GetPhyPageNum() == mnPageNum;
1338 const PreviewPage* SwPagePreviewLayout::GetPreviewPageByPageNum( const sal_uInt16 _nPageNum ) const
1340 auto aFoundPreviewPageIter =
1341 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
1342 EqualsPageNumPred( _nPageNum ) );
1344 if ( aFoundPreviewPageIter == maPreviewPages.end() )
1345 return nullptr;
1347 return aFoundPreviewPageIter->get();
1350 /** determine row the page with the given number is in
1352 OD 17.01.2003 #103492#
1354 @note _nPageNum is relative
1356 sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1358 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1359 // by <mbBookPreview>.
1360 if ( mbBookPreview )
1362 // Note: increase given physical page number by one, because left-top-corner
1363 // in the preview layout is left blank.
1364 ++_nPageNum;
1367 return _nPageNum / mnCols + ((_nPageNum % mnCols)>0 ? 1 : 0);
1370 /** determine column the page with the given number is in
1372 OD 17.01.2003 #103492#
1374 @note _nPageNum is relative
1376 sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1378 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1379 // by <mbBookPreview>.
1380 if ( mbBookPreview )
1382 // Note: increase given physical page number by one, because left-top-corner
1383 // in the preview layout is left blank.
1384 ++_nPageNum;
1387 const sal_uInt16 nCol = _nPageNum % mnCols;
1388 return nCol ? nCol : mnCols;
1391 Size SwPagePreviewLayout::GetPreviewDocSize() const
1393 OSL_ENSURE( PreviewLayoutValid(), "PagePreviewLayout not valid" );
1394 return maPreviewDocRect.GetSize();
1397 /** get size of a preview page by its physical page number
1399 OD 15.01.2003 #103492#
1401 Size SwPagePreviewLayout::GetPreviewPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1403 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1404 if ( pPreviewPage )
1406 return pPreviewPage->aPageSize;
1408 return Size( 0, 0 );
1411 /** get virtual page number by its physical page number
1413 OD 21.03.2003 #108282#
1415 sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1417 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1418 if ( pPreviewPage )
1420 return pPreviewPage->pPage->GetVirtPageNum();
1422 return 0;
1425 /** Convert absolute to relative page numbers (see PrintEmptyPages) */
1426 sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1428 if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
1430 return _nAbsPageNum;
1433 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1435 sal_uInt16 nRet = 1;
1437 while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
1439 if ( !pTmpPage->IsEmptyPage() )
1440 ++nRet;
1442 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1445 return nRet;
1448 /** Convert relative to absolute page numbers (see PrintEmptyPages) */
1449 sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1451 if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
1453 return _nRelPageNum;
1456 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1457 const SwPageFrame* pRet = nullptr;
1459 sal_uInt16 i = 0;
1460 while( pTmpPage && i != _nRelPageNum )
1462 if ( !pTmpPage->IsEmptyPage() )
1463 ++i;
1465 pRet = pTmpPage;
1466 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1469 assert(pRet);
1471 return pRet->GetPhyPageNum();
1474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */